The previous fix only excluded 5038 (AMI). Confirmed live: after
attaching caddy_net, `docker compose up -d` still failed —
"failed to bind host port 0.0.0.0:5060/tcp: address already in use" —
because Asterisk (network_mode: host) also owns 5060 (SIP, tcp+udp)
and 5061 (SIP TLS, tcp), both inside Traccar's 5000-5150 range.
Asterisk gets priority on all three ports; Traccar's range just skips
them. Audited every other network_mode: host service in the repo
(caddy, homeassistant, kyber-server, lyrion, mattermost, watchyourlan,
wolf-pair, wolf) — none of them land in 5000-5150, so Asterisk is the
only conflict to account for.
Confirmed live: on a box also running Asterisk from this repo,
`docker network connect caddy_net traccar` failed with "failed to bind
host port 0.0.0.0:5038/tcp: address already in use". Asterisk runs with
network_mode: host (services/asterisk.sh), so its AMI (port 5038,
hardcoded in services/sms-inbound.sh) binds directly on the host's
network stack — no Docker NAT involved. Traccar's docker-compose.yml
published the entire 5000-5150 range for device protocols, which
needs Docker to also bind host port 5038 for its own port-forwarding,
directly colliding with Asterisk's AMI on any box running both
services from this repo.
Split the TCP range into 5000-5037 and 5039-5150 to skip that one
port; left UDP as a single 5000-5150 range since AMI is TCP-only.
Current Traccar images ship with no built-in account at all — the login
screen's Register flow creates the first user, and that user is
automatically made admin. The admin@admin.com/admin default our messages
still quoted belongs to older Traccar versions and no longer exists,
so anyone following our own output would try that login and fail.
Updated the dry-run summary, README, and final on-screen message to
describe the real flow, and to flag that self-registration stays open
to anyone who reaches the server until it's turned off (Settings →
Server → Permissions), since that's a real exposure window on a
freshly-installed instance with no way to lock it down at config time.
The previous fix still baked database.user/database.password directly
into config/traccar.xml, duplicating the secret that .env already held
and leaving a second, unmanaged copy of it on disk.
Traccar supports reading its config from environment variables
(CONFIG_USE_ENVIRONMENT_VARIABLES=true, confirmed against the official
traccar/traccar docker/compose/traccar-mysql.yaml reference). Use that:
DATABASE_DRIVER/URL/USER/PASSWORD are now set in the compose file via
${POSTGRES_*} interpolation from .env, so .env is the only place the
credentials live — drop config/traccar.xml and its volume mount
entirely, matching the official reference example.
Also switched to the official reference healthcheck (wget against
/api/health, 1h start_period) — a real endpoint on real hardware rather
than a guessed /dev/tcp probe against an unverified image's toolset —
and added the interval/start-period env vars to the autoheal container
to match, while keeping the container scoped to just Traccar via the
autoheal=true label instead of the reference's host-wide "all".
Verified with `docker compose config` (both with and without a local
Caddy directory present) that the ${POSTGRES_DB}/${POSTGRES_USER}/
${POSTGRES_PASSWORD} references resolve correctly from .env with no
warnings.
The caddy_net wiring for the new db/traccar containers was gated only on
whether ~/docker/caddy exists locally, so it didn't account for a site
where Caddy runs on a different box (CADDY_MODE=remote or the legacy
CADDY_REMOTE_HOST var, set with no local Caddy directory). Resolve the
mode the same way configure_caddy_for_service does — explicit CADDY_MODE
first, then the local directory, then CADDY_REMOTE_HOST — so caddy_net is
only joined when Caddy is actually local. A remote Caddy reaches Traccar
via this host's published 8082 port regardless, so no other change is
needed for that path.
Traccar's docker image no longer bundles the H2 driver, so the
generated traccar.xml (org.h2.Driver / jdbc:h2:...) failed at startup
with no working database. Add a postgres:15-alpine db container with
a healthcheck, point traccar.xml/POSTGRES_* at it via .env, and gate
traccar's startup on db being healthy.
Also add a willfarrell/autoheal container scoped to just the traccar
container (via the autoheal=true label) that restarts it if its own
TCP healthcheck on 8082 fails.
Reruns reuse the existing DB_PASS from .env instead of generating a
new one, since the postgres volume keeps the original password from
its first init.
New site config key: CADDY_REMOTE_HOST (set via 'sudo ./setup.sh configure').
When set, configure_caddy_for_service operates in "remote" mode instead of
writing to a local Caddyfile:
- Upstream uses CADDY_REMOTE_HOST:PORT (host IP, not container name)
- Snippet saved to ~/docker/caddy-snippets/<subdomain>.caddy
- User is shown scp/rsync commands to copy it to the Caddy machine
Three modes in configure_caddy_for_service (lib/common.sh and inline stubs):
local: ~/docker/caddy/ exists → write Caddyfile + reload (existing behavior)
remote: CADDY_REMOTE_HOST set → save snippet, print copy instructions
none: neither configured → silent return (unchanged)
All 31 service standalone bootstrap stubs updated with the new logic.
CADDY_REMOTE_HOST global added to all 42 standalone bootstrap sections.
setup.sh configure now prompts for CADDY_REMOTE_HOST with a clear explanation.
wolf.sh: add missing stubs (configure_caddy_for_service, write_readme,
prompt_yn, ensure_docker_dir_ownership) and the Authelia/Caddy/start calls
that were missing from the install function.
https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
Each service can now be run directly with sudo bash <service>.sh on any
machine with Docker installed, without needing the full post-install repo.
Uses the shared bootstrap pattern from docs/standalone-template.sh.
https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
Undo the host.docker.internal approach from the previous commit — proper
Docker networking routes Caddy to services by container name on the shared
caddy_net, not via the host gateway.
- lib/common.sh: configure_caddy_for_service now accepts either a plain
port number (localhost:PORT fallback) or container:port (preferred).
The Caddyfile entry uses the container name for direct Docker DNS routing.
- services/caddy.sh: remove extra_hosts hack; update Caddyfile template
comments to show container_name:port format
- All service files: update configure_caddy_for_service calls to pass
container_name:internal_port (e.g. "filebrowser:80", "mealie:9000").
Services using network_mode:host keep plain port numbers.
- tools/manage_users.sh: new FileBrowser user-management script (deployed
to ~/docker/filebrowser/ during installation). Manages users via the
FileBrowser REST API: list, add, delete, passwd, scope, info commands.
Documents username format (letters/numbers/hyphens/underscores),
password rules (min 8 chars, letter + number required), and scope path
convention relative to /srv (= FB_PATH on the host).
https://claude.ai/code/session_01UZus2Q9gNTfUdqSMrhuX29
- lib/common.sh: fix broken reverse_proxy target — localhost inside Caddy's
container is the container's own loopback, not the host; change to
host.docker.internal so proxied ports are actually reachable
- services/caddy.sh: add extra_hosts host.docker.internal:host-gateway so
the above resolves correctly; create caddy_net bridge network in Caddy's
own compose so other services can reference it as external; update all
Caddyfile template comments and README examples to match
- services/filebrowser.sh: update image tag from deprecated :s6 to :latest;
remove non-functional PUID/PGID env vars (filebrowser/filebrowser does not
honour them); add configure_caddy_for_service call; add caddy_net
- services/ntfy.sh: add configure_caddy_for_service call; add caddy_net
- services/portainer.sh: add configure_caddy_for_service call; add caddy_net
- services/frigate-notify.sh, watchtower.sh: add caddy_net for
container-to-container comms (frigate, ntfy) without a Caddy call
- All remaining web-facing Docker services: add caddy_net network block to
docker-compose and CADDY_NET to .env where applicable; services using
network_mode: host (wolf-pair, lyrion) have the top-level block only
https://claude.ai/code/session_01UZus2Q9gNTfUdqSMrhuX29