jb-website/Caddyfile
Josh Bairstow 7ecd1b32ae feat(deploy): self-hosted CI/CD + dedicated edge-proxy topology
Refactor the site container from a TLS-owning, port-binding proxy into an
internal plaintext static server that sits behind a dedicated edge reverse
proxy, and add an automated build/deploy pipeline.

- Caddyfile: single :80 listener (auto_https off), Host-matcher routing for
  apex/blog/art/code with /_astro+/assets re-root and www->apex redirect
- Dockerfile: EXPOSE 80 only (TLS now handled by the edge proxy)
- compose.yml: pull registry image, join external 'edge' network, declare
  routing via caddy-docker-proxy labels; drop build/ports/cert volumes
- compose.dev.yml: local container preview on :8080
- .forgejo/workflows/deploy.yml: push-to-main -> desktop runner builds, pushes
  to the Forgejo registry, SSH-deploys to the VPS
- docs + .dockerignore updated for the new topology

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:31:16 +10:00

99 lines
3 KiB
Caddyfile

# ----------------------------------------------------------------------------
# jb-website — INTERNAL static server (behind the edge reverse proxy).
#
# This Caddy no longer terminates TLS or owns 80/443. The edge proxy
# (caddy-docker-proxy, see the infra repo) terminates HTTPS for every host and
# reverse-proxies plaintext to this container on :80, preserving the original
# Host header. We branch on that Host header to serve the right slice of the
# single static build:
#
# joshbairstow.com / www. -> /srv (apex / home)
# blog.joshbairstow.com -> /srv/blog (writing archive + posts)
# art.joshbairstow.com -> /srv/art (generative art focus view)
# code.joshbairstow.com -> /srv/code (experiments & tools)
#
# Shared build assets (/_astro/*, /assets/*) live at the apex root, so the
# subdomain handlers re-root those paths back to /srv.
#
# One bare `:80` listener + host matchers (NOT named-host site blocks) keeps
# this purely plaintext: named-host blocks would re-trigger Caddy's automatic
# HTTPS, which the edge proxy already handles. Local preview is provided by
# compose.dev.yml mapping a host port to this :80.
# ----------------------------------------------------------------------------
{
# Edge proxy owns TLS; this server is plaintext-only and has no admin needs.
auto_https off
admin off
}
:80 {
encode zstd gzip
# ---- www -> apex redirect ----------------------------------------------
# The upstream only ever sees http, so the scheme is hardcoded https.
@www host www.joshbairstow.com
redir @www https://joshbairstow.com{uri} permanent
# ---- apex --------------------------------------------------------------
@apex host joshbairstow.com
handle @apex {
root * /srv
try_files {path} {path}/index.html /404.html
file_server
}
# ---- blog --------------------------------------------------------------
@blog host blog.joshbairstow.com
handle @blog {
@asset path /_astro/* /assets/*
handle @asset {
root * /srv
file_server
}
handle {
root * /srv/blog
try_files {path} {path}/index.html /srv/404.html
file_server
}
}
# ---- art ---------------------------------------------------------------
@art host art.joshbairstow.com
handle @art {
@asset path /_astro/* /assets/*
handle @asset {
root * /srv
file_server
}
handle {
root * /srv/art
try_files {path} {path}/index.html /srv/404.html
file_server
}
}
# ---- code --------------------------------------------------------------
@code host code.joshbairstow.com
handle @code {
@asset path /_astro/* /assets/*
handle @asset {
root * /srv
file_server
}
handle {
root * /srv/code
try_files {path} {path}/index.html /srv/404.html
file_server
}
}
# ---- fallback ----------------------------------------------------------
# Any other Host (e.g. hitting the container directly, or local preview at
# localhost:8080) serves the apex build so the site is never blank.
handle {
root * /srv
try_files {path} {path}/index.html /404.html
file_server
}
}