# Deploy en Produccion (Docker + CI/CD) - Direccion de Admision 2026

Todo el proyecto se dockeriza y se despliega mediante **GitHub Actions**. Las imagenes se construyen en GitHub y se suben a GitHub Container Registry (GHCR). El VPS solo descarga y ejecuta.

## Resumen rapido — ¿Que hago yo?

### Setup inicial (solo una vez, ~25 min)

| Paso | Que haces | Donde | Tiempo |
|---|---|---|---|
| 1 | Pegar 6 secrets en GitHub | Navegador (GitHub Settings) | 5 min |
| 2 | Conectar al VPS, clonar repo, crear `.env.prod` y editar valores | Terminal SSH | 10 min |
| 3 | Copiar/pegar 2 comandos para MySQL + importar dump | Terminal SSH | 2 min |
| 4 | Clic en "Run workflow" en GitHub Actions y esperar | Navegador (GitHub Actions) | 3 min |
| 5 | Copiar/pegar 2 comandos (storage link + seeders) | Terminal SSH | 1 min |
| 6 | Copiar/pegar server block de nginx + correr certbot | Terminal SSH | 5 min |

### Deploys del dia a dia

| Tu haces | Que pasa |
|---|---|
| `git push` a main | Nada (hasta que tu decidas) |
| Clic en **"Run workflow"** en GitHub Actions | Build + Push al registry + Deploy al VPS (~3 min) |

**No tocas terminal, no compilas, no haces SSH. Solo un clic desde el navegador.**

---

## Arquitectura de deploy

```
  Tu PC                 GitHub                  GHCR              VPS
    |                      |                      |                |
    | git push            |                      |                |
    | ──────────►   [main branch]                |                |
    |                      |                      |                |
    |              [GitHub Actions]               |                |
    |              (trigger manual)               |                |
    |                      |                      |                |
    |              Build backend  ──────►  ghcr.io/.../backend    |
    |              Build frontend ──────►  ghcr.io/.../frontend   |
    |                      |                      |                |
    |              SSH al VPS ────────────────────────────►       |
    |                      |                      |    docker pull |
    |                      |                      |    docker up   |
    |                      |                      |     App lista  |
```

## Arquitectura de contenedores

```
                    Puerto 80/443
                         |
                  [nginx del host]  ← SSL/Certbot
                         |
                    proxy_pass
                         |
                  127.0.0.1:8080
                         |
                  [nginx container]  (reverse proxy)
                    /         \
         /api/*   /           \   /*
                 /             \
          [backend]         [frontend]
          PHP-FPM            nginx+SPA
          :9000               :80
              |
           [mysql]
            :3306
```

---

## De donde sale cada credencial

Hay 3 lugares donde se ponen credenciales. Esta tabla explica cada una y como obtenerla:

### A. Archivo `.env.prod` (en el VPS)

| Credencial | Como la obtienes |
|---|---|
| `APP_KEY` | Ejecutas `php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;"` en tu PC y copias el resultado |
| `DB_PASSWORD` | La inventas tu. Para generar una segura: `openssl rand -base64 32` |
| `APP_URL` | Tu dominio (ej: `https://admision.tu-universidad.edu.pe`) |
| `SESSION_DOMAIN` | Tu dominio sin https (ej: `admision.tu-universidad.edu.pe`) |
| `SANCTUM_STATEFUL_DOMAINS` | Igual que SESSION_DOMAIN |
| `GITHUB_REPO` | Tu usuario/repo de GitHub (ej: `juanperez/direccion_de_admision_2026`) |
| `MAIL_PASSWORD` | Te lo da tu proveedor SMTP (Gmail, Mailgun, etc.) |

### B. GitHub Secrets (en el navegador)

| Secret | Como lo obtienes |
|---|---|
| `VPS_HOST` | La IP de tu droplet, la ves en el panel de DigitalOcean |
| `VPS_USER` | Normalmente `root` |
| `VPS_SSH_KEY` | El contenido de la clave privada SSH (ver paso 1 abajo) |
| `VPS_PORT` | Normalmente `22` |
| `VPS_PROJECT_PATH` | La ruta donde clonas el repo (ej: `/root/direccion_de_admision_2026`) |
| `CR_PAT` | Token que generas en GitHub > Settings > Developer settings > Tokens |

### C. Se generan automaticamente (no los tocas)

| Credencial | Descripcion |
|---|---|
| `GITHUB_TOKEN` | GitHub Actions lo crea solo en cada ejecucion |
| `MYSQL_ROOT_PASSWORD` | Docker lo lee de `DB_PASSWORD` del `.env.prod` |

---

## Setup inicial (solo la primera vez)

### 1. Crear clave SSH en el VPS y configurar secrets en GitHub

GitHub Actions necesita conectarse al VPS por SSH. Si actualmente entras con contraseña, necesitas crear una clave SSH.

**En el VPS** (conectate con tu contraseña como siempre):

```bash
# Generar clave SSH para GitHub Actions
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions -N ""

# Agregar la clave publica a las claves autorizadas
cat ~/.ssh/github_actions.pub >> ~/.ssh/authorized_keys

# Mostrar la clave PRIVADA (la que copias a GitHub)
cat ~/.ssh/github_actions
```

> Copia TODO el contenido que muestra el ultimo comando (desde `-----BEGIN` hasta `-----END`). Esa es la clave que pegas en GitHub como secret `VPS_SSH_KEY`.

**En GitHub** (navegador):

1. Ir a tu repo > **Settings** > **Secrets and variables** > **Actions**
2. Clic en **"New repository secret"** y agregar uno por uno:

| Secret | Que pegar |
|---|---|
| `VPS_HOST` | La IP de tu droplet (ej: `164.92.xxx.xxx`) |
| `VPS_USER` | `root` |
| `VPS_SSH_KEY` | El contenido completo de `~/.ssh/github_actions` (clave privada) |
| `VPS_PORT` | `22` |
| `VPS_PROJECT_PATH` | `/root/direccion_de_admision_2026` |
| `CR_PAT` | El token generado en el siguiente paso |

### Generar el CR_PAT (Personal Access Token)

1. Ir a GitHub > tu foto (esquina superior derecha) > **Settings**
2. Ir a **Developer settings** > **Personal access tokens** > **Tokens (classic)**
3. Clic en **"Generate new token (classic)"**
4. Nombre: `deploy-admision` | Expiracion: 90 dias o sin expiracion
5. Marcar permisos: `read:packages`, `write:packages`
6. Clic en **"Generate token"**
7. Copiar el token y guardarlo como secret `CR_PAT` en el repo

---

### 2. Preparar el VPS

**En el VPS** (por SSH):

```bash
# Instalar Docker si no lo tienes
curl -fsSL https://get.docker.com | sh

# Clonar el repo
git clone <url-del-repo> direccion_de_admision_2026
cd direccion_de_admision_2026

# Configurar variables de entorno
cp .env.prod.example .env.prod
```

Editar `.env.prod`:

```bash
nano .env.prod
```

Cambiar estos valores **obligatoriamente**:

```
APP_KEY=               # Pegar la clave generada (ver abajo)
APP_URL=https://tu-dominio.com
DB_PASSWORD=           # Pegar la password generada (ver abajo)
SESSION_DOMAIN=tu-dominio.com
SANCTUM_STATEFUL_DOMAINS=tu-dominio.com
GITHUB_REPO=tu-usuario/tu-repo
```

Para generar APP_KEY (en tu PC local si no hay PHP en el VPS):

```bash
php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;"
```

Para generar DB_PASSWORD:

```bash
openssl rand -base64 32
```

Asegurar permisos del archivo:

```bash
chmod 600 .env.prod
```

### Credenciales de la base de datos

La base de datos MySQL se crea automaticamente con estos valores (definidos en `.env.prod`):

| Variable | Valor | Descripcion |
|---|---|---|
| `DB_HOST` | `mysql` | Nombre del contenedor Docker (no cambiar) |
| `DB_PORT` | `3306` | Puerto interno de MySQL (no cambiar) |
| `DB_DATABASE` | `admision_2026` | Nombre de la base de datos |
| `DB_USERNAME` | `root` | Usuario de MySQL |
| `DB_PASSWORD` | Lo que pongas en `.env.prod` | La misma password para todo: MySQL root y conexion Laravel |

> **Importante:** La password que pongas en `DB_PASSWORD` es la que usa Docker para crear el usuario root de MySQL **y** la que usa Laravel para conectarse. Debe ser la misma en ambos casos porque es una sola variable. Esta misma password es la que usas en los comandos de importacion donde dice `TU_PASSWORD`.

---

### 3. Levantar MySQL e importar la base de datos

```bash
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d mysql
```

Esperar ~10 segundos y luego importar:

```bash
docker exec -i admision_prod_db mysql -uroot -pTU_PASSWORD admision_2026 < admision_2006-vI.sql
```

Verificar:

```bash
docker exec admision_prod_db mysql -uroot -pTU_PASSWORD admision_2026 -e "SHOW TABLES;"
```

---

### 4. Primer deploy

Ir a GitHub > pestaña **Actions** > seleccionar **"Build & Deploy"** > clic en **"Run workflow"** > marcar **"Desplegar en el VPS"** > confirmar.

GitHub Actions construira las imagenes, las subira al registry y las desplegara en el VPS.

---

### 5. Post-deploy (solo la primera vez)

```bash
# Crear enlace de storage
docker exec admision_prod_backend php artisan storage:link

# Ejecutar seeders
docker exec admision_prod_backend php artisan db:seed --class=RoleSeeder --force
```

---

### 6. Configurar nginx del host como proxy

Crear o editar el server block:

```bash
sudo nano /etc/nginx/sites-available/tu-dominio.com
```

```nginx
server {
    listen 80;
    server_name tu-dominio.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        client_max_body_size 25M;
    }
}
```

```bash
sudo ln -sf /etc/nginx/sites-available/tu-dominio.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```

Para HTTPS:

```bash
sudo certbot --nginx -d tu-dominio.com
```

---

## Deploys posteriores

Solo necesitas ir a GitHub > **Actions** > **Run workflow**. Eso es todo.

O si prefieres activar deploy automatico en cada push a main, edita `.github/workflows/deploy.yml` y agrega:

```yaml
on:
  workflow_dispatch:
  push:
    branches: [main]
```

---

## Comandos utiles en el VPS

```bash
# Ver logs
docker compose --env-file .env.prod -f docker-compose.prod.yml logs -f

# Ver logs de un servicio
docker compose --env-file .env.prod -f docker-compose.prod.yml logs -f backend

# Reiniciar todo
docker compose --env-file .env.prod -f docker-compose.prod.yml restart

# Detener todo
docker compose --env-file .env.prod -f docker-compose.prod.yml down

# Ejecutar comandos artisan
docker exec admision_prod_backend php artisan migrate --force
docker exec admision_prod_backend php artisan cache:clear

# Ver que imagenes estan corriendo
docker compose --env-file .env.prod -f docker-compose.prod.yml ps
```

---

## Rollback (volver a una version anterior)

Cada imagen se etiqueta con el SHA del commit. Para volver a una version anterior:

```bash
# En .env.prod cambiar IMAGE_TAG al SHA del commit deseado
IMAGE_TAG=abc123def456

# Recrear contenedores
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --force-recreate backend frontend nginx
```

---

## Notas de produccion

- Los datos de MySQL se persisten en un volumen Docker (`mysql_data`)
- El storage de Laravel se persiste en un volumen Docker (`backend_storage`)
- El archivo `.env.prod` **nunca** debe subirse al repositorio (esta en `.gitignore`)
- Siempre usar `--env-file .env.prod` en los comandos de Docker Compose
- Las imagenes en GHCR son **privadas** (solo tu cuenta las ve)
- Para HTTPS, usar Certbot en el nginx del host
