infra/README.md

30 lines
1.8 KiB
Markdown

# Manohar's Infrastructure
Self-hosted stack on Hetzner CX32 (Helsinki), deployed via Dokploy + Traefik.
## Services
AppURLPurposeForgejo<https://git.manohargupta.com>Self-hosted Gitn8n<https://automate.manohargupta.com>Workflow automationApprise<https://notify.manohargupta.com>Notification API (Tailscale only)Miniflux<https://feeds.manohargupta.com>RSS readerChangeDetection<https://watch.manohargupta.com>Webpage change monitorPaperless-ngx<https://docs.manohargupta.com>Document OCR + searchTiger Agent<https://agent.manohargupta.com>AI orchestrationDokploy<https://dokploy.manohargupta.com>Docker orchestrationUptime Kuma<https://status.manohargupta.com>MonitoringUmami<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](http://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: