From 51c857902ad189d987f723669f0a1e34c43a92c0 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Tue, 24 Mar 2026 00:32:05 -0400 Subject: [PATCH 1/2] feat: add nginx.conf and update deploy.sh for the-nexus.alexanderwhitestone.com MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nginx.conf: HTTP→HTTPS redirect, TLS via Let's Encrypt, gzip, long-lived cache headers for hashed assets, no-cache on index.html, WebSocket proxy for /ws → localhost:8080, static-file proxy to nexus-main Docker (port 4200) - deploy.sh: git pull origin/main --hard-reset before docker rebuild/restart, nginx reload after successful deploy; documents expected VPS layout Fixes #211 Co-Authored-By: Claude Sonnet 4.6 --- deploy.sh | 31 ++++++++++++---- nginx.conf | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 nginx.conf diff --git a/deploy.sh b/deploy.sh index 76f1fd3..aee8bbf 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,7 +1,13 @@ #!/usr/bin/env bash -# deploy.sh — spin up (or update) the Nexus staging environment -# Usage: ./deploy.sh — rebuild and restart nexus-main (port 4200) -# ./deploy.sh staging — rebuild and restart nexus-staging (port 4201) +# deploy.sh — pull latest main and restart the Nexus +# +# Usage (on the VPS): +# ./deploy.sh — deploy nexus-main (port 4200) +# ./deploy.sh staging — deploy nexus-staging (port 4201) +# +# Expected layout on VPS: +# /opt/the-nexus/ ← git clone of this repo (git remote = origin, branch = main) +# nginx site config ← /etc/nginx/sites-enabled/the-nexus set -euo pipefail SERVICE="${1:-nexus-main}" @@ -11,7 +17,18 @@ case "$SERVICE" in main) SERVICE="nexus-main" ;; esac -echo "==> Deploying $SERVICE …" -docker compose build "$SERVICE" -docker compose up -d --force-recreate "$SERVICE" -echo "==> Done. Container: $SERVICE" +REPO_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "==> Pulling latest main …" +git -C "$REPO_DIR" fetch origin +git -C "$REPO_DIR" checkout main +git -C "$REPO_DIR" reset --hard origin/main + +echo "==> Building and restarting $SERVICE …" +docker compose -f "$REPO_DIR/docker-compose.yml" build "$SERVICE" +docker compose -f "$REPO_DIR/docker-compose.yml" up -d --force-recreate "$SERVICE" + +echo "==> Reloading nginx …" +nginx -t && systemctl reload nginx + +echo "==> Done. $SERVICE is live." diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..32050c7 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,103 @@ +# nginx.conf — the-nexus.alexanderwhitestone.com +# +# DNS SETUP: +# Add an A record pointing the-nexus.alexanderwhitestone.com → +# Then obtain a TLS cert with Let's Encrypt: +# certbot certonly --nginx -d the-nexus.alexanderwhitestone.com +# +# INSTALL: +# sudo cp nginx.conf /etc/nginx/sites-available/the-nexus +# sudo ln -sf /etc/nginx/sites-available/the-nexus /etc/nginx/sites-enabled/the-nexus +# sudo nginx -t && sudo systemctl reload nginx + +# ── HTTP → HTTPS redirect ──────────────────────────────────────────────────── +server { + listen 80; + listen [::]:80; + server_name the-nexus.alexanderwhitestone.com; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} + +# ── HTTPS ──────────────────────────────────────────────────────────────────── +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name the-nexus.alexanderwhitestone.com; + + # TLS — managed by Certbot; update paths if cert lives elsewhere + ssl_certificate /etc/letsencrypt/live/the-nexus.alexanderwhitestone.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/the-nexus.alexanderwhitestone.com/privkey.pem; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + # Security headers + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header X-Content-Type-Options nosniff always; + add_header X-Frame-Options SAMEORIGIN always; + add_header Referrer-Policy strict-origin-when-cross-origin always; + + # ── gzip ───────────────────────────────────────────────────────────────── + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_min_length 1024; + gzip_types + text/plain + text/css + text/javascript + application/javascript + application/json + application/wasm + image/svg+xml + font/woff + font/woff2; + + # ── WebSocket proxy (/ws) ───────────────────────────────────────────────── + # Forwards to the Hermes / presence backend running on port 8080. + # Adjust the upstream address if the WS server lives elsewhere. + location /ws { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + } + + # ── Static files — proxied to nexus-main Docker container ──────────────── + location / { + proxy_pass http://127.0.0.1:4200; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Long-lived cache for hashed/versioned assets + location ~* \.(js|css|woff2?|ttf|otf|eot|svg|ico|png|jpg|jpeg|gif|webp|avif|wasm)$ { + proxy_pass http://127.0.0.1:4200; + proxy_set_header Host $host; + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # index.html must always be revalidated + location = /index.html { + proxy_pass http://127.0.0.1:4200; + proxy_set_header Host $host; + add_header Cache-Control "no-cache, must-revalidate"; + } + } +} -- 2.43.0 From 237f2c09a4888e549faa0b8298b8dcd00aa4b6c4 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Tue, 24 Mar 2026 00:35:40 -0400 Subject: [PATCH 2/2] fix: add sudo to nginx reload in deploy.sh Refs #211 Co-Authored-By: Claude Sonnet 4.6 --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index aee8bbf..1ed2574 100755 --- a/deploy.sh +++ b/deploy.sh @@ -29,6 +29,6 @@ docker compose -f "$REPO_DIR/docker-compose.yml" build "$SERVICE" docker compose -f "$REPO_DIR/docker-compose.yml" up -d --force-recreate "$SERVICE" echo "==> Reloading nginx …" -nginx -t && systemctl reload nginx +sudo nginx -t && sudo systemctl reload nginx echo "==> Done. $SERVICE is live." -- 2.43.0