# Despliegue en VPS (Docker) — Teletón Rifa

Esta app **no es un sitio estático ni PHP**: es un servidor Node.js (Next.js 16) con
base de datos y pasarela de pago del lado del servidor. **No se puede subir por FTP a
hosting compartido.** Necesita un VPS donde corra un proceso permanente.

Este paquete (Dockerfile + docker-compose) la deja corriendo con un comando.

---

## 1. Requisitos del servidor

- Un **VPS** con Linux (Ubuntu 22.04+ recomendado) y acceso **SSH (root o sudo)**.
- **Docker** + **Docker Compose v2** instalados:
  ```bash
  curl -fsSL https://get.docker.com | sh
  ```
- **DNS**: un registro **A** `rifa.teleton.pe` -> IP pública del VPS (en GoDaddy).
- **Puertos 80 y 443 abiertos** en el firewall del VPS.

## 2. Subir el código al VPS

Opción recomendada (git):
```bash
git clone <repo> teleton-rifa && cd teleton-rifa
```
O sube el archivo `teleton-rifa-deploy.zip` (fuente limpia, sin secretos ni
node_modules), descomprímelo en el VPS y entra a la carpeta.

> NUNCA subas `.env.local` ni `node_modules` ni `.next`. El deploy los reconstruye.

## 3. Configurar el entorno

```bash
cp .env.production.example .env.production
nano .env.production
```

Llena **como mínimo** (lo demás tiene defaults):

| Variable | Qué es |
|---|---|
| `NEXT_PUBLIC_APP_URL` | `https://rifa.teleton.pe` (se hornea en el build) |
| `RIFA_DOMAIN`, `ACME_EMAIL` | dominio para el certificado HTTPS + correo de contacto |
| `POSTGRES_PASSWORD` + `DATABASE_URL`/`DIRECT_URL` | contraseña fuerte de la BD (o apunta a una BD administrada) |
| `NIUBIZ_MERCHANT_ID` = `650236685`, `NIUBIZ_USER`, `NIUBIZ_PASSWORD` | credenciales **reales** de Niubiz |
| `RESEND_API_KEY`, `RESEND_FROM_EMAIL` | para que el comprador reciba sus números por correo |
| `UPSTASH_*`, `TURNSTILE_*` | rate-limit y anti-bot (en prod) |
| `ADMIN_SESSION_SECRET` (>=16 chars), `ADMIN_ALLOWLIST`, `CRON_SECRET` | admin + cron |

**Contraseña del admin (ADMIN_ALLOWLIST):** el formato es
`correo:rol:scrypt$salt$hash`. Genera el hash una vez:
```bash
docker run --rm -v "$PWD":/src -w /src node:20 \
  sh -c "npm ci --silent && npx tsx -e 'import{hashPassword}from\"./lib/auth\";console.log(hashPassword(\"TU_CLAVE\"))'"
# pega el resultado en ADMIN_ALLOWLIST, por ejemplo:
# ADMIN_ALLOWLIST="ops@teleton.pe:admin:scrypt$abcd...$ef01..."
```
> En este archivo el hash va con `$` **normal** (es una variable de entorno del SO,
> no un archivo dotenv, así que NO se escapa con `\$`). Si Compose se queja del `$`,
> duplícalo a `$$`.

## 4. Migrar la base de datos (una sola vez)

Levanta primero solo la BD y aplica el esquema:
```bash
docker compose --env-file .env.production up -d db

# aplica el esquema con drizzle (usa la red de compose para llegar a "db"):
docker run --rm -v "$PWD":/src -w /src --env-file .env.production \
  --network "$(basename "$PWD")_default" \
  node:20 sh -c "npm ci --silent && npm run db:push"
```
(Si usas una BD administrada externa, omite `up -d db` y solo corre el `db:push`.)

## 5. Construir y arrancar

```bash
docker compose --env-file .env.production up -d --build
```
Esto construye la imagen y levanta app + Postgres + Caddy. Caddy pide el certificado
HTTPS automáticamente (necesita el DNS ya apuntando + puertos 80/443 abiertos).

## 6. Verificar

```bash
docker compose ps                 # todos "running"/"healthy"
docker compose logs -f app        # busca "Ready" / sin errores
curl -I https://rifa.teleton.pe   # 200
```
Entra a `https://rifa.teleton.pe/admin/login` con la cuenta de `ADMIN_ALLOWLIST`.

## 7. Cron de reconciliación

La app tiene un endpoint de conciliación protegido por `CRON_SECRET`. Agrega al
crontab del VPS (`crontab -e`):
```
*/30 * * * * curl -fsS -H "Authorization: Bearer TU_CRON_SECRET" https://rifa.teleton.pe/api/cron/reconcile >/dev/null 2>&1
```

## 8. Actualizar a una versión nueva

```bash
git pull        # o vuelve a subir el zip
docker compose --env-file .env.production up -d --build
```

---

## Alternativas

- **Tu propio nginx en vez de Caddy:** elimina el servicio `caddy`, publica el puerto
  del `app` (`ports: ["127.0.0.1:3000:3000"]`) y apunta tu nginx a
  `http://127.0.0.1:3000` con tu certificado.
- **BD administrada (Supabase/Neon):** pon sus URLs en `DATABASE_URL`/`DIRECT_URL` y
  borra el servicio `db` + el `depends_on`.

## Notas de seguridad

- `DEMO_MODE` debe quedar **vacío** en la rifa real (además la app se auto-protege si
  `NEXT_PUBLIC_APP_URL` contiene `teleton.pe`).
- No publiques `.env.production` en git ni por FTP.
- El sorteo es verificable públicamente en `https://rifa.teleton.pe/sorteo/verificar`.
