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>
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, conhttps://.DB_PASSWORD— contraseña de PostgreSQL (usada también por el serviciodb).SESSION_DOMAIN— dominio (o.tu-dominio.comsi 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):
- Genera las claves RSA de Passport (
storage/oauth-private.key/.pub) si no existen — quedan persistidas en el volumenapp_storage, no se regeneran en cada deploy (regenerarlas invalidaría todos los tokens ya emitidos). - Corre
php artisan migrate --force. - 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:
- Conseguir certificado (por ejemplo con
certbot --webrootapuntando adocker/nginx/certs, o cualquier CA propia). - Colocar
fullchain.pemyprivkey.pemendocker/nginx/certs/. - Descomentar el bloque
server { listen 443 ... }endocker/nginx/default.confy ellocation /que redirige a HTTPS. - Descomentar
"443:443"endocker-compose.prod.yml(servicionginx). 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_dumpperiódico contra el serviciodb). - 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). |