5.1 KiB
Deployment Handover
How the migrated Hugo site is served, and how to adjust the server-side deploy workflow (Gitea Actions + webhook) for the new two-stage build.
Serving topology (unchanged)
The site is served as before. The host's system nginx (Certbot-managed TLS at djosen.one) proxies location / → 127.0.0.1:8080, where the Docker web container listens. Nothing changed in the system nginx (nginx/system-default.conf / nginx/reverse.conf) or the Certbot/DNS setup during this migration.
What changed is what's inside the container: instead of a Vite SPA (a single index.html plus JavaScript), the container now serves a Hugo static site — public/ with one real .html page per path.
What changed in the build
The build is now two steps:
- Engine —
gpu-bg/Vite/Typescript build → a static JS bundle (gpu-bg/dist/). - Site —
hugo --minify→public/.
The Dockerfile runs both in stages (node → hugo → nginx).
Key details for the server build:
- Hugo image: the
sitestage useshugomods/hugo:debian-dart-sass-go-0.165.0— an extended Hugo build including dart-sass. This is required because hugo-coder compiles the theme's SCSS via Hugo Pipes (toCSS), and Hugo 0.129+ dropped libsass in favor of dart-sass. This replaced the deprecatedklakegg/hugoimage. - Theme submodule: hugo-coder lives as a git submodule at
themes/hugo-coder. - Static serving only: the container nginx no longer does SPA fallback (
try_files ... /index.html). It serves plain static files — each page is a real.html, and a 404 for a missing path is legitimate and intentional.
Mandatory server-side change (the #1 gotcha)
Your clone/checkout must initialize submodules before building. The themes/hugo-coder submodule must be pulled in before docker build; otherwise hugo fails with theme not found and the build breaks.
-
Gitea Actions
deploy.yml: make the checkout recursive. Withactions/checkout, set:- uses: actions/checkout@v3 with: submodules: recursive -
Plain webhook / shell: use a recursive clone, or run the update before building:
git clone --recursive ... # or, on an existing clone: git pull git submodule update --init --recursive
Nothing else changes server-side: registry credentials, the SSH/webhook target, and the docker compose up -d deploy command are all the same. The image is slightly larger to build (node and Hugo-extended layers are discarded; the final nginx stage stays small).
Testing
Local (before pushing)
git submodule update --init --recursive
cd gpu-bg && npm install && npm run build && cd ..
hugo # builds public/
docker compose build # 3-stage build
docker compose up -d # maps 127.0.0.1:8080:8080
Smoke test (after up -d)
curl -sf http://127.0.0.1:8080/ | grep -q 'id="gpu"' && echo "canvas OK"
curl -sf http://127.0.0.1:8080/gpu/engine.js -o /dev/null && echo "engine bundle OK"
curl -sf http://127.0.0.1:8080/about/ -o /dev/null && echo "about OK"
curl -sf http://127.0.0.1:8080/projects/ -o /dev/null && echo "projects OK"
curl -sf http://127.0.0.1:8080/resume/ -o /dev/null && echo "resume OK"
curl -sf http://127.0.0.1:8080/posts/ -o /dev/null && echo "posts OK"
curl -s http://127.0.0.1:8080/nonexistent -o /dev/null -w "%{http_code}\n" # expect 404
Browser check (manual — WebGPU is a real-GPU feature)
- Homepage: emerald spiral animates behind the dark glass panel; text readable.
- With WebGPU disabled, the WebGL2 fallback still animates.
- With no WebGL at all, the page still shows its content; the canvas simply doesn't render.
After deploy (remote)
curl -s https://djosen.one/health→ok(system nginx health endpoint, unchanged).- Verify
/,/about/,/projects/,/resume/,/posts/over HTTPS. - Confirm the spiral actually renders in a real browser — the one thing
curlcannot check.
Troubleshooting
Deploy status stuck/red on Gitea after a migration or restart
If the Actions/deploy status shows broken or stops updating (commits push but no
run is registered), the per-repo git hooks may be stale or missing. Fix by
resynchronizing hooks from the Gitea admin CLI (this regenerates
pre-receive, update, post-receive and their .d/gitea delegates):
docker exec -u git gitea gitea admin regenerate hooks
For the full documented recovery, the Gitea FAQ steps are: "Sync missed branches from git data to databases", "Sync tags from git data to database", and "Resynchronize pre-receive, update and post-receive hooks of all repositories" (the last one is what the command above does). After regenerating, push a commit to refresh the status.
Rollback
The previous site is preserved in the git tag pre-hugo and the archive/ folder. To roll back: git checkout pre-hugo and redeploy with the old single-stage Dockerfile (also recoverable from git history).
No system nginx or DNS changes were made in this migration, so rollback is purely a container-image swap.