Files
oauth/docs/despliegue.md
Josep Piguillem c2b5291a74 Initial commit: OAuth IAM Laravel application
Laravel-based OAuth/IAM service with Passport, Vue 3 frontend, and
Docker Compose setup for local and production deployment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 01:02:41 +02:00

4.1 KiB

Despliegue en producción (Docker)

Stack: app (PHP-FPM 8.3) + nginx (estáticos y proxy) + db (PostgreSQL 16) + redis (cache/sesión/colas) + queue (worker) + scheduler.

1. Preparar el .env

cp .env.production.example .env

Editar .env y completar como mínimo:

  • APP_URL — dominio real, con https://.
  • DB_PASSWORD — contraseña de PostgreSQL (usada también por el servicio db).
  • SESSION_DOMAIN — dominio (o .tu-dominio.com si hay subdominios).
  • APP_KEY — generar uno nuevo, no reutilizar el de desarrollo:
docker run --rm -v "$PWD":/app -w /app composer:2 sh -c \
  "php -r \"echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;\""

Pegar el resultado en APP_KEY=.

2. Levantar el stack

docker compose -f docker-compose.prod.yml up -d --build

En el primer arranque, el contenedor app (ver docker/php/entrypoint.sh):

  1. Genera las claves RSA de Passport (storage/oauth-private.key / .pub) si no existen — quedan persistidas en el volumen app_storage, no se regeneran en cada deploy (regenerarlas invalidaría todos los tokens ya emitidos).
  2. Corre php artisan migrate --force.
  3. Cachea config/rutas/vistas y regenera la documentación de Swagger.
docker compose -f docker-compose.prod.yml logs -f app

3. Crear el primer usuario admin

Recomendado para producción: no correr db:seed (ese seeder crea datos de demo con contraseñas conocidas). En su lugar, con la base de usuarios vacía, andá a /register y creá una cuenta — al ser la primera, el sistema la marca automáticamente como admin, aprobada y con la sesión iniciada (no hace falta que nadie la apruebe, porque todavía no existe ningún admin). Cualquier registro posterior vuelve a requerir aprobación manual desde el panel de usuarios.

Alternativa solo para entornos de prueba/demo, con datos de ejemplo (usuarios, clientes OAuth, historial de logins falso):

docker compose -f docker-compose.prod.yml exec app php artisan db:seed --force

Esto sí crea admin@example.com / password — cambiar la contraseña de inmediato si se usa fuera de un entorno descartable.

4. TLS

Por defecto nginx sirve solo HTTP en el puerto 80 (docker/nginx/default.conf). Para HTTPS:

  1. Conseguir certificado (por ejemplo con certbot --webroot apuntando a docker/nginx/certs, o cualquier CA propia).
  2. Colocar fullchain.pem y privkey.pem en docker/nginx/certs/.
  3. Descomentar el bloque server { listen 443 ... } en docker/nginx/default.conf y el location / que redirige a HTTPS.
  4. Descomentar "443:443" en docker-compose.prod.yml (servicio nginx).
  5. docker compose -f docker-compose.prod.yml up -d --build nginx.

5. Desplegar una actualización

git pull   # o el mecanismo que uses para traer código nuevo
docker compose -f docker-compose.prod.yml up -d --build

Las claves de Passport, la base de datos y Redis viven en volúmenes con nombre (app_storage, db_data, redis_data) — sobreviven a los rebuilds. El código y los assets del frontend, en cambio, se hornean dentro de la imagen en cada build (no hay bind mounts de código en producción).

6. Backups

Mínimo indispensable a respaldar:

  • Volumen db_data (o mejor, pg_dump periódico contra el servicio db).
  • Volumen app_storage — contiene, entre otras cosas, las claves de Passport. Perderlas invalida todos los tokens emitidos hasta ese momento.
docker compose -f docker-compose.prod.yml exec db \
  pg_dump -U "$DB_USERNAME" "$DB_DATABASE" > backup-$(date +%F).sql

Servicios del compose

Servicio Rol
app PHP-FPM. Corre migraciones y cacheo al arrancar (CONTAINER_ROLE=app).
queue php artisan queue:work redis — misma imagen que app, sin el paso de migración.
scheduler php artisan schedule:work — reemplaza al cron del sistema.
nginx Sirve public/build y hace proxy de *.php a app:9000.
db PostgreSQL 16, datos en el volumen db_data.
redis Cache, sesiones y colas, datos en el volumen redis_data (AOF activado).