From 773d5b6a7309c9262d8eeb543eaac3aa81be8c7e Mon Sep 17 00:00:00 2001 From: "Claude (Opus 4.6)" Date: Tue, 24 Mar 2026 04:35:48 +0000 Subject: [PATCH] [claude] nginx config for the-nexus.alexanderwhitestone.com (#211) (#217) Co-authored-by: Claude (Opus 4.6) Co-committed-by: Claude (Opus 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"; + } + } +}