traccar.sh's caddy_net wiring was fixed to mirror configure_caddy_for_service's
own mode resolution (CADDY_MODE from site config, then a local ~/docker/caddy,
then the legacy CADDY_REMOTE_HOST var) instead of only checking for the local
directory. That same bare directory check was copy-pasted into the caddy_net
wiring of every other Docker service in the repo, so a site with Caddy on a
different box would silently fail to join any of their containers to caddy_net
during setup (or, for homeassistant/koha, only get half the wiring right).
Applied the same fix mechanically across all 37 services using the standard
_CADDY_NET_BLOCK/_CADDY_NET_SECTION pattern (verified identical text via
scripted diff before touching any of them), plus by hand for:
- homeassistant.sh and koha.sh, which use their own differently-shaped
variables (HA_CADDY_NET_LINES / _CADDY_NET_ENTRY) for the same decision
- paintplus.sh and ai-stack.sh, which do a live `docker network connect`
instead of a compose network block
- watchyourlan.sh, whose Caddy note was worded for local-only setups
sms-inbound.sh got more than a mode swap: its Caddy wiring was hand-rolled
(not routed through configure_caddy_for_service) and had no remote-Caddy
path at all — a remote Caddy box would get a misleading "Caddy isn't
installed here" message instead of a snippet. Added
_sms_write_caddy_snippet(), mirroring the snippet-file pattern
configure_caddy_for_service uses everywhere else, and pointed the firewall
gate at the same three-way mode instead of a two-way dir check.
Verified: bash -n across all of services/*.sh, a scripted check that every
touched file has exactly one _CADDY_MODE resolution and no leftover bare
`[ -d "$DOCKER_DIR/caddy" ]` feeding a caddy_net decision, and spot-checked
docker compose config renders (traccar, mattermost) confirming the ${VAR}
interpolation and multi-service usage sites still resolve correctly.
wg-easy: PASSWORD env var removed in v14+; generate bcrypt hash at install
time via 'docker run wg-easy wgpw' and write PASSWORD_HASH instead.
ntfy: write config/server.yml with base-url, cache-file, auth-file, and
behind-proxy:true so push notification links work when behind Caddy.
auth-default-access: deny-all (require topic auth).
mealie: BASE_URL was hardcoded to http://localhost:9925; email links and
OAuth redirects broke when served via Caddy. Now computed from SITE_DOMAIN
and written to .env so it's easy to update.
nextcloud: add OVERWRITEPROTOCOL=https, OVERWRITECLIURL, TRUSTED_PROXIES to
.env so share links and internal redirects use https:// behind Caddy.
onlyoffice: Caddy's default X-Frame-Options: SAMEORIGIN header blocked
OnlyOffice from being embedded as an iframe in Nextcloud. Override it in
the Caddy site block to allow framing.
vaultwarden: remove exposed port 3012 (WebSocket — not needed since v1.29+,
all handled on port 80). Publish port 8888 for direct host access instead.
Remove WEBSOCKET_ENABLED=true (ignored in current versions).
https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
Nextcloud: custom Dockerfile (nextcloud:apache + smbclient) for SMB external
storage support without AIO. All data uses bind mounts so Kopia/Borg coverage
is automatic. Enables files_external app after first boot.
OnlyOffice: JWT-secured document server wired to Nextcloud via occ commands
and FileBrowser Quantum config.yaml if both are installed. Port 8082.
Mattermost: Team Edition + PostgreSQL + dedicated coturn on port 3479 (does
not conflict with Easy Asterisk's coturn on 3478). Bind mounts throughout.
UFW rules and router port-forward instructions printed at install time.
https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt