Add up your monthly subscriptions: hosting, databases, monitoring, email, analytics, CI/CD. For a typical indie developer or small team, it's $80–200/month before you've written a single line of product code.
Most of it can run on a $6/month VPS. Here's how.
Why Self-Host?
Cost. A Hetzner CX21 (2 vCPU, 4 GB RAM, 40 GB SSD) costs €3.79/month. That single server can replace dozens of SaaS subscriptions for personal projects and small apps.
Control. Self-hosted infrastructure doesn't change its pricing, deprecate features, or go down because someone else's systems are having an incident.
Learning. Running your own infrastructure teaches you things that no amount of platform-as-a-service usage will: networking, containers, reverse proxies, SSL, backups. Skills that make you a better engineer everywhere.
Data ownership. Your user data, logs, and application state live on hardware you control, not in a multi-tenant cloud you're a line item in.
The Foundation: One VPS, Docker, and Traefik
The self-hosting stack that works for most indie developers:
- Docker: containerize everything for portability and isolation
- Docker Compose: manage multi-service stacks with simple YAML files
- Traefik: reverse proxy that handles HTTPS and routing for all your services
- DomainDock: provision custom domains instantly without owning a domain or managing DNS
This combination turns a bare VPS into a platform that can run any number of web apps simultaneously, each at their own HTTPS domain.
The Services Worth Self-Hosting
Databases
PostgreSQL is free to run in Docker and handles production workloads for most indie apps.
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: myapp
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
Redis handles caching, sessions, queues, and pub/sub.
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
restart: unless-stopped
Replacing: $25–50/month managed database → $0 (uses resources already on your VPS)
Analytics
Plausible is a privacy-focused, GDPR-compliant analytics tool. Self-host it and you avoid both the $9+/month SaaS fee and the need to show a cookie consent banner (no cookies, no cross-site tracking).
plausible:
image: ghcr.io/plausible/community-edition:v2.1
environment:
BASE_URL: https://analytics.yourproject.digitalweb.host
SECRET_KEY_BASE: ${PLAUSIBLE_SECRET_KEY}
depends_on:
- postgres
- clickhouse
restart: unless-stopped
Replacing: $9–19/month Plausible cloud → $0
Uptime Monitoring
Uptime Kuma is a self-hosted monitoring dashboard similar to UptimeRobot. Add your services, set check intervals, configure notification channels (Slack, Telegram, email), and you have real-time uptime monitoring.
uptime-kuma:
image: louislam/uptime-kuma:1
volumes:
- kuma_data:/app/data
ports:
- "127.0.0.1:3001:3001"
restart: unless-stopped
Point it at https://monitor.yourproject.digitalweb.host via Traefik.
Replacing: $7/month UptimeRobot Pro → $0
CI/CD
Gitea is a lightweight self-hosted Git service. Combine it with Gitea Actions (GitHub Actions-compatible) and Woodpecker CI (a lightweight, open-source CI runner) for a complete CI/CD pipeline that costs nothing extra.
Or, for simplicity: use GitHub's free tier for the repo and a webhook-triggered deploy script on your VPS. Works fine for solo or small projects.
Email (Transactional)
This one is worth keeping on a managed service. Email deliverability is a reputation problem (IP warming, PTR records, DMARC) that's genuinely difficult to self-host correctly. Resend, Mailgun, and Postmark all have generous free tiers for transactional email (1,000–3,000 emails/month free).
Exception: If you need full control over your email server and are willing to manage reputation, Stalwart Mail Server or Mailu are solid self-hosted options.
Setting Up Custom Domains for Each Service
This is where DomainDock comes in. Instead of configuring Cloudflare DNS for each service you spin up, DomainDock handles it from a dashboard.
For the services above, you'd create:
app.yourproject.digitalweb.host→ port 3000 (your main app)analytics.yourproject.digitalweb.host→ port 8000 (Plausible)monitor.yourproject.digitalweb.host→ port 3001 (Uptime Kuma)git.yourproject.digitalweb.host→ port 3100 (Gitea)
In DomainDock: four domains, same VPS IP, different ports. Four Traefik routing files. All with automatic HTTPS.
The Traefik Configuration
Each service needs a routing rule in ~/traefik/dynamic/. Here's the pattern:
http:
routers:
plausible:
rule: "Host(`analytics.yourproject.digitalweb.host`)"
service: plausible-svc
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
plausible-svc:
loadBalancer:
servers:
- url: "http://127.0.0.1:8000"
Duplicate this file for each service, changing the domain and port. Traefik hot-reloads and issues Let's Encrypt certificates automatically.
Backup Strategy
Self-hosting requires you to manage your own backups. A basic strategy:
Database backups:
# Daily PostgreSQL backup to local disk
docker exec postgres pg_dumpall -U admin | gzip > /backups/pg_$(date +%Y%m%d).sql.gz
# Prune backups older than 7 days
find /backups -name "pg_*.sql.gz" -mtime +7 -delete
Off-site replication: Copy backups to an S3-compatible object storage service (Backblaze B2 is $6/TB/month, much cheaper than AWS S3). Use rclone for automated syncing.
Docker volume backups: Use docker run --rm -v volume_name:/data -v /backups:/backup alpine tar czf /backup/volume_$(date +%Y%m%d).tar.gz /data to back up named volumes.
Schedule these with cron and add monitoring via Uptime Kuma's "Heartbeat" monitor type.
Resource Planning
A €3.79/month Hetzner CX11 (1 vCPU, 2 GB RAM) can handle:
- 2–3 small web apps (Node.js, Go, Python)
- PostgreSQL + Redis
- Light traffic (up to ~1,000 requests/minute)
A €6.49/month Hetzner CX21 (2 vCPU, 4 GB RAM) can handle:
- 5–7 apps simultaneously
- PostgreSQL + Redis + Plausible + Uptime Kuma + Gitea
- Medium traffic with room to spare
For most indie developers and freelancers, the CX21 is the sweet spot. Upgrade as you grow.
The Total Cost
| Service | Self-hosted cost | SaaS equivalent |
|---|---|---|
| VPS (Hetzner CX21) | €6.49/month | n/a |
| PostgreSQL | $0 | $25–50/month |
| Redis | $0 | $7–15/month |
| Analytics (Plausible) | $0 | $9–19/month |
| Uptime monitoring | $0 | $7–20/month |
| Custom domains (DomainDock) | $0 | $2–5/domain/month |
| CI/CD | $0 | $8–20/month |
| Total | ~$7/month | $50–130/month |
For a single developer running 3–5 projects, this is a saving of $500–1,500/year.
When Self-Hosting Isn't the Right Choice
Self-hosting makes sense when:
- You're running personal projects, side projects, or small client work
- You have time to manage infrastructure
- Control and cost matter more than convenience
Self-hosting is the wrong choice when:
- You need guaranteed SLAs and managed operations
- Your team doesn't have infrastructure experience and can't afford to develop it
- Revenue-critical systems need enterprise support
For the personal project tier, which describes most indie developers most of the time, self-hosting wins convincingly.
Start with a clean domain. Create your free domain on DomainDock and point it at whatever you're building.