Self-hosted stack compose files and deployment notes
Find a file
2026-04-27 00:04:33 +05:30
apprise.compose.yml apprise: switch from IP whitelist to basic auth 2026-04-27 00:04:33 +05:30
changedetection.compose.yml Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30
forgejo.compose.yml Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30
miniflux.compose.yml Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30
n8n.compose.yml Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30
paperless.compose.yml Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30
README.md Initial commit: all 6 self-hosted app compose files + README 2026-04-26 23:08:58 +05:30

Manohar's Infrastructure

Self-hosted stack on Hetzner CX32 (Helsinki), deployed via Dokploy + Traefik.

Services

AppURLPurposeForgejohttps://git.manohargupta.comSelf-hosted Gitn8nhttps://automate.manohargupta.comWorkflow automationApprisehttps://notify.manohargupta.comNotification API (Tailscale only)Minifluxhttps://feeds.manohargupta.comRSS readerChangeDetectionhttps://watch.manohargupta.comWebpage change monitorPaperless-ngxhttps://docs.manohargupta.comDocument OCR + searchTiger Agenthttps://agent.manohargupta.comAI orchestrationDokployhttps://dokploy.manohargupta.comDocker orchestrationUptime Kumahttps://status.manohargupta.comMonitoringUmamihttps://analytics.manohargupta.comWeb 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-network as external: true
  • Labels duplicated under both labels: and deploy.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: