From 70dffce202a8cc1d15473bbc2750bdf29a54b0fb Mon Sep 17 00:00:00 2001 From: Void Agent Date: Thu, 22 Oct 2026 23:11:10 +0100 Subject: nginx: serve public_key to curl cleanly, restore lost security headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `curl https://jayrup.me/public_key` is the documented way to get this key onto a VPS, so both the file and the config serving it need to be exact. Key file: drop the trailing space, one trailing newline. A key with no trailing newline makes `curl ... >> ~/.ssh/authorized_keys` glue itself onto the previous line and silently break every later key in the file. nginx: - `/assets/public_key` ignored $final_suffix, so curl got 404 while browsers got 200. Route both through the suffix-aware try_files. - add_header does not merge across levels: the asset, PDF and .txt locations each declared one, so they inherited none of the security headers. The asset location now repeats them; the PDF and .txt locations no longer declare any (default_type / mime.types + charset do the job), so they inherit again. - `add_header Content-Type application/pdf` appended a second Content-Type instead of setting it. Use default_type. - `expires 30d` plus an explicit Cache-Control emitted two Cache-Control headers. Use one explicit header. - add `charset utf-8` so text/plain (what curl gets) is not served charset-less while the content contains non-ASCII. deploy: ship nginx.conf alongside public/. It is bind-mounted into the container, so it never travelled with the rsync'd tree — the live config was from May and predated the hardening committed in 0ee667a. Test with `nginx -t` before reloading and restore the previous config on failure. --- deploy.sh | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'deploy.sh') diff --git a/deploy.sh b/deploy.sh index 51159fe..306f666 100755 --- a/deploy.sh +++ b/deploy.sh @@ -11,6 +11,7 @@ set -euo pipefail # call must be pointed at $REPO explicitly. REPO="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" SHA="$(git -C "$REPO" rev-parse --short HEAD)" +DEPLOY_HOST="${DEPLOY_HOST:-jayrup.me}" # 1. Render into a fresh temp dir so a partial build never gets deployed BUILD_DIR="$(mktemp -d /tmp/homepage-local.XXXXXX)" @@ -45,14 +46,32 @@ mkdir -p public/assets cp -r assets/* public/ cp -r assets/* public/assets/ -# .txt twin: curl/wget UAs map to .txt, so `curl https://jayrup.me/public_key` -# resolves to public_key.txt. Source of truth stays assets/public_key. -cp assets/public_key public/public_key.txt +# .txt twin for curl/wget: normalize to exactly one line ending in a newline, +# so `curl https://jayrup.me/public_key >> ~/.ssh/authorized_keys` appends a +# clean key instead of gluing itself onto the previous line. +KEY="$(tr -d '\r' < assets/public_key | sed -e 's/[[:space:]]*$//' | tr -d '\n')" +[ -n "$KEY" ] || { echo "assets/public_key is empty" >&2; exit 1; } +printf '%s\n' "$KEY" > public/public_key.txt # 6. Deploy marker printf 'deployed %s commit %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$SHA" > public/last-deploy.txt echo "Pushing to vps" -# Only reached if all renders succeeded (set -e) -rsync -avz --delete public/ jayrup.me:~/homepage/public/ +# 7. Content. Only reached if all renders succeeded (set -e) +rsync -avz --delete public/ "$DEPLOY_HOST":~/homepage/public/ + +# 8. nginx config. It is bind-mounted into the container, so it does not travel +# with public/. Test it before reloading: a bad file must not take down the +# running workers, so restore the previous one and fail loudly instead. +echo "Pushing nginx.conf" +ssh "$DEPLOY_HOST" 'cp -a ~/homepage/nginx.conf ~/homepage/nginx.conf.prev' +rsync -avz nginx.conf "$DEPLOY_HOST":~/homepage/nginx.conf +if ssh "$DEPLOY_HOST" 'docker exec homepage nginx -t'; then + ssh "$DEPLOY_HOST" 'docker exec homepage nginx -s reload' + echo "nginx reloaded" +else + echo "!! nginx config failed its test - restoring previous config" >&2 + ssh "$DEPLOY_HOST" 'mv ~/homepage/nginx.conf.prev ~/homepage/nginx.conf' + exit 1 +fi -- cgit v1.2.3