Copying new files directly over a live static directory creates a period where visitors can receive HTML from one release and assets from another. A safer pattern stages one complete tree beside the live tree, verifies it, then changes directory names.
Keep all release directories on one filesystem
Name replacement is strongest when the live tree, staged tree, and rollback tree share the same filesystem and parent directory. Check first:
df -P /srv/www
Create a uniquely named stage directory under that parent. Do not reuse an unresolved variable or broad wildcard as a deletion target.
stage=$(mktemp -d /srv/www/site.new.XXXXXX)
Populate and verify the stage
Copy the generated artifact into the empty directory, then check representative files and the expected file count:
tar -C public -cf - . | tar -C "$stage" -xf -
test -s "$stage/index.html"
test -s "$stage/404.html"
find "$stage" -type f | wc -l
Run link and checksum checks against the staged path when the tooling supports a directory argument. A stage that has not passed verification must never acquire the live name.
Switch names with an explicit rollback path
Resolve every path before the first move:
live=/srv/www/site
stamp=$(date -u +%Y%m%dT%H%M%SZ)
rollback=/srv/www/site.old-$stamp
test -d "$live"
test -d "$stage"
test ! -e "$rollback"
mv "$live" "$rollback"
if mv "$stage" "$live"; then
test -s "$live/index.html"
else
mv "$rollback" "$live"
exit 1
fi
This sequence leaves a short interval between the two moves. For a single static-server process that resolves the root on each request, the interval is usually small but still observable. Platform-specific rename or symlink patterns can tighten the switch; test the exact filesystem and server behavior before relying on stronger claims.
Verify the public edge
After the switch, request the homepage, one deep route, one fingerprinted asset, and a missing path. Compare public bytes with the staged artifact. Keep the rollback directory until that check and the observation window complete.
Sources
- POSIX
rename(), name replacement semantics, checked 2026-08-23. - Linux
rename(2), filesystem and replacement behavior, checked 2026-08-23. - GNU tar manual, archive creation and extraction, checked 2026-08-23.