Troubleshooting
Real failure modes documented in this repository — the first-boot password, AppArmor, BuildKit, the read-only secrets volume, and gateway 401s.
Where is the first-boot admin password?
Printed once, on the boot that creates the account, to the control plane’s log — and nowhere else:
docker compose logs control-plane | grep -A6 'FIRST-BOOT ADMIN'
If DSH_ADMIN_PASSWORD was set before that first boot, nothing is ever printed — that password is the one to use.
Postgres won’t start on a Proxmox or Debian host
AppArmor on these hosts blocks Postgres’ own unix socket. Add an override for the affected services:
# docker-compose.override.yml
services:
postgres:
security_opt: ["apparmor=unconfined"]
control-plane:
security_opt: ["apparmor=unconfined"]
gateway:
security_opt: ["apparmor=unconfined"]
This is a quirk of those hosts, not a stack setting — it isn’t needed elsewhere.
Building an image fails with no network access
On a Proxmox or Debian Docker host, BuildKit’s default builder has no network reachable from a RUN step, so any build step that needs the network (installing packages, for example) fails there and nowhere else. Fall back to the classic builder with the host’s network:
DOCKER_BUILDKIT=0 docker build --network=host …
A service can’t read a file from the secrets volume
The secrets volume is mounted read-only everywhere except the service that generates it — by design, so nothing else can rotate a secret out from under the rest of the stack. If a service can’t read a file it expects there, check that the first-boot init service completed successfully rather than adjusting permissions on the reader.
Every Gateway call returns 401
The control plane and the Gateway are handed the same token and refuse anything that doesn’t match, byte for byte — including a trailing newline. A token file written with an extra newline at the end produces exactly this: every RPC 401s, and neither log says why, because from the Gateway’s side an unrecognized token and a mistyped one look identical. Compare the token files directly rather than assuming the value is wrong.