The recommendation: let Gitea own the repository and build process, but keep the public site as plain static files served by Caddy. Do not turn Gitea into the web server.
why this shape fits
The current site is already easy to host: it is static HTML, CSS, images, video, and one small JavaScript project. The homelab already runs Docker Compose, Caddy, and a Cloudflare Tunnel on coconut. The migration can use that base instead of adding another public web stack.
Gitea should handle Git, review, and automation. A separate runner should turn each accepted commit into a release. Caddy should only read the selected release and serve it.
first: move Git without moving the site
- Create the repository on Gitea and copy every branch and tag from GitHub.
- Add Gitea as a second local remote and compare both histories.
- Protect
mainand enable repository Actions. - Leave GitHub Pages live until the new path has passed the same checks.
- After cutover, keep GitHub as a read-only push mirror and backup of Git history.
then: deploy immutable releases
Store each build under /srv/www/temphtml/releases/<commit> on coconut. Point /srv/www/temphtml/current at the active release and mount the parent directory read-only inside Caddy.
A deployment uploads a complete new directory, tests it, and switches current only after every check passes. A failed build never changes the live site. Keep the five newest releases so rollback is a single symlink change.
make the runner prove the build
- Parse every HTML file and check CSS syntax.
- Validate internal links, asset paths, 640×400 thumbnails, and 80-character summaries.
- Test the homepage and changed pages at desktop and 390-pixel widths.
- Write a public
build.jsonwith the exact commit SHA. - Deploy through a restricted SSH account that can write only to the temphtml release directory.
- Confirm that the public
build.jsonmatches Giteamain.
Run the repository-scoped Gitea runner on a trusted machine separate from the Gitea server when practical. Do not give the job direct control of coconut's Docker socket.
reduce manual page work later
Do not combine the hosting cutover with a site rewrite. Once the new deployment path is stable, move writeups to Markdown with front matter and let a small static generator build the homepage rows automatically.
Hugo is a good fit because it is a mature single binary. The existing Coconut-derived CSS can stay unchanged, and standalone projects such as Stardoku can remain passthrough static directories. Old HTML pages can be migrated one at a time.
back up what cannot be rebuilt
The published site can always be rebuilt from Git. The Gitea database, repositories, configuration, attachments, and secrets need separate off-host backups. Keep the GitHub mirror, copy Gitea backups away from coconut, and test a restore on a schedule.
Monitor the public homepage, one representative asset, and build.json. An alert should fire when the site is unavailable or the deployed SHA differs from Gitea main.
cut over without a cliff
- Bring up
temphtml.mhny.devbeside the GitHub Pages site. - Compare every current route and run desktop and mobile visual checks.
- Switch links to the new hostname only after parity is confirmed.
- Keep GitHub Pages available for two to four weeks.
- Retain GitHub as a mirror or replace the old Pages site with redirects.
done means
A push to Gitea main publishes the exact tested commit. Failed checks leave the old release online. Rollback takes one command. No secret enters Git history. The site works without GitHub, and Gitea can be restored from an off-host backup.