8.1 KiB
Homelab Configs
Docker Compose files and configuration for homelab infrastructure. All stacks are managed via Portainer at http://192.168.88.27:9000 (or https://portainer.jgitta.com).
Portainer Access
| Item | Value |
|---|---|
| URL | http://192.168.88.27:9000 |
| External URL | https://portainer.jgitta.com |
| API Token | ptr_1cThi+cjOKeICslJbSzCtUhORF06xUOykbAWPUoTyMU= |
Note: The API token above is for automation/scripting. Keep it private. To call the Portainer API:
curl -H "X-API-Key: <token>" http://192.168.88.27:9000/api/stacks
Important — Volume Paths: All volume mounts in Portainer stacks must use absolute paths (e.g.
/srv/docker/myapp/data:/app/data). Relative paths (e.g../data) resolve to Portainer's internal/data/compose/<id>/directory and will lose data if the stack is redeployed with a different ID. This was audited and corrected on 2026-05-07.
Hosts
| Host | IP | Role | Portainer Endpoint ID | Docker Version |
|---|---|---|---|---|
| siklos | 192.168.88.27 | Main Docker server (VM 112 on Proxmox) | 3 (local) | 26.1.5 |
| jellyfin | 192.168.88.10 | Media server | 4 (agent) | 26.1.5 |
| thinkstation-p710 | 192.168.88.41 | Workstation / Ollama / AI | 5 (agent) | 29.4.2 |
Stack Inventory
siklos (192.168.88.27) — 20 stacks
| Stack | Port(s) | Data Path | URL | Notes |
|---|---|---|---|---|
| actual-budget | 5006 | /srv/docker/actual-budget | budget.jgitta.com | Budget tracking |
| dashboard | 8096 | /srv/docker/dashboard | dashboard.jgitta.com | Custom homepage |
| dashy | 8081 | /srv/docker/dashy | dashy.jgitta.com | Dashboard |
| gitea | 3002, 2222 | /srv/docker/gitea/data | gitea.jgitta.com | Git server — this repo |
| glances | 61208 | — | glances.jgitta.com | System monitoring |
| goldengames | 3030 | /srv/docker/goldengames | goldengamer.org | (built locally) |
| guacamole | 8080 | /srv/docker/guacamole | apache.jgitta.com | Apache Guacamole — remote desktop gateway |
| homarr | 7575 | /srv/docker/homarr/.homarr/appdata | homarr.jgitta.com | Dashboard |
| karakeep | 3010 | /srv/docker/karakeep | notes.jgitta.com | Bookmarks / read-later |
| kopia | 51515 | /srv/docker/kopia | kopia.jgitta.com | Backup tool (backs up to TrueNAS) |
| linkwarden | 3015 | /srv/docker/linkwarden/pgdata | links.jgitta.com | Link manager |
| litellm | 4000 | /srv/docker/litellm | — | LLM API gateway |
| meshcentral | 444 | /srv/docker/meshcentral | mesh.jgitta.com | Remote management |
| monitoring | 9090, 3020, 8090 | /srv/docker/monitoring | grafana.jgitta.com | Prometheus + Grafana + cAdvisor |
| onlyoffice | 8880 | /srv/docker/onlyoffice | office.jgitta.com | Office document server (replaced Collabora) |
| pihole | host network | /srv/docker/pihole | pihole.jgitta.com | DNS ad blocker + faster-whisper + open-webui |
| portainer | 9000, 9443 | /srv/docker/portainer | portainer.jgitta.com | Container management UI |
| uptime-kuma | 3001 | /srv/docker/uptime-kuma/data | status.jgitta.com | Uptime monitoring |
| watchtower | — | — | — | Auto-updates containers |
| wordpress | 8095 | /srv/docker/wordpress | jgitta.com | WordPress site |
jellyfin (192.168.88.10) — 3 stacks
| Stack | Port(s) | Data Path | Notes |
|---|---|---|---|
| arr-stack | various | /srv/docker | Radarr, Sonarr, Prowlarr, Flaresolverr, Watchtower |
| node-exporter | 9100 (host) | — | Prometheus metrics exporter (host network) |
| portainer-agent | 9001 | — | Portainer agent (fully managed) |
thinkstation-p710 (192.168.88.41) — 4 stacks
| Stack | Port(s) | Data Path | Notes |
|---|---|---|---|
| frigate | 5000, 8554, 8555 | /srv/docker/frigate | NVR / camera AI |
| open-webui | 3000 | /srv/docker/open-webui | Ollama web UI |
| portainer-agent | 9001 | — | Portainer agent (shows "limited" — expected, see notes) |
| stirling-pdf | 8081 | /srv/docker/stirling-pdf | PDF tools |
Caddy Reverse Proxy
Caddy runs on a dedicated VM at 192.168.88.110 (alias: caddy) as a systemd service.
It handles all HTTPS termination and reverse proxying for *.jgitta.com subdomains.
TLS certificates are obtained automatically via Cloudflare DNS challenge (Let's Encrypt).
Config location: /etc/caddy/ on the caddy VM.
File Structure
| File | Purpose |
|---|---|
Caddyfile |
Main file — sets global options, imports snippets and sites |
snippets.caddy |
Reusable blocks: web_secure, internal_only, proxy_timeouts, etc. |
sites/infrastructure.caddy |
Management/tool services (portainer, kopia, grafana, pihole, etc.) |
sites/media.caddy |
Media and automation stack (jellyfin, sonarr, radarr, next, etc.) |
sites/homenet.caddy |
Internal .homenet HTTP-only domains (no TLS) |
sites/goldengamer.caddy |
goldengamer.org external domain |
Key Snippets
internal_only— Blocks requests from outside192.168.88.0/24and192.168.2.0/24viaabort. Used on sensitive services (portainer, pihole, proxmox, etc.).web_secure— Standard security headers + gzip compression.proxy_timeouts— 90s read/write timeouts on upstream connections.
DNS Notes
- Internal services use MikroTik DNS (
192.168.88.1) to resolve*.jgitta.com→192.168.88.110. - Browsers with DNS-over-HTTPS (DoH) enabled (e.g. Brave) bypass MikroTik DNS and use public resolvers, which have no record of internal-only subdomains. Disable DoH in browser settings or ensure Cloudflare DNS has grey-cloud records pointing to the WAN IP for all subdomains.
- Public-facing services use Cloudflare DNS (grey cloud) → WAN IP → MikroTik port-forwards 443 → Caddy VM.
internal_onlyservices should use grey-cloud Cloudflare records (not orange/proxied) — orange cloud sends traffic from Cloudflare's IPs whichinternal_onlywill abort, causing a 520 error.
Data Directory Convention
All stack data is stored under /srv/docker/<stack-name>/ on each host.
All Portainer volume mounts must use absolute paths — relative paths break on stack redeploy.
Old compose files were renamed to .bak after migration to Portainer.
Kopia Backup Notes (updated 2026-05-07)
Kopia backs up Nextcloud data (VM 103) and other sources to TrueNAS NFS.
- Cache limit set to 4 GB content + 512 MB metadata (
kopia cache set) /tmpand/app/logsare bind-mounted out of the container to prevent overlay2 growth- After-snapshot hook pings Uptime Kuma heartbeat at
status.jgitta.comafter each backup - If disk fills up again, check
/srv/docker/kopia/tmp/for leftover verify/restore artifacts - Ignore policy active for
/data/.claudein the Nextcloud data source
Portainer Agent Notes
Portainer agents run on jellyfin and thinkstation, allowing the central Portainer instance on siklos to manage all three Docker hosts from one UI.
- jellyfin agent: Fully managed by Portainer (Stack ID 36)
- thinkstation agent: Shows as "limited" in Portainer UI — this is expected and harmless.
The portainer-agent cannot redeploy itself through its own proxy (catch-22). The agent
is stable and the endpoint is fully functional. Agent data is persisted in the
portainer_agent_dataDocker named volume so TLS certs survive restarts.
Git / Gitea Push Methodology
Gitea runs as a Docker container on siklos (192.168.88.27), SSH on port 2222.
Pushes use SSH key auth (not HTTPS/password). The ~/.ssh/config entry on any machine that needs to push:
Host gitea
HostName 192.168.88.27
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
PreferredAuthentications publickey
The remote URL for this repo:
git remote set-url origin gitea:jgitta/homelab-configs.git
To add a new machine's SSH key to Gitea:
- Copy the machine's public key:
cat ~/.ssh/id_ed25519.pub - Paste it at https://gitea.jgitta.com/user/settings/keys
- Add gitea to
~/.ssh/known_hosts:ssh-keyscan -p 2222 192.168.88.27 >> ~/.ssh/known_hosts
Proxmox / Infrastructure Notes
| Item | Details |
|---|---|
| Proxmox host | 192.168.88.25 |
| PBS | 192.168.88.60 |
| TrueNAS | 192.168.88.24 |
| Nextcloud VM | VM 103 (192.168.88.62) |
| Docker server VM | VM 112 = siklos (192.168.88.27) |
| Caddy proxy VM | 192.168.88.110 |