diff options
| author | Void Agent <void@jayrup.hermes> | 2026-10-22 23:12:30 +0100 |
|---|---|---|
| committer | Void Agent <void@jayrup.hermes> | 2026-10-22 23:12:30 +0100 |
| commit | 1e58fcb98fd17dbec3a2b477d3737b83101a18b5 (patch) | |
| tree | 000c68ffa8cb69807b2f922f21d05704becbeddc | |
| parent | 70dffce202a8cc1d15473bbc2750bdf29a54b0fb (diff) | |
deploy: write nginx.conf in place so the container's bind mount sees it
nginx.conf is mounted as a single file. rsync renames a temp over the
destination, which replaces the inode, so the container kept reading the old
inode: nginx -t validated the old bytes, reload was a no-op, and the deploy
reported success while the live config was unchanged. Stage to
nginx.conf.new, copy in place with cat so the mounted inode keeps its
identity, then test and reload. Rollback copies in place too, for the same
reason.
| -rwxr-xr-x | deploy-docker.sh | 14 | ||||
| -rwxr-xr-x | deploy.sh | 16 |
2 files changed, 20 insertions, 10 deletions
diff --git a/deploy-docker.sh b/deploy-docker.sh index 716bb8d..12d4a54 100755 --- a/deploy-docker.sh +++ b/deploy-docker.sh @@ -70,18 +70,22 @@ printf 'deployed %s commit %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$SHORT_SHA" > echo ">> pushing to $DEPLOY_HOST" rsync -avz --delete public/ "$DEPLOY_HOST":~/homepage/public/ -# nginx config is bind-mounted into the container, so it does not travel with -# public/. Test before reloading: a bad file must not take down the running -# workers, so restore the previous one and fail loudly instead. +# nginx config is bind-mounted into the container as a SINGLE FILE, so rsync's +# rename-into-place would swap the inode the mount points at and the container +# would keep reading the old file while `nginx -t` validated the old bytes. +# Stage to a sidecar, copy in place so the mounted inode keeps its identity, +# test, and only then reload; restore the previous content on failure. echo ">> pushing nginx.conf" +rsync -avz nginx.conf "$DEPLOY_HOST":~/homepage/nginx.conf.new ssh "$DEPLOY_HOST" 'cp -a ~/homepage/nginx.conf ~/homepage/nginx.conf.prev' -rsync -avz nginx.conf "$DEPLOY_HOST":~/homepage/nginx.conf +ssh "$DEPLOY_HOST" 'cat ~/homepage/nginx.conf.new > ~/homepage/nginx.conf' if ssh "$DEPLOY_HOST" 'docker exec homepage nginx -t'; then ssh "$DEPLOY_HOST" 'docker exec homepage nginx -s reload' + ssh "$DEPLOY_HOST" 'rm -f ~/homepage/nginx.conf.new' 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' + ssh "$DEPLOY_HOST" 'cat ~/homepage/nginx.conf.prev > ~/homepage/nginx.conf' exit 1 fi @@ -61,17 +61,23 @@ echo "Pushing to vps" # 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. +# 8. nginx config. It is bind-mounted into the container as a SINGLE FILE, so +# it does not travel with public/, and rsync's rename-into-place would swap +# the inode the mount points at: the container would keep reading the old +# inode while `nginx -t` cheerfully validated it. Stage to a sidecar, then +# copy in place (cat >) so the mounted inode keeps its identity. +# Test before reloading; on failure restore the previous content the same +# way and fail loudly instead of taking the running workers down. echo "Pushing nginx.conf" +rsync -avz nginx.conf "$DEPLOY_HOST":~/homepage/nginx.conf.new ssh "$DEPLOY_HOST" 'cp -a ~/homepage/nginx.conf ~/homepage/nginx.conf.prev' -rsync -avz nginx.conf "$DEPLOY_HOST":~/homepage/nginx.conf +ssh "$DEPLOY_HOST" 'cat ~/homepage/nginx.conf.new > ~/homepage/nginx.conf' if ssh "$DEPLOY_HOST" 'docker exec homepage nginx -t'; then ssh "$DEPLOY_HOST" 'docker exec homepage nginx -s reload' + ssh "$DEPLOY_HOST" 'rm -f ~/homepage/nginx.conf.new' 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' + ssh "$DEPLOY_HOST" 'cat ~/homepage/nginx.conf.prev > ~/homepage/nginx.conf' exit 1 fi |
