Self-hosted stack compose files and deployment notes
The CouchDB 3.3 entrypoint runs as root and executes:
find /opt/couchdb \! -user couchdb -exec chown couchdb {} +
before writing a single log line. The :ro bind-mounted local.ini is
owned by root on the host, so chown fails with EROFS — set -e exits
immediately with code 1 and zero output (381ms crash, empty logs).
Running as user 5984:5984 skips the root block in the entrypoint
entirely, going straight to admin setup and CouchDB launch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|---|---|---|
| dashboard | ||
| notifier | ||
| obsidian-sync | ||
| apprise.compose.yml | ||
| changedetection.compose.yml | ||
| forgejo.compose.yml | ||
| miniflux.compose.yml | ||
| n8n.compose.yml | ||
| paperless.compose.yml | ||
| README.md | ||
| seed_changedetection.py | ||
| seed_miniflux.py | ||
| write_homepage_config.py | ||
Manohar's Infrastructure
Self-hosted stack on Hetzner CX32 (Helsinki), deployed via Dokploy + Traefik.
Services
| App | URL | Purpose |
|---|---|---|
| Forgejo | https://git.manohargupta.com | Self-hosted Git |
| n8n | https://automate.manohargupta.com | Workflow automation |
| Apprise | https://notify.manohargupta.com | Notification API (Tailscale only) |
| Miniflux | https://feeds.manohargupta.com | RSS reader |
| ChangeDetection | https://watch.manohargupta.com | Webpage change monitor |
| Paperless-ngx | https://docs.manohargupta.com | Document OCR + search |
| Tiger Agent | https://agent.manohargupta.com | AI orchestration |
| Dokploy | https://dokploy.manohargupta.com | Docker orchestration |
| Uptime Kuma | https://status.manohargupta.com | Monitoring |
| Umami | https://analytics.manohargupta.com | Web analytics |
Stack
- Server: Hetzner CX32, Ubuntu 24.04, Helsinki (hel1)
- Orchestration: Dokploy (Docker Swarm)
- Reverse proxy: Traefik with Let's Encrypt TLS
- Access: Tailscale SSH only
ssh root@manohar-ubuntu - DNS: Namecheap → manohargupta.com
Deployment Notes
- All compose files are in
deployments/ - Every compose declares
dokploy-networkasexternal: true - Labels duplicated under both
labels:anddeploy.labels:— required because Dokploy uses swarm stack deploy for multi-service composes (swarm provider reads deploy.labels; docker provider reads labels) - Secrets set in Dokploy Env tab, never hardcoded (except bcrypt hashes in labels which Dokploy cannot substitute)
- Apprise and ChangeDetection restricted to Tailscale CGNAT range (100.64.0.0/10)
Key Learnings
- Forgejo Docker image uses /data as root, not /var/lib/gitea
- n8n WEBHOOK_URL must match public domain exactly or webhook URLs are wrong
- htpasswd hashes in Traefik labels need
escaping (Compose interpolates single $) - Dokploy env var substitution works in environment: blocks but NOT in labels: