Stack Keycloak + MySQL + API/Web
Servidor: srv-app-01 (Ubuntu 24.04)
Ruta del stack: /opt/apps/stack
Datos persistentes:
- MySQL: /srv/mysql/data
- Keycloak: /srv/keycloak/data
Variables de entorno
Archivo: /etc/stack/stack.env (600)
# MySQL root
MYSQL_ROOT_PASSWORD=********
# Base Keycloak (creada por init si volumen vacío)
MYSQL_DATABASE=keycloak
MYSQL_USER=keycloak
MYSQL_PASSWORD=********
# Conexión que usa KC
KC_DB=mysql
KC_DB_URL_HOST=mysql
KC_DB_URL_PORT=3306
KC_DB_URL_DATABASE=keycloak
KC_DB_NAME=keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD=********
KC_HTTP_ENABLED=true
KC_HOSTNAME=auth.erre.com
KC_HOSTNAME_STRICT=false
KC_PROXY=edge
# App fastfood
FF_DB_NAME=fastfood
FF_DB_USER=fastfood
FF_DB_PASSWORD=********
Servicios (Docker Compose)
Archivo:/opt/apps/stack/docker-compose.yml
Puertos locales:
KC → 127.0.0.1:8080
API → 127.0.0.1:8081
WEB → 127.0.0.1:8082
Operación
cd /opt/apps/stack
sudo docker compose up -d
sudo docker compose ps
sudo docker logs -n 80 keycloak
Salud de MySQL
docker ps --format "table {{.Names}}\t{{.Status}}"
sudo docker logs -n 50 mysql
Init DB fastfood (si hace falta)
sudo docker compose run --rm db-init
sudo docker logs mysql-init
Backups
Script (ejemplo):
mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases --single-transaction > /backups/mysql-$(date +%F).sql
docker run --rm -v /srv/keycloak/data:/data alpine:3 tar czf - /data > /backups/kc-data-$(date +%F).tgz
Seguridad
Exponer servicios solo detrás de Nginx (HTTPS).
Limitar sudo del usuario deploy (NOPASSWD solo para acciones necesarias).
UFW: permitir 22/tcp desde IPs confiables, 80/443 si se publica hacia fuera.
Fail2ban activo para sshd.
Pruebas rápidas
curl -sI https://auth.erre.com | head -n1
curl -sI https://api.erre.com | head -n1
curl -sI https://app.erre.com | head -n1