No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Paul Provost e12392f0e8 Initial static-sites role: Caddy serving static sites by Host header
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:00:15 -04:00
defaults Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00
handlers Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00
meta Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00
tasks Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00
templates Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00
README.md Initial static-sites role: Caddy serving static sites by Host header 2026-10-18 20:00:15 -04:00

static-sites

Serve static sites, such as Hugo builds, from one Caddy container via Docker Compose. Sites are picked by the request's Host header, so any number of domains and subdomains share one plain-HTTP port behind a TLS-terminating reverse proxy.

Requirements

  • Docker with the compose plugin already installed (e.g. via geerlingguy.docker).
  • community.docker collection (needs the python3-docker apt package's bindings - this role installs it).

Role Variables

Variable Default Description
static_sites [] (required) Sites: {name, root, aliases?}; root is a directory under static_sites_root.
static_sites_image caddy:2 Caddy image.
static_sites_memory 128m Container memory limit.
static_sites_bind_address 0.0.0.0 Host address the port is published on.
static_sites_port 8090 Host port mapped to Caddy's :80.
static_sites_base_dir ~/local/static-sites Compose file and etc/Caddyfile.
static_sites_root ~/local/sites Site content, one subdirectory per site, mounted read-only at /srv.
static_sites_restart_policy unless-stopped Compose restart policy.

Tags

  • config, container, verify - the usual run.
  • upgrade - pull the image and recreate.

Example Playbook

- hosts: razorback
  vars:
    ansible_python_interpreter: /usr/bin/python3
    static_sites:
      - { name: brain2.home.provost.one, root: brain2 }
  roles:
    - role: static-sites

Notes

  • The role only creates each site's directory (owned by the connecting user); content is deployed separately, e.g. rsync -az --delete public/ host:local/sites/brain2/. Caddy picks up new files immediately, so a deploy needs no restart.
  • Missing pages are answered with the site's /404.html (Hugo generates one) and a 404 status. Unknown hosts get a bare 404.
  • Caddyfile changes are validated, then hot-reloaded; a config that fails validation never reaches the running server.
  • No TLS here: put a reverse proxy in front that passes the Host header through (Caddy's reverse_proxy does by default).