Infraestructura··12 min de lectura

Com muntar un entorn SaaS en un VPS: stack, deploy i automatització

Guia pràctica per configurar un VPS per a projectes SaaS: Caddy, Cloudflare Tunnel, Next.js, Supabase i Resend. Tot automatitzat amb un Makefile. Cost total: 8€/mes.

Per què un VPS i no un PaaS?

Vercel, Railway, Fly.io — tots funcionen bé. Però quan valides varies idees en paral·lel, el cost s'escala ràpid i perds el control de la infraestructura. Un VPS a Hetzner CX22 costa 8€/mes i pots allotjar-hi tants projectes com vulguis. La diferència és que has de gestionar el servidor tu.

El truc és automatitzar-ho tot des del principi perquè la gestió manual no et costi més que el que estalvies.

L'stack escollit

Aquests són els criteris que em guien:

  • Mínima superfície d'atac — res de ports oberts innecessaris
  • Zero configuració TLS manual — vull HTTPS sense pensar-hi
  • Tot al repo — si no és al git, no existeix
  • Reproducible des de zero — poder esborrar el VPS i recrear-ho en 10 min

La taula de decisions:

Capa Tecnologia Per qué
VPS Hetzner CX22 Millor relació preu/rendiment d'Europa
Web server Caddy HTTPS automàtic, config mínima
TLS / proxy Cloudflare Tunnel Cap port 80/443 obert al VPS
Frontend Next.js (App Router) SSG + API routes en un sol projecte
Auth Supabase Auth + DB + Storage gratuïts fins a cert punt
Email Resend API neta, bona deliverability, free tier generós
DNS Cloudflare API completa per automatitzar registres
Analytics Plausible CE Open source, selfhosted, GDPR compliant

La clau: Cloudflare Tunnel

El canvi que més ha simplificat la configuració. En comptes d'obrir ports 80 i 443 al servidor i gestionar certificats, el VPS estableix un túnel sortint cap a Cloudflare. El tràfic arriba xifrat a Cloudflare i Cloudflare el passa al teu servidor per dins del túnel.

Avantatges reals:

  • UFW bloqueja tots els ports web — només queda SSH (2222)
  • TLS gestionat per Cloudflare — cap certificat a renovar
  • El VPS no necessita IP pública accessible directament
# UFW: un sol port obert
ufw allow 2222/tcp comment 'SSH'
ufw default deny incoming

# Tot el web passa pel túnel, sense ports oberts

Estructura del repositori

La filosofia és simple: si no és al repo, no existeix. Cada fitxer de configuració, cada script de deploy, cada regla de firewall — tot al git.

repo/
├── infra/
│   ├── caddy/Caddyfile        # Web server config
│   ├── cloudflare/ingress.yml # Tunnel routes
│   ├── ssh/99-hardening.conf  # SSH hardening
│   └── ufw/rules.sh           # Firewall rules
├── deploy/
│   ├── setup.sh               # Bootstrap del VPS (una vegada)
│   ├── deploy.sh              # Deploy de l'app
│   └── apply-infra.sh         # Aplicar configs d'infra
├── apps/
│   └── tenza/                 # Next.js app
├── scripts/
│   └── cloudflare.py          # DNS via API
└── Makefile                   # Punt d'entrada

El Makefile com a interfície

Mai executes SSH manualment per desplegar. El Makefile és la interfície pública:

# Deploy complet en una comanda
make deploy

# Aplicar canvis d'infraestructura
make apply-infra

# Veure logs en temps real
make logs

# Gestionar el túnel
make tunnel-status
make tunnel-logs

Cada target és idempotent — pots executar-lo tantes vegades com vulguis sense por. Això és crític perquè no has de recordar quin estat té el servidor.

Deploy en 3 passes

El flux de deploy és:

  1. git push — el codi puja a GitHub
  2. git pull al VPS — el servidor baixa el codi
  3. deploy.sh — instala deps, builda i reinicia el servei

Tot automatitzat amb make deploy. El VPS mai necessita accés a GitHub amb credencials especials — simplement fa pull del repo públic (o privat via deploy key).

Email amb Resend i zero configuració DNS manual

Un dels punts de fricció clàssics al muntar un SaaS és l'email: SPF, DKIM, DMARC, configuració del sender... Resend ho simplifica molt, però encara cal configurar els registres DNS.

La solució: un script Python que configura tot via l'API de Cloudflare:

# Configura SPF, DKIM, DMARC i email routing en una comanda
uv run scripts/email_setup.py setup \
  --domain tenza.io \
  --forward-to [email protected] \
  --addresses hola,support

Analytics amb Plausible selfhosted

Google Analytics 4 és massa complex per a validació. Plausible CE (Community Edition) és open source, s'autoposa en Docker al mateix VPS, i dóna les mètriques essencials sense complexitat ni problemes GDPR.

El dashboard en temps real et diu: quants visitors, d'on vénen, quines pàgines visiten i quins UTMs funcionen. Per a validació inicial, és tot el que necessites.

Cost total

Servei Cost/mes Límit gratuït
Hetzner CX22 8€
Cloudflare 0€ DNS + Tunnel gratuïts
Supabase 0€ 500 MB DB, 50K MAU
Resend 0€ 3.000 emails/mes
Plausible CE 0€ Selfhosted al VPS
Total ~8€/mes per a múltiples projectes

Conclusions

Aquest setup no és per a producció a escala — és per a validació ràpida de SaaS. L'objectiu és passar de idea a landing page amb email capture en menys d'un dia, amb tots els fonaments ben posats: domini, email, analytics, deploy automatitzat.

Quan el producte arriba a escala, migres a Vercel/Railway/k8s. Però fins llavors, 8€/mes és prou per aprendre, validar i iterar ràpid.

Construint en públic

Apunta't per rebre les actualitzacions del projecte — stack, decisions, mètriques i aprenentatges.