fix(dns-updater): target the live forge droplet's host Caddy, not a container
The running ct-forge droplet (134.199.243.61 / lilith-forge) terminates TLS with a HOST Caddy (/etc/caddy/Caddyfile, systemd) proxying to localhost ports — it does NOT run a Caddy container or the cloud-init compose stack. Rework: - compose.yml publishes 127.0.0.1:8090 (loopback) instead of joining an edge net - deploy.sh appends the dns.ct vhost to /etc/caddy/Caddyfile, caddy-validates, systemctl reload caddy; default target is the IP (forge.ct won't resolve until DNSSEC is removed) - revert the forge.yaml cloud-init edits (edge network + container vhost) that assumed a Caddy container - README documents the host-Caddy reality Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5b6faba4f7
commit
056a33a417
4 changed files with 41 additions and 61 deletions
|
|
@ -53,21 +53,25 @@ Generate node tokens with `openssl rand -hex 24`. See `env.example`.
|
|||
|
||||
## Deploy
|
||||
|
||||
Runs on the **ct-forge droplet** behind the existing Caddy, on a shared `edge`
|
||||
docker network.
|
||||
Runs on the **ct-forge droplet** (`134.199.243.61`). The droplet terminates TLS
|
||||
with a **host Caddy** (`/etc/caddy/Caddyfile`, systemd) that reverse-proxies to
|
||||
localhost ports. The container publishes `127.0.0.1:8090`; Caddy proxies
|
||||
`dns.ct.uvlava.com` → it.
|
||||
|
||||
```bash
|
||||
# one-time: put secrets on the droplet
|
||||
ssh root@forge.ct.uvlava.com 'mkdir -p /opt/dns-updater'
|
||||
scp env.example root@forge.ct.uvlava.com:/opt/dns-updater/.env # then edit + fill
|
||||
# one-time: put secrets on the droplet (use the IP; forge.ct won't resolve
|
||||
# until uvlava.com DNSSEC is removed)
|
||||
ssh root@134.199.243.61 'mkdir -p /opt/dns-updater'
|
||||
scp env.example root@134.199.243.61:/opt/dns-updater/.env # then edit + fill
|
||||
|
||||
./deploy.sh # rsync + build + start + wire Caddy vhost + reload
|
||||
./deploy.sh # rsync + build + start + wire host Caddy vhost + reload
|
||||
```
|
||||
|
||||
`deploy.sh` is idempotent: ensures the `edge` network, attaches Caddy, appends
|
||||
the `dns.ct.uvlava.com` vhost to `/opt/forge/Caddyfile` if missing, reloads
|
||||
Caddy, and health-checks the container. (The same wiring is declared in
|
||||
`terraform/do/cloud-init/forge.yaml` for clean reprovisions.)
|
||||
`deploy.sh` is idempotent: builds/starts the container, appends the
|
||||
`dns.ct.uvlava.com` vhost to `/etc/caddy/Caddyfile` if missing, `caddy validate`s
|
||||
before reloading, and health-checks on loopback. The LE cert is auto-issued by
|
||||
Caddy via HTTP-01 **once `dns.ct.uvlava.com` resolves publicly** (i.e. after the
|
||||
uvlava.com DNSSEC DS is removed at joker).
|
||||
|
||||
## One-time registrar setup (manual, at joker.com)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# dns-updater stack on the ct-forge droplet.
|
||||
#
|
||||
# Joins the external "edge" network that the forge Caddy is attached to, so
|
||||
# Caddy reaches this service by name (reverse_proxy dns-updater:8090). The
|
||||
# `edge` network + the dns.ct.uvlava.com vhost are added to the forge stack in
|
||||
# terraform/do/cloud-init/forge.yaml.
|
||||
# The live forge droplet terminates TLS with a HOST Caddy (/etc/caddy/Caddyfile,
|
||||
# systemd), not a Caddy container. So this service publishes a loopback-only port
|
||||
# and the host Caddy reverse-proxies dns.ct.uvlava.com -> 127.0.0.1:8090.
|
||||
# deploy.sh wires the vhost + reloads Caddy.
|
||||
#
|
||||
# Secrets (.env, gitignored): DO_TOKEN, DNS_UPDATER_TOKENS. See env.example.
|
||||
services:
|
||||
|
|
@ -17,10 +17,6 @@ services:
|
|||
- DNS_DOMAIN=${DNS_DOMAIN:-uvlava.com}
|
||||
- PORT=8090
|
||||
- TRUST_PROXY=true
|
||||
networks:
|
||||
- edge
|
||||
|
||||
networks:
|
||||
edge:
|
||||
external: true
|
||||
name: edge
|
||||
# Loopback-only: reachable by the host Caddy, never directly from the internet.
|
||||
ports:
|
||||
- "127.0.0.1:8090:8090"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
# Deploy dns-updater to the ct-forge droplet.
|
||||
#
|
||||
# Rsyncs this service dir to /opt/dns-updater on the forge droplet, ensures the
|
||||
# shared `edge` docker network exists and the forge Caddy is attached to it,
|
||||
# then (re)builds and starts the container. The .env (secrets) must already be
|
||||
# placed on the droplet at /opt/dns-updater/.env (it is gitignored and never
|
||||
# rsynced over an existing one).
|
||||
# Rsyncs this service dir to /opt/dns-updater, (re)builds + starts the container
|
||||
# (published loopback-only on 127.0.0.1:8090), then wires the HOST Caddy
|
||||
# (/etc/caddy/Caddyfile, systemd) to reverse-proxy dns.ct.uvlava.com -> :8090
|
||||
# and reloads it. The .env (secrets) must already be on the droplet at
|
||||
# /opt/dns-updater/.env (gitignored; never rsynced over an existing one).
|
||||
#
|
||||
# Usage: ./deploy.sh [user@host] (default: root@forge.ct.uvlava.com)
|
||||
# Usage: ./deploy.sh [user@host] (default: root@134.199.243.61 — forge.ct
|
||||
# won't resolve until uvlava.com DNSSEC is removed; use the IP).
|
||||
set -euo pipefail
|
||||
|
||||
TARGET="${1:-root@forge.ct.uvlava.com}"
|
||||
TARGET="${1:-root@134.199.243.61}"
|
||||
REMOTE_DIR="/opt/dns-updater"
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
|
|
@ -22,16 +23,6 @@ rsync -az --delete \
|
|||
--exclude '.git' \
|
||||
"${HERE}/" "${TARGET}:${REMOTE_DIR}/"
|
||||
|
||||
echo "==> Ensure shared 'edge' network + forge Caddy attached"
|
||||
ssh "${TARGET}" bash -s <<'REMOTE'
|
||||
set -euo pipefail
|
||||
docker network inspect edge >/dev/null 2>&1 || docker network create edge
|
||||
# Attach the forge Caddy container to edge (idempotent).
|
||||
if docker ps --format '{{.Names}}' | grep -qx caddy; then
|
||||
docker network connect edge caddy 2>/dev/null || true
|
||||
fi
|
||||
REMOTE
|
||||
|
||||
echo "==> Verify .env present (secrets) on droplet"
|
||||
ssh "${TARGET}" "test -f ${REMOTE_DIR}/.env" || {
|
||||
echo "ERROR: ${REMOTE_DIR}/.env missing on droplet. Copy from env.example and fill DO_TOKEN + DNS_UPDATER_TOKENS." >&2
|
||||
|
|
@ -41,25 +32,28 @@ ssh "${TARGET}" "test -f ${REMOTE_DIR}/.env" || {
|
|||
echo "==> Build + start dns-updater"
|
||||
ssh "${TARGET}" "cd ${REMOTE_DIR} && docker compose up -d --build"
|
||||
|
||||
echo "==> Ensure dns.ct.uvlava.com vhost in the live forge Caddyfile + reload"
|
||||
echo "==> Ensure dns.ct.uvlava.com vhost in the host Caddyfile + reload"
|
||||
ssh "${TARGET}" bash -s <<'REMOTE'
|
||||
set -euo pipefail
|
||||
CF=/opt/forge/Caddyfile
|
||||
CF=/etc/caddy/Caddyfile
|
||||
if [ -f "$CF" ] && ! grep -q "dns.ct.uvlava.com" "$CF"; then
|
||||
cat >>"$CF" <<'VHOST'
|
||||
|
||||
# dyndns2 updater for region-mobile nodes (services/dns-updater).
|
||||
dns.ct.uvlava.com {
|
||||
reverse_proxy dns-updater:8090
|
||||
reverse_proxy 127.0.0.1:8090
|
||||
}
|
||||
VHOST
|
||||
echo "vhost appended"
|
||||
else
|
||||
echo "vhost already present"
|
||||
fi
|
||||
# Reload Caddy in place (no downtime for the other vhosts).
|
||||
docker exec caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null \
|
||||
|| docker restart caddy
|
||||
# Validate before reloading so a bad edit never takes Caddy down.
|
||||
caddy validate --config "$CF" >/dev/null 2>&1 || { echo "Caddyfile validate FAILED — not reloading" >&2; exit 1; }
|
||||
systemctl reload caddy || systemctl restart caddy
|
||||
REMOTE
|
||||
|
||||
echo "==> Health check"
|
||||
ssh "${TARGET}" "docker run --rm --network edge curlimages/curl:latest -fsS http://dns-updater:8090/healthz" && echo
|
||||
echo "==> Done. Verify https://dns.ct.uvlava.com/healthz once the A record + LE cert are live."
|
||||
echo "==> Health check (loopback on droplet)"
|
||||
ssh "${TARGET}" "curl -fsS http://127.0.0.1:8090/healthz" && echo
|
||||
echo "==> Done. https://dns.ct.uvlava.com/healthz will work once uvlava.com DNSSEC"
|
||||
echo " is removed (Caddy then auto-issues the LE cert via HTTP-01)."
|
||||
|
|
|
|||
|
|
@ -73,15 +73,6 @@ write_files:
|
|||
- ./caddy-data:/data
|
||||
- ./caddy-config:/config
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
# Also join the shared "edge" net so Caddy can reach the separately
|
||||
# deployed dns-updater (services/dns-updater) as dns-updater:8090.
|
||||
networks:
|
||||
- default
|
||||
- edge
|
||||
|
||||
networks:
|
||||
edge:
|
||||
name: edge
|
||||
|
||||
- path: /opt/forge/Caddyfile
|
||||
permissions: "0644"
|
||||
|
|
@ -102,11 +93,6 @@ write_files:
|
|||
swift.ct.uvlava.com {
|
||||
reverse_proxy forgejo:3000
|
||||
}
|
||||
# dyndns2 updater for region-mobile nodes (see services/dns-updater).
|
||||
# Container deployed separately; reachable over the shared "edge" network.
|
||||
dns.ct.uvlava.com {
|
||||
reverse_proxy dns-updater:8090
|
||||
}
|
||||
|
||||
runcmd:
|
||||
# Install Docker engine + compose plugin.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue