cinny: version-control the production nginx site config
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 50s
Lint / Secret scan (gitleaks) (push) Successful in 9s

The chat.lotusguild.org nginx config (LXC 106) was edited directly on the box
and never tracked — which is how its CSP drifted (kept a dead Sentry URL and
blocked matrix.org logins). Snapshot it as cinny/nginx.conf (verbatim from prod,
incl. the corrected connect-src that now allows matrix.org/*.matrix.org) and
deploy it via lxc106-cinny.sh: back up the live file, swap, `nginx -t`, and
reload only on success (auto-restore the backup if validation fails, so a bad
config can't take the site down). TLS terminates at the NPM proxy, so this is a
plain HTTP server block with no secrets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 13:14:49 -04:00
parent 45444e5118
commit 40ceb43672
2 changed files with 100 additions and 3 deletions
+79
View File
@@ -0,0 +1,79 @@
server {
listen 80;
listen [::]:80;
server_name chat.lotusguild.org;
# Brotli compression (better than gzip for modern browsers)
brotli on;
brotli_static on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json
image/svg+xml application/wasm font/woff2;
root /var/www/html;
server_tokens off;
client_max_body_size 50m;
limit_req zone=chat_limit burst=60 nodelay;
limit_conn chat_conn 25;
index index.html;
# Security headers
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
# Block all source map files and dotfiles from public access
location ~* \.(js|css)\.map$ {
deny all;
return 404;
}
location ~ /\. {
deny all;
return 404;
}
location = /netlify.toml {
deny all;
return 404;
}
# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://matrix.lotusguild.org https://drive.lotusguild.org https://media.giphy.com https://media0.giphy.com https://media1.giphy.com https://media2.giphy.com https://media3.giphy.com https://media4.giphy.com https://www.openstreetmap.org https://tile.openstreetmap.org https://api.qrserver.com; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://matrix.lotusguild.org wss://matrix.lotusguild.org https://matrix.org https://*.matrix.org https://api.giphy.com https://*.giphy.com wss:; media-src 'self' https: blob:; frame-src 'self' https://www.openstreetmap.org; worker-src 'self' blob:; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
# Service worker must never be cached so updates are picked up immediately
location = /sw.js {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
# Cache content-addressed static assets aggressively
location ~* \.(?:js|css|woff2?|png|svg|ico|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable" always;
}
# Never cache HTML or JSON (index.html, config.json, manifest.json)
location ~* \.(json|html)$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
# Auto-deploy webhook — proxied to local webhook service
location = /hooks/lotus-deploy {
proxy_pass http://127.0.0.1:9001/hooks/lotus-deploy;
proxy_set_header Host $host;
proxy_read_timeout 300;
proxy_connect_timeout 5;
}
location / {
rewrite ^/config\.json$ /config.json break;
rewrite ^/manifest\.json$ /manifest.json break;
rewrite ^/sw\.js$ /sw.js break;
rewrite ^/pdf\.worker\.min\.js$ /pdf.worker.min.js break;
rewrite ^/public/(.*)$ /public/$1 break;
rewrite ^/assets/(.*)$ /assets/$1 break;
rewrite ^(.+)$ /index.html break;
}
}
+21 -3
View File
@@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
# Auto-deploy script for LXC 106 (cinny) # Auto-deploy script for LXC 106 (cinny)
# Handles: cinny/config.json, cinny/upstream-check.sh, cinny/lotus-build.sh, # Handles: cinny/config.json, cinny/nginx.conf, cinny/upstream-check.sh,
# deploy/hooks-lxc106.json, systemd/cinny-upstream-check.cron # cinny/lotus-build.sh, deploy/hooks-lxc106.json,
# systemd/cinny-upstream-check.cron
# Triggered by: Gitea webhook on push to main # Triggered by: Gitea webhook on push to main
set -euo pipefail set -euo pipefail
@@ -14,7 +15,7 @@ echo "=== $(date) === LXC106 deploy triggered ==="
if [ ! -d "$REPO_DIR/.git" ]; then if [ ! -d "$REPO_DIR/.git" ]; then
git clone "$CLONE_URL" "$REPO_DIR" git clone "$CLONE_URL" "$REPO_DIR"
CHANGED="cinny/config.json cinny/upstream-check.sh cinny/lotus-build.sh deploy/hooks-lxc106.json systemd/cinny-upstream-check.cron" CHANGED="cinny/config.json cinny/nginx.conf cinny/upstream-check.sh cinny/lotus-build.sh deploy/hooks-lxc106.json systemd/cinny-upstream-check.cron"
else else
cd "$REPO_DIR" cd "$REPO_DIR"
git fetch --all git fetch --all
@@ -31,6 +32,23 @@ if echo "$CHANGED" | grep -q '^cinny/config.json'; then
echo "✓ config.json deployed" echo "✓ config.json deployed"
fi fi
if echo "$CHANGED" | grep -q '^cinny/nginx.conf'; then
echo "Deploying cinny nginx site config..."
# Back up the live config, swap in the repo copy, and validate before
# reloading. If `nginx -t` fails, restore the backup and skip the reload so
# a bad config can never take the site down.
BACKUP="/etc/nginx/sites-available/cinny.bak-$(date +%Y%m%d%H%M%S)"
cp /etc/nginx/sites-available/cinny "$BACKUP"
cp "$REPO_DIR/cinny/nginx.conf" /etc/nginx/sites-available/cinny
if nginx -t; then
systemctl reload nginx
echo "✓ nginx site config deployed + reloaded"
else
echo "✗ nginx -t FAILED — restoring previous config, skipping reload"
cp "$BACKUP" /etc/nginx/sites-available/cinny
fi
fi
if echo "$CHANGED" | grep -q '^cinny/upstream-check.sh'; then if echo "$CHANGED" | grep -q '^cinny/upstream-check.sh'; then
echo "Deploying upstream-check.sh..." echo "Deploying upstream-check.sh..."
cp "$REPO_DIR/cinny/upstream-check.sh" /usr/local/bin/cinny-upstream-check.sh cp "$REPO_DIR/cinny/upstream-check.sh" /usr/local/bin/cinny-upstream-check.sh