← back to Dead Agentabrams
add source-hosted Dead listening experience
8d68829b5a31cc1fa43a55f781b8c00f0ccbb291 · 2026-09-01 13:30:34 -0700 · Steve Abrams
Files touched
A deploy/dead.agentabrams.com.nginxA deploy/dead.agentabrams.com.ssl.nginxA deploy/deploy.shM index.html
Diff
commit 8d68829b5a31cc1fa43a55f781b8c00f0ccbb291
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 1 13:30:34 2026 -0700
add source-hosted Dead listening experience
---
deploy/dead.agentabrams.com.nginx | 9 +++++++++
deploy/dead.agentabrams.com.ssl.nginx | 21 +++++++++++++++++++++
deploy/deploy.sh | 33 +++++++++++++++++++++++++++++++++
index.html | 2 +-
4 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/deploy/dead.agentabrams.com.nginx b/deploy/dead.agentabrams.com.nginx
new file mode 100644
index 0000000..4336888
--- /dev/null
+++ b/deploy/dead.agentabrams.com.nginx
@@ -0,0 +1,9 @@
+server {
+ listen 80;
+ listen [::]:80;
+ server_name dead.agentabrams.com;
+ root /var/www/dead.agentabrams.com;
+ index index.html;
+ location / { try_files $uri $uri/ =404; }
+}
+
diff --git a/deploy/dead.agentabrams.com.ssl.nginx b/deploy/dead.agentabrams.com.ssl.nginx
new file mode 100644
index 0000000..41dd5b2
--- /dev/null
+++ b/deploy/dead.agentabrams.com.ssl.nginx
@@ -0,0 +1,21 @@
+server {
+ listen 80;
+ listen [::]:80;
+ server_name dead.agentabrams.com;
+ return 301 https://$host$request_uri;
+}
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name dead.agentabrams.com;
+ root /var/www/dead.agentabrams.com;
+ index index.html;
+ ssl_certificate /etc/letsencrypt/live/dead.agentabrams.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/dead.agentabrams.com/privkey.pem;
+ include /etc/letsencrypt/options-ssl-nginx.conf;
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+ add_header X-Content-Type-Options nosniff always;
+ add_header Referrer-Policy strict-origin-when-cross-origin always;
+ location / { try_files $uri $uri/ =404; }
+}
+
diff --git a/deploy/deploy.sh b/deploy/deploy.sh
new file mode 100755
index 0000000..b200438
--- /dev/null
+++ b/deploy/deploy.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -euo pipefail
+KAMATERA=root@45.61.58.125
+SITE=dead.agentabrams.com
+HERE="$(cd "$(dirname "$0")/.." && pwd)"
+
+export $(grep -E '^CLOUDFLARE_API_TOKEN=' ~/Projects/secrets-manager/.env)
+ZONE=$(curl -s -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" "https://api.cloudflare.com/client/v4/zones?name=agentabrams.com" | python3 -c "import sys,json; print(json.load(sys.stdin)['result'][0]['id'])")
+EXISTS=$(curl -s -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records?name=$SITE" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['result']))")
+if [ "$EXISTS" = "0" ]; then
+ curl -s -X POST -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H 'Content-Type: application/json' "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records" -d '{"type":"A","name":"dead","content":"45.61.58.125","ttl":300,"proxied":false}' | python3 -c "import sys,json; r=json.load(sys.stdin); assert r['success'],r['errors']; print('DNS record created')"
+else
+ echo 'DNS record already exists'
+fi
+
+rsync -az --delete --exclude .git --exclude deploy --exclude README.md --exclude verification "$HERE/" "$KAMATERA:/var/www/$SITE/"
+CERT="/etc/letsencrypt/live/$SITE/fullchain.pem"
+if ssh "$KAMATERA" "test -f $CERT"; then
+ scp -q "$HERE/deploy/$SITE.ssl.nginx" "$KAMATERA:/etc/nginx/sites-available/$SITE"
+ ssh "$KAMATERA" "ln -sf /etc/nginx/sites-available/$SITE /etc/nginx/sites-enabled/$SITE && nginx -t && systemctl reload nginx"
+else
+ scp -q "$HERE/deploy/$SITE.nginx" "$KAMATERA:/etc/nginx/sites-available/$SITE"
+ ssh "$KAMATERA" "ln -sf /etc/nginx/sites-available/$SITE /etc/nginx/sites-enabled/$SITE && nginx -t && systemctl reload nginx"
+ for _ in $(seq 1 30); do [ -n "$(dig +short "$SITE" @1.1.1.1)" ] && break; sleep 10; done
+ ssh "$KAMATERA" "certbot certonly --webroot -w /var/www/$SITE -d $SITE --non-interactive --agree-tos -m steve@designerwallcoverings.com"
+ scp -q "$HERE/deploy/$SITE.ssl.nginx" "$KAMATERA:/etc/nginx/sites-available/$SITE"
+ ssh "$KAMATERA" "nginx -t && systemctl reload nginx"
+fi
+sleep 2
+code=$(curl -s -o /dev/null -w '%{http_code}' "https://$SITE/")
+echo "https://$SITE -> HTTP $code"
+[ "$code" = '200' ] && echo 'DEPLOY OK' || exit 1
+
diff --git a/index.html b/index.html
index 6b92f76..b16472e 100644
--- a/index.html
+++ b/index.html
@@ -53,7 +53,7 @@ function selectShow(i){current=i;const s=shows[i];renderShows();$('#stageDate').
$('#shows').addEventListener('click',e=>{const b=e.target.closest('[data-i]');if(b)selectShow(Number(b.dataset.i));});
$('#listenBtn').addEventListener('click',()=>{const s=shows[current];$('#player').src='https://archive.org/embed/'+s.id;$('#frameWrap').classList.add('on');$('#listenBtn').hidden=true;});
function renderRooms(){let list=rooms.slice();const sort=$('#sort').value;if(sort==='title')list.sort((a,b)=>a.title.localeCompare(b.title));if(sort==='era')list.sort((a,b)=>a.era-b.era);$('#builds').innerHTML=list.map(r=>`<a class="build" href="https://gallery.agentabrams.com/#${r.id}" target="_blank" rel="noopener"><div class="visual" style="background-image:url('${r.img}')"></div><div class="copy"><span class="n">ROOM ${r.n}</span><h3>${r.title}</h3><p>${r.desc}</p><span class="go">Enter exhibition ↗</span></div></a>`).join('');}
-const savedShow=Number(localStorage.getItem('dead:selected-show'));if(Number.isInteger(savedShow)&&savedShow>=0&&savedShow<shows.length)current=savedShow;
+const savedShowRaw=localStorage.getItem('dead:selected-show');const savedShow=savedShowRaw===null?NaN:Number(savedShowRaw);if(Number.isInteger(savedShow)&&savedShow>=0&&savedShow<shows.length)current=savedShow;
const savedSort=localStorage.getItem('dead:sort');if(savedSort)$('#sort').value=savedSort;const savedDensity=localStorage.getItem('dead:density');if(savedDensity){$('#density').value=savedDensity;document.documentElement.style.setProperty('--cols',savedDensity)}
$('#sort').addEventListener('change',()=>{localStorage.setItem('dead:sort',$('#sort').value);renderRooms()});$('#density').addEventListener('input',()=>{const v=$('#density').value;document.documentElement.style.setProperty('--cols',v);localStorage.setItem('dead:density',v)});
selectShow(current);renderRooms();
← 80a57f8 initial Dead listening exhibition
·
back to Dead Agentabrams
·
ship and verify dead.agentabrams.com 3a0a387 →