Adding a Service¶
How to onboard a new Docker Compose service into the homelab monorepo so that Komodo deploys it automatically and Homepage picks up a tile.
Prerequisites¶
- Docker and Docker Compose installed on the target host
- The Traefik stack is running (it owns the
traefikDocker network) - Komodo is running and connected to the host
Steps¶
1. Copy the template¶
2. Edit compose.yml¶
- Replace all
REPLACE_MEplaceholders with real values - Set the correct image, container name, and ports
- Configure Traefik labels with the desired subdomain (
<name>.infra.realemail.app) - Add volumes for persistent data if needed
- Ensure the service joins the
traefiknetwork (external)
3. Configure secrets¶
If the service needs secrets (API keys, passwords, DB credentials):
- Copy
.env.sops.yaml.exampleto.env.sops.yamland fill in real values - Encrypt in WSL:
sops -e -i services/<service-name>/.env.sops.yaml - Commit and push the encrypted file
- On the host, decrypt SOPS YAML to a dotenv-format
.env:
See secrets runbook for details on the YAML-to-dotenv conversion.
4. Update inventory (if applicable)¶
If this is a significant service that should appear in the inventory:
- Add an entry to the appropriate inventory file or create a new one
- Run generators to update downstream files:
uv run python inventory/generators/render-homepage.py
uv run python inventory/generators/render-doc-stubs.py
5. Update backup policy¶
Edit backup.yml in the service directory:
- Set the correct tier (1 = critical, 2 = nice-to-have, 3 = replaceable)
- List the paths that need backing up
- Add pre/post hooks if the service needs to quiesce before backup
6. Write the README¶
Fill in the service README with:
- What the service does
- Quick reference table (image, port, URL)
- Any manual setup steps
- Troubleshooting tips
7. Commit and push¶
Komodo detects the push (via webhook or polling) and deploys the stack automatically. The Homepage tile appears after the generator runs.
DNS¶
New services on infra-services use *.infra.realemail.app subdomains.
Create a CNAME or A record pointing to 192.168.6.17 (or use Cloudflare
DNS if the service should be publicly accessible with TLS).
Checklist¶
- [ ]
compose.ymlhas noREPLACE_MEplaceholders - [ ]
.env.sops.yamlis encrypted (pre-commit hook verifies this) - [ ]
backup.ymltier is set correctly - [ ] README documents the service
- [ ] Generators run cleanly (
--checkpasses) - [ ] Service starts with
docker compose up -don the target host - [ ] Traefik routes traffic correctly to the service