4.0 KiB
Homelab Stack Standards
Repository Root
/mnt/docker-ssd/docker/compose
Remotes:
- GitHub:
git@github.com:Paccoco/truenas-stacks.git - Gitea web:
http://10.5.1.6:3002/fizzlepoof/truenas-stacks - Gitea SSH:
ssh://git@10.5.1.6:2222/fizzlepoof/truenas-stacks.git
Use the internal Gitea SSH remote from PD/NOMAD. Port 2222 is SSH, not HTTP.
Stack Layout
Each production stack lives in a subdirectory of the repo root.
Each stack contains:
docker-compose.yaml— required.env— required (gitignored).env.example— committed with placeholder values- optional init scripts (e.g.
initdb/,initdb-mariadb/)
Host-Run Services
If something on NOMAD is not deployed as a Docker compose stack, its live runtime belongs under /opt/<service>.
Examples:
/opt/project-nomad/opt/newt/opt/doris-dashboard
Use the repo for source/staging, but do not run production host services from an agent workspace or random checkout under /home/fizzlepoof/.openclaw/workspace.
Deployment Order
databases/— must be up before anything elseinfrastructure/— newt creates the pangolin network- All other stacks in any order
Deployment Workflow
Validate before deploying:
cd /mnt/docker-ssd/docker/compose/<stack>
docker compose --env-file .env config
Deploy:
docker compose --env-file .env up -d
Teardown a single service:
docker compose --env-file .env down <service>
Networks
ix-databases_shared-databases
Created by the databases stack with name: ix-databases at top level. Any stack connecting to shared databases must declare:
networks:
ix-databases_shared-databases:
external: true
pangolin
Created by newt at runtime. Any externally exposed service must declare:
networks:
pangolin:
external: true
Storage Standards
Local SSD: /mnt/docker-ssd
Use /mnt/docker-ssd/docker/appdata/<service> for:
- Postgres / MariaDB / Redis data
- SQLite-backed apps
- Apps that chown aggressively on startup
- GPU/model caches
- Write-heavy logs, cache, state
TrueNAS Pool (tank): /mnt/tank
Use /mnt/tank/docker/appdata/<service> for:
- General appdata
- Configs
- Uploads
- Non-permission-sensitive state
Unraid NFS: /mnt/unraid
/mnt/unraid/data/media/— media libraries/mnt/unraid/immich— Immich photo/video storage
Volume Rules
- no anonymous volumes
- no ad-hoc home directory paths
- all binds use standardized production paths
- evaluate SSD vs tank vs Unraid before deploying any new service
- apps known to have permission issues on NFS go on SSD
Known Permission Quirks
shlinkdata directory must be chmod 777 — runs as non-root userimmich-mlcache goes to/mnt/docker-ssd/docker/appdata/immich-ml(separate from immich-server)donetickrequires/mnt/tank/docker/appdata/donetick/config/selfhosted.yaml— env vars alone insufficient
Secrets Management
.envfiles are gitignored.env.examplefiles are committed with placeholder values- Database passwords:
openssl rand -hex 24 - JWT secrets:
openssl rand -hex 32
Healthcheck Patterns
Always check available tools before writing healthchecks:
sudo docker exec <container> sh -c "which curl; which wget" 2>&1
- Has curl:
["CMD-SHELL", "curl -sf http://127.0.0.1:<port>/ || exit 1"] - Has wget only:
["CMD-SHELL", "wget -qO- http://127.0.0.1:<port>/ >/dev/null 2>&1 || exit 1"] - Has neither:
["CMD-SHELL", "cat /proc/net/tcp6 | grep -q <HEX_PORT> || exit 1"] - Redirecting endpoint:
["CMD-SHELL", "curl -sfL http://127.0.0.1:<port>/ || exit 1"]
Common hex port values: 8080=1F90, 3003=BBB, 3000=BB8, 8181=1FF5, 5055=13BF, 2021=7E5
After changing a healthcheck, must down then up (not just restart).
Git Workflow
cd /mnt/docker-ssd/docker/compose
git add .
git commit -m "description"
git push ssh://git@10.5.1.6:2222/fizzlepoof/truenas-stacks.git main
All .env files are gitignored. Only compose files, .env.example, and init scripts are committed.