From 438573ea7b60a52809cf7fc037ff8f0fc58d901a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Waldson=20Patr=C3=ADcio?= Date: Thu, 23 Jul 2026 12:13:20 -0300 Subject: [PATCH] Version-control the shared Caddy edge proxy The droplet's single Caddy container terminates TLS for every site and routes each host to its upstream over proxy_net. Until now its only copy lived on the server; capture compose.yaml and the Caddyfile here, with a README covering how to add a site and reload without downtime. ACME material is git-ignored. --- .gitignore | 7 +++++ Caddyfile | 7 +++++ README.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ compose.yaml | 23 +++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 .gitignore create mode 100644 Caddyfile create mode 100644 README.md create mode 100644 compose.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a96434 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# ACME material and issued certs - private keys, never commit. +letsencrypt/ +acme.json + +# Caddy's data/config live in named Docker volumes on the droplet, not here. +data/ +config/ diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..8a63e72 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,7 @@ +personaledson.com.br, app.personaledson.com.br, api.personaledson.com.br, www.personaledson.com.br { + reverse_proxy bigode-gateway-1:80 +} + +www.nazareonline.com.br, nazareonline.com.br { + reverse_proxy nazareonline-web-1:80 +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..5cd300b --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# central-proxy + +The shared edge reverse proxy for the DigitalOcean droplet (`174.138.36.232`). +A single **Caddy** container terminates TLS for every site on the box and routes +each hostname to the right upstream container. It is the only thing published on +ports 80 and 443; all the application stacks (bigode, nazareonline, ...) sit +behind it on the external `proxy_net` Docker network and speak plain HTTP to it. + +Caddy manages Let's Encrypt certificates automatically - it obtains and renews a +cert for each hostname listed in the `Caddyfile` on first request. Issued certs +and ACME account keys persist in the `caddy_data` Docker volume (mounted at +`/data`), not in this repo. + +## Layout + +``` +compose.yaml the Caddy service: publishes 80/443, joins proxy_net, + bind-mounts the Caddyfile, persists certs in caddy_data +Caddyfile one site block per app; each reverse_proxies to a container + reachable by name on proxy_net +``` + +## Prerequisites + +- The external network exists: `docker network create proxy_net`. +- Each upstream stack attaches its public-facing container to `proxy_net`, so + Caddy can reach it by container name (e.g. `nazareonline-web-1:80`). +- DNS A records for every hostname in the `Caddyfile` point at the droplet. + +## Adding a site + +Add a block to the `Caddyfile` naming the hostname(s) and the upstream: + +``` +www.example.com, example.com { + reverse_proxy example-web-1:80 +} +``` + +The upstream container must be on `proxy_net`. Caddy forwards the original `Host` +and sets `X-Forwarded-Proto: https`, so upstreams behind it can rebuild HTTPS +URLs and do their own host canonicalisation. + +Then reload without downtime (does not disturb the other sites): + +```sh +docker exec central-proxy-caddy-1 caddy reload --config /etc/caddy/Caddyfile +``` + +Validate a change before reloading: + +```sh +docker run --rm -v "$PWD/Caddyfile":/etc/caddy/Caddyfile:ro caddy:2-alpine \ + caddy validate --config /etc/caddy/Caddyfile +``` + +## Deploy + +The compose stack lives at `/home/waldson/central-proxy` on the droplet. To +apply a change, copy the edited `Caddyfile` up and reload: + +```sh +scp -i ~/.ssh/deploy_key ./Caddyfile waldson@174.138.36.232:/home/waldson/central-proxy/Caddyfile +ssh -i ~/.ssh/deploy_key waldson@174.138.36.232 \ + 'docker exec central-proxy-caddy-1 caddy reload --config /etc/caddy/Caddyfile' +``` + +Bring the proxy up (or recreate it after a compose change) from that directory: + +```sh +docker compose up -d +``` + +## Notes + +- `letsencrypt/acme.json` is leftover state from an earlier Traefik-based proxy + and is not used by Caddy. It is git-ignored (it contains private keys); it can + be deleted from the droplet once you are sure nothing references it. +- Never `docker volume rm caddy_data` - that discards every issued certificate + and forces re-issuance, which can hit Let's Encrypt rate limits. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..8636d1e --- /dev/null +++ b/compose.yaml @@ -0,0 +1,23 @@ +name: central-proxy + +services: + caddy: + image: caddy:2-alpine + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + - caddy_config:/config + networks: + - proxy_net + +networks: + proxy_net: + external: true + +volumes: + caddy_data: + caddy_config: