# HawkHost Deploy — checklist Fase 3.3

Guía paso-a-paso para llevar MaxEditor a producción en HawkHost (cPanel
shared/VPS). Complementa `DEPLOY.md` (genérico) con los detalles
específicos del proveedor.

> **Pre-requisitos**: cuenta cPanel activa, dominio `altoque.tv`
> apuntando al server, acceso SSH habilitado (cPanel → "SSH Access").

### Acceso al server: SSH key vs cPanel Terminal

Dos caminos para ejecutar comandos en el server:

1. **SSH desde la PC local** (lo ideal — permite scripting, scp, rsync).
   - cPanel → SSH Access → Manage SSH Keys → Generate (o Import).
   - Importante: **anotá la passphrase exacta** (sin espacios). Si la
     perdés, no se recupera; hay que cambiarla con el ícono 🔑 en
     "Private Keys" y **re-descargar** la key.
   - Authorize la pública (✓ en "Public Keys").
   - Descargá la privada (⬇ en "Private Keys") y guardala en
     `C:\Users\<TU>\.ssh\maxeditor_hawk`.
   - Validá local antes de conectarte:
     ```powershell
     ssh-keygen -y -f "$env:USERPROFILE\.ssh\maxeditor_hawk" -P 'TU-PASSPHRASE'
     ```
     Si imprime una línea `ssh-rsa AAAA…` la key está OK. Si dice
     `invalid format` → la passphrase no coincide con el archivo.
   - Conectar:
     ```powershell
     ssh -i "$env:USERPROFILE\.ssh\maxeditor_hawk" -p 22 altoquet@172.96.187.176
     ```

2. **cPanel → Terminal** (browser-based shell, fallback si SSH falla).
   - Hace lo mismo (`bash` en `/home/altoque/`) sin necesidad de keys.
   - Útil para pasos 2–5 de este checklist si el SSH local está roto.
   - Limitación: no permite copiar archivos desde tu PC; usá File
     Manager o `wget` desde el repo público.

> **Tip**: los secrets pre-generados para `.env` están en
> `secrets/hawkhost.env.local` (gitignored). Copiá su contenido al
> server vía cPanel File Manager o pegándolo en `nano ~/maxeditor/.env`
> dentro de la Terminal de cPanel.

## Resumen de la pila objetivo

```
  altoque.tv/maxeditor/                        ← React bundle (Vite build)
  altoque.tv/maxeditor/api/  → Passenger/uWSGI ← Django (gunicorn-like)
  altoque.tv/maxeditor/media/                  ← uploads (fuera de DB)
  altoque.tv/maxeditor/download                ← landing del .exe
  HTTPS Let's Encrypt vía cPanel (auto-renew)
  PostgreSQL 14 (cPanel → "PostgreSQL Databases")
  Cron: clearsessions diaria + recover_stale_processing_projects c/30min
```

## 0) Sanity check antes de tocar el server

- [ ] El `.exe` compilado contra `http://127.0.0.1:8000` funciona
      end-to-end (`docs/LOCAL_INSTALL_TEST.md` ejecutado y pasado).
- [ ] Tests smoke verdes:
  ```powershell
  .\.venv\Scripts\python.exe -X utf8 backend\tests\smoke_create_user.py
  .\.venv\Scripts\python.exe -X utf8 backend\tests\smoke_recover_stale_projects.py
  .\.venv\Scripts\python.exe -X utf8 backend\tests\smoke_companion_version_check.py
  .\.venv\Scripts\python.exe -X utf8 backend\tests\smoke_project_import_manifest.py
  ```
- [ ] `git status` limpio en `main` y push hecho al repo (HawkHost va a
      hacer `git pull`).

## 1) Crear la base de datos PostgreSQL

cPanel → **PostgreSQL Databases**:

1. Database name: `altoque_maxeditor` (cPanel le pondrá el prefijo de la
   cuenta, p.ej. `altoque_altoque_maxeditor` — anotar el nombre real).
2. Crear user: `altoque_meditor` con password fuerte (anotar).
3. Asignar el user a la DB con **All Privileges**.

Connection string resultante:

```
postgres://altoque_meditor:<password>@127.0.0.1:5432/altoque_altoque_maxeditor
```

## 2) Clonar el repo y crear el venv

**Versiones disponibles en el server (verificadas 2026-05-04 en `nyc005.arandomserver.com`)**:

- Python system: 3.6.8 (NO usar). Alt-Python: `3.10` y `3.11` en `/opt/alt/`.
  - `/opt/alt/python-internal/bin/python3.11` (recomendado)
  - `/opt/alt/python310/bin/python3.10`
- Node: alt-nodejs hasta `alt-nodejs24` (server tiene 10 por default; `/opt/cpanel/ea-nodejs*` o `scl enable alt-nodejs20 bash`).
- PostgreSQL 10.23 (cliente `psql` en path).
- Git en `/usr/local/cpanel/3rdparty/lib/path-bin/git`.
- Disco home: ~587 GB libres.

Por SSH (cPanel → Terminal o ssh externo):

```bash
cd ~
git clone https://github.com/<org>/video-editor.git maxeditor
cd maxeditor
# Usar Alt-Python 3.11 directamente (NO el python3 del system, que es 3.6):
/opt/alt/python-internal/bin/python3.11 -m venv .venv
source .venv/bin/activate
python --version    # debe decir 3.11.x
pip install -U pip
pip install -r backend/requirements.txt
pip install -r backend/requirements-prod.txt    # postgres + gunicorn + whitenoise
```

> **Frontend**: el Node del server es 10.24 (demasiado viejo para Vite).
> Tres opciones, en orden de simplicidad:
>
> 1. **Build local + scp**: `cd frontend && npm run build` en tu PC, luego
>    `scp -i ~/.ssh/maxeditor_hawk -r dist/* altoquet@172.96.187.176:~/maxeditor/frontend/dist/`.
> 2. Activar Alt-NodeJS 20: `scl enable alt-nodejs20 bash` (si está
>    instalado; si no, pedirlo a soporte o usar opción 1).
> 3. Instalar nvm en `~/`: `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash`
>    → `nvm install 20`.

## 3) Variables de entorno

Crear `~/maxeditor/.env`:

```bash
DJANGO_ENV=production
SECRET_KEY=<generar con `python -c "import secrets;print(secrets.token_urlsafe(60))"`>
ALLOWED_HOSTS=altoque.tv,www.altoque.tv
DATABASE_URL=postgres://altoque_meditor:<password>@127.0.0.1:5432/altoque_altoque_maxeditor
CORS_ALLOWED_ORIGINS=https://altoque.tv,https://www.altoque.tv
CSRF_TRUSTED_ORIGINS=https://altoque.tv,https://www.altoque.tv
DJANGO_USE_HTTPS=True
BYOK_FERNET_KEY=<generar con `python -c "from cryptography.fernet import Fernet;print(Fernet.generate_key().decode())"`>
FRONTEND_LOGIN_URL=/maxeditor/login
OPENAI_API_KEY=<la del workspace compartido>
LOG_DIR=/home/altoque/logs/maxeditor
```

```bash
chmod 600 ~/maxeditor/.env       # protege secrets
mkdir -p ~/logs/maxeditor
```

## 4) Migraciones + collectstatic + superuser

```bash
cd ~/maxeditor
source .venv/bin/activate
cd backend
python manage.py migrate --noinput
cd ..
# Build del frontend (puede hacerse local + commit, o en el server)
cd frontend && npm ci && npm run build && cd ..
cd backend && python manage.py collectstatic --noinput --clear && cd ..
# Crear admin de oficina
python backend/manage.py create_admin_user --email admin@altoque.tv --name "Admin"
```

## 5) Servir con Passenger (cPanel) o gunicorn + nginx (VPS)

### 5a) cPanel "Setup Python App" (shared)

1. cPanel → **Setup Python App** → Create.
2. Python version: **3.11** (es lo más nuevo verificado en este server).
3. Application root: `~/maxeditor/backend`.
4. Application URL: `altoque.tv/maxeditor/api`.
5. Application startup file: `config/wsgi.py`.
6. Application Entry point: `application`.
7. En "Environment variables" pegar las del `.env` (Passenger no lee
   `.env`; o usar `python-dotenv` en `wsgi.py`).
8. **Restart** la app cada vez que cambies código (`touch
   ~/maxeditor/tmp/restart.txt` también funciona).

### 5b) gunicorn + nginx (VPS)

```bash
gunicorn config.wsgi:application \
  --chdir ~/maxeditor/backend \
  --bind 127.0.0.1:8001 \
  --workers 3 --timeout 120 \
  --access-logfile ~/logs/maxeditor/access.log \
  --error-logfile ~/logs/maxeditor/error.log
```

nginx `server` block (resumen):

```nginx
location /maxeditor/api/  { proxy_pass http://127.0.0.1:8001/; proxy_set_header Host $host; }
location /maxeditor/media/ { alias /home/altoque/maxeditor/backend/media/; }
location /maxeditor/static/ { alias /home/altoque/maxeditor/backend/staticfiles/; }
location /maxeditor/        { alias /home/altoque/maxeditor/frontend/dist/; try_files $uri /maxeditor/index.html; }
```

## 6) HTTPS con Let's Encrypt

cPanel → **SSL/TLS Status** → "Run AutoSSL". Verificar que
`altoque.tv` y `www.altoque.tv` tengan cert válido. Auto-renew lo maneja
cPanel.

## 7) Cron jobs

cPanel → **Cron Jobs**:

```cron
# Cada 30 min: recuperar projects atascados en processing por crash/reload
*/30 * * * * cd /home/altoque/maxeditor && /home/altoque/maxeditor/.venv/bin/python backend/manage.py recover_stale_processing_projects --stale-after 1800 >> /home/altoque/logs/maxeditor/recover.log 2>&1

# Diario 03:00: limpiar sesiones expiradas
0 3 * * * cd /home/altoque/maxeditor && /home/altoque/maxeditor/.venv/bin/python backend/manage.py clearsessions
```

## 8) Smoke en producción

Desde tu PC local:

```powershell
# 1) Health
curl https://altoque.tv/maxeditor/api/health/
# 2) Login
curl -X POST https://altoque.tv/maxeditor/api/auth/login/ -H "Content-Type: application/json" -d '{"email":"admin@altoque.tv","password":"..."}'
# 3) Frontend
curl https://altoque.tv/maxeditor/   # debe servir index.html
```

Después: rebuild local del `.exe` apuntando a producción (sin
`-LocalBackendUrl`, queda con `BUILD_BACKEND_URL=None` →
`https://altoque.tv/maxeditor`):

```powershell
.\tools\build_local_distribution.ps1 -SkipFrontend -SkipCollectStatic -SkipInstaller
```

Probar el `.exe` en una PC limpia: login → cargar un proyecto → editar →
exportar.

## 9) Configurar la página de descarga

Subir `MaxEditor_Setup_v0.X.X.exe` a `/home/altoque/maxeditor/frontend/public/downloads/`
(o S3/B2 si la cuota de cPanel no alcanza). Actualizar
`COMPANION_LATEST_VERSION` y `COMPANION_DOWNLOAD_URL` en backend
settings + `manifest` endpoint.

## 10) Rollback plan

Si algo falla en producción:

1. `cd ~/maxeditor && git log --oneline -5` → identificar último commit estable.
2. `git checkout <sha>`.
3. `source .venv/bin/activate && cd backend && python manage.py migrate <app> <migration_anterior>` (si migration es la culpable).
4. `touch tmp/restart.txt` para que Passenger recargue.
5. Backup de DB previo a cualquier deploy: `pg_dump altoque_altoque_maxeditor > ~/backups/maxeditor_$(date +%F).sql`.

## Checklist final pre-anuncio

- [ ] `https://altoque.tv/maxeditor/` carga el editor sin errores en consola.
- [ ] Login con `admin@altoque.tv` funciona y devuelve JWT.
- [ ] Crear proyecto + subir video + transcribir + exportar OK.
- [ ] El `.exe` instalado en una PC limpia se conecta a producción.
- [ ] Cron de `recover_stale` corre y deja log.
- [ ] HTTPS válido (sin warnings) y HSTS activo.
- [ ] Backup nocturno de DB programado.
