Skip to content

feat(caddy): cert-getter addendum for pronode.prosopo.io#2734

Merged
forgetso merged 2 commits into
mainfrom
feat/caddy-pronode-global-cert-getter
Jun 18, 2026
Merged

feat(caddy): cert-getter addendum for pronode.prosopo.io#2734
forgetso merged 2 commits into
mainfrom
feat/caddy-pronode-global-cert-getter

Conversation

@forgetso

Copy link
Copy Markdown
Member

Summary

  • Extracts the existing route/handler block in docker/provider.Caddyfile into a (provider_site) snippet imported by the per-host site (same shape as feat(caddy): respond to load-balanced pronode.prosopo.io alongside per-host #2670).
  • Adds docker/provider.cert-getter.Caddyfile as a deploy-time addendum that ansible concatenates onto the base file on hosts flagged cert_getter: true in the inventory. The addendum defines a second site block on :8443 for the load-balanced pronode.prosopo.io hostname.
  • TLS for the global hostname uses a PEM at /certs/pronode-global/{fullchain,privkey}.pem. The PEM is provisioned out of band by certbot via Bunny DNS-01 — installed and renewed by a sibling ansible playbook in the captcha-private repo (see companion PR there).

Why this PR

#2670 left the global hostname TLS strategy as a tls internal placeholder and called the real cert distribution mechanism a follow-up. This is that follow-up for the cert-getter side: one node (pronode4) owns ACME for pronode.prosopo.io against Bunny DNS, terminates TLS for it, and the addendum lives only on that node. Distribution of the PEM to the other 13 pronodes is a manual ansible step done out of band.

Test plan

  • On pronode4 (the cert getter): openssl s_client -connect <ip>:443 -servername pronode.prosopo.io returns a Let's Encrypt cert with CN=pronode.prosopo.io.
  • On pronode4: openssl s_client -connect <ip>:443 -servername pronode4.prosopo.io still returns the original per-host LE cert (no regression).
  • On pronode4: curl -sS -o /dev/null -w '%{http_code} %{ssl_verify_result}' https://pronode.prosopo.io/healthz returns 200 0.
  • On a non-cert-getter pronode: deploying the base provider.Caddyfile (without the addendum) still loads cleanly and serves the per-host hostname (snippet extraction is the only base-file change; behaviour-equivalent).

🤖 Generated with Claude Code

Extracts the existing route/handler block in docker/provider.Caddyfile
into a (provider_site) snippet imported by the per-host site, then adds
docker/provider.cert-getter.Caddyfile as a deploy-time addendum that
ansible concatenates onto the base file on hosts flagged as the cert
getter (currently pronode4). The addendum defines a second site block
for the load-balanced pronode.prosopo.io hostname that reads a PEM
provisioned out of band by certbot via Bunny DNS-01.

Follows the snippet-extraction approach from #2670; the live PEM is
distributed by ansible (see the captcha-private companion PR).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `./certs/pronode-global:/certs/pronode-global:ro` to the caddy
service in docker-compose.provider.yml. The mount source is created
and populated by ansible (provider.yml distributes the PEM from the
cert getter to every pronode), and the path inside the container
matches the `tls /certs/pronode-global/...` line in
provider.cert-getter.Caddyfile.

A previous attempt added this mount and got silently stripped (likely
an editor format-on-save). Re-adding with a comment so it's clear it
must stay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@forgetso forgetso merged commit bcd15e5 into main Jun 18, 2026
10 checks passed
@forgetso forgetso deleted the feat/caddy-pronode-global-cert-getter branch June 18, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant