# Deploy Manual CMS Kevin Victor — Pasos exactos

Este archivo contiene los comandos exactos para terminar el deploy del CMS. **Ejecutar desde tu Mac.**

## Estado actual (al 2026-10-01)

- ✅ Rama `feature/cms-agents` con 22 commits
- ✅ Subdominio `cms.kevinvictorrealestate.com` creado en cPanel (doc root: `/home/wwkevi/cms.kevinvictorrealestate.com`)
- ✅ Dir app + uploads + DB vacía creados en VPS
- ✅ Rsync inicial (120MB) subido
- ⚠️ Falta: A record en Cloudflare
- ⚠️ Falta: completar deploy

## Paso 0: A record en Cloudflare (DNS-only)

1. Ve a https://dash.cloudflare.com → `kevinvictorrealestate.com` → DNS → Records
2. Add record:
   - Type: **A**
   - Name: **cms**
   - IPv4: **162.240.232.251**
   - Proxy: **DNS only** (gris)
   - TTL: Auto
3. Save. Espera 30 seg para propagar.

Verifica:
```bash
dig +short cms.kevinvictorrealestate.com
# Esperado: 162.240.232.251
```

## Paso 1: SSH al VPS y generar AUTH_SECRET

```bash
VPS_PASS='NLyL#8fqhS48qqgC'
SSHPASS="$VPS_PASS" sshpass -e ssh -o StrictHostKeyChecking=no -p 22022 root@162.240.232.251
```

Una vez dentro del VPS:

```bash
cd /home/wwkevi/cms.kevinvictorrealestate.com

# Generar AUTH_SECRET (32 bytes random)
echo "AUTH_SECRET=$(openssl rand -base64 32)"

# (Copia ese valor para usarlo abajo)
```

## Paso 2: Crear `.env.production` (sin password del admin)

```bash
APP_DIR=/home/wwkevi/cms.kevinvictorrealestate.com
AUTH_SECRET='<PEGA_AQUÍ_TU_AUTH_SECRET>'

cat > $APP_DIR/.env.production <<ENVEOF
DATABASE_URL="file:./cms.db"
NEXTAUTH_URL="https://cms.kevinvictorrealestate.com"
AUTH_URL="https://cms.kevinvictorrealestate.com"
AUTH_SECRET="$AUTH_SECRET"
RESEND_API_KEY="re_G8fHdgrr_4eB3TRTCXSoZeBQRcQEvJqFT"
NEXT_PUBLIC_UPLOADS_BASE="https://cms.kevinvictorrealestate.com/uploads"
UPLOADS_DIR="/home/wwkevi/cms.kevinvictorrealestate.com/public/uploads"
ADMIN_EMAIL="kevin@kevinvictorrealestate.com"
EMAIL_FROM="noreply@kevinvictorrealestate.com"
EMAIL_FROM_NAME="Kevin Victor Real Estate"
PORT=3002
NODE_ENV=production
ENVEOF

chmod 600 $APP_DIR/.env.production
chown wwkevi:wwkevi $APP_DIR/.env.production
```

## Paso 3: npm ci + Prisma migrate

```bash
cd $APP_DIR
npm ci --omit=dev 2>&1 | tail -5
npx prisma generate 2>&1 | tail -3
npx prisma migrate deploy 2>&1 | tail -5
```

## Paso 4: Seed (crea admin con password random)

```bash
npx tsx prisma/seed.ts 2>&1
```

**Importante:** el seed imprimirá el password generado. **Cópialo AHORA** porque no se guarda en texto plano (solo el hash).

## Paso 5: PM2 start

```bash
cd $APP_DIR
PORT=3002 pm2 start npm --name kv-cms -- start
pm2 save
pm2 list
# Esperado: kv-cms status = online
```

Verifica que Node está listening:
```bash
ss -tlnp | grep ":3002"
# Esperado: pdns_server OR node ... LISTEN 0 ... 127.0.0.1:3002
curl -sk http://127.0.0.1:3002/login
# Esperado: HTML con form de login
```

## Paso 6: Reemplazar Apache vhost (mod_proxy → Node :3002)

Backup del vhost actual:
```bash
cp /etc/apache2/conf/httpd.conf /etc/apache2/conf/httpd.conf.bak-$(date +%Y%m%d-%H%M%S)

# Encontrar líneas del vhost cms
grep -n "cms.kevinvictorrealestate" /etc/apache2/conf/httpd.conf
```

Voy a crear el nuevo bloque vhost. Editar `/etc/apache2/conf/httpd.conf` y:

1. Buscar la línea que comienza `<VirtualHost ...>` para `cms.kevinvictorrealestate.com`
2. Comentar TODO el bloque vhost con `#` al inicio de cada línea
3. Agregar al FINAL del archivo:

```apache
<VirtualHost *:443>
    ServerName cms.kevinvictorrealestate.com
    ServerAlias www.cms.kevinvictorrealestate.com

    # Proxy todo a Node.js en :3002
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3002/ retry=0 timeout=60
    ProxyPassReverse / http://127.0.0.1:3002/

    # Sirve /uploads directamente desde disco (Apache más rápido que Node)
    Alias /uploads /home/wwkevi/cms.kevinvictorrealestate.com/public/uploads
    <Directory /home/wwkevi/cms.kevinvictorrealestate.com/public/uploads>
        Options -Indexes +FollowSymLinks
        Require all granted
        Header set Cache-Control "public, max-age=31536000, immutable"
    </Directory>

    # Document root ficticio (no se usa, todo va a Node)
    DocumentRoot /home/wwkevi/cms.kevinvictorrealestate.com

    SSLEngine on
    SSLCertificateFile /var/cpanel/certs/cpanel/cms.kevinvictorrealestate.com/cert.pem
    SSLCertificateKeyFile /var/cpanel/certs/cpanel/cms.kevinvictorrealestate.com/key.pem
    SSLCertificateChainFile /var/cpanel/certs/cpanel/cms.kevinvictorrealestate.com/fullchain.pem

    ErrorLog /var/log/apache2/cms.kevinvictorrealestate.com-error.log
    CustomLog /var/log/apache2/cms.kevinvictorrealestate.com-access.log combined
</VirtualHost>
```

## Paso 7: Recargar Apache

```bash
apachectl configtest
# Esperado: "Syntax OK"

systemctl reload httpd
# No output si OK

sleep 2
```

## Paso 8: Smoke test

```bash
# Verificar que el subdominio responde
curl -sk -o /dev/null -w "Login: %{http_code}\n" https://cms.kevinvictorrealestate.com/login
# Esperado: 200

curl -sk -o /dev/null -w "Admin redirect: %{http_code}\n" https://cms.kevinvictorrealestate.com/admin
# Esperado: 307 (redirect a /login)

# Login programático (opcional)
curl -sk -c /tmp/cms-cookies.txt -X POST https://cms.kevinvictorrealestate.com/api/auth/callback/credentials \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=kevin@kevinvictorrealestate.com&password=<PASSWORD_DEL_SEED>&csrfToken=<OBTENLO_DE_LOGIN>"
```

## Troubleshooting

| Problema | Solución |
|----------|----------|
| `Syntax error` en configtest | Revisar `/etc/apache2/conf/httpd.conf.bak-*` para restaurar |
| 502 Bad Gateway | `pm2 list` y `pm2 restart kv-cms` |
| 404 Not Found | El subdominio DNS no propaga todavía, esperar o verificar Cloudflare |
| SSL error | AutoSSL puede tardar 2-5 min. Verificar `ls /var/cpanel/certs/cpanel/cms.kevinvictorrealestate.com/` |
| Login falla | Verificar que el password del seed se copió bien |

## Cleanup

Si algo sale mal y querés revertir TODO:
```bash
# Restaurar vhost anterior
cp /etc/apache2/conf/httpd.conf.bak-<TIMESTAMP> /etc/apache2/conf/httpd.conf
apachectl configtest && systemctl reload httpd

# Detener CMS
pm2 stop kv-cms && pm2 delete kv-cms
```

## Contacto

Si necesitás ayuda durante el deploy, contacta al equipo.