Configurar despliegue con Docker, Traefik y Authentik
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 27s

- Agregar Dockerfile para build multi-stage con Node 20
- Configurar docker-compose.yml con Traefik y Authentik exteriorlvl2
- Crear workflow de Gitea Actions para CI/CD automático
- Configurar routers público (assets) y protegido (app + APIs)
- Documentar arquitectura y proceso de despliegue
This commit is contained in:
2025-10-27 12:00:05 -06:00
commit 4c729866aa
13 changed files with 3091 additions and 0 deletions

83
docker-compose.yml Normal file
View File

@@ -0,0 +1,83 @@
services:
photo-server:
image: gitea.nucleoriofrio.com/nucleo000/photo-server:latest
container_name: photo-server
restart: unless-stopped
volumes:
# Mount photos directory from server
- /srv/photo-server/photos:/app/photos:ro
environment:
- NODE_ENV=production
- PORT=3001
networks:
- principal
labels:
# Habilitar Traefik
- "traefik.enable=true"
# ==========================================
# Router público para recursos estáticos (sin autenticación)
# Assets: CSS, JS, favicon, etc.
# ==========================================
- "traefik.http.routers.photos-nucleoriofrio-public.rule=Host(`photos.nucleoriofrio.com`) && (PathPrefix(`/styles.css`) || PathPrefix(`/main.js`) || Path(`/favicon.ico`)) && !PathPrefix(`/api/`)"
- "traefik.http.routers.photos-nucleoriofrio-public.entrypoints=websecure"
- "traefik.http.routers.photos-nucleoriofrio-public.tls.certresolver=letsencrypt"
- "traefik.http.routers.photos-nucleoriofrio-public.priority=100"
- "traefik.http.routers.photos-nucleoriofrio-public.middlewares=photos-static-headers"
- "traefik.http.routers.photos-nucleoriofrio-public.service=photos-nucleoriofrio-service"
# ==========================================
# Router protegido para el resto de la app
# ==========================================
# IMPORTANTE: Todas las APIs y contenido principal requieren autenticación
# - /api/photos → Lista de fotos (requiere auth)
# - /api/photos/zip → Descarga ZIP (requiere auth)
# - /photos/:name → Ver foto individual (requiere auth)
# - Página principal (/) → Requiere auth
- "traefik.http.routers.photos-nucleoriofrio.rule=Host(`photos.nucleoriofrio.com`)"
- "traefik.http.routers.photos-nucleoriofrio.entrypoints=websecure"
- "traefik.http.routers.photos-nucleoriofrio.tls.certresolver=letsencrypt"
- "traefik.http.routers.photos-nucleoriofrio.priority=50"
# Middlewares (orden: auth -> headers -> body-size)
- "traefik.http.routers.photos-nucleoriofrio.middlewares=photos-authentik,photos-headers,photos-body-size"
- "traefik.http.routers.photos-nucleoriofrio.service=photos-nucleoriofrio-service"
# ==========================================
# Middleware: Authentik ForwardAuth (mismo que rioCata)
# ==========================================
- "traefik.http.middlewares.photos-authentik.forwardauth.address=http://ak-outpost-exterior-lvl2:9000/outpost.goauthentik.io/auth/traefik"
- "traefik.http.middlewares.photos-authentik.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.photos-authentik.forwardauth.authResponseHeaders=X-Authentik-Username,X-Authentik-Email,X-Authentik-Name,X-Authentik-Uid,X-Authentik-Groups,X-Authentik-Entitlements"
# ==========================================
# Middleware: Headers para assets estáticos
# ==========================================
- "traefik.http.middlewares.photos-static-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.photos-static-headers.headers.customrequestheaders.X-Forwarded-Scheme=https"
- "traefik.http.middlewares.photos-static-headers.headers.customresponseheaders.X-Content-Type-Options=nosniff"
- "traefik.http.middlewares.photos-static-headers.headers.customresponseheaders.X-XSS-Protection=1; mode=block"
- "traefik.http.middlewares.photos-static-headers.headers.customresponseheaders.Cache-Control=public, max-age=86400"
# ==========================================
# Middleware: Headers personalizados para app protegida
# ==========================================
- "traefik.http.middlewares.photos-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.photos-headers.headers.customrequestheaders.X-Forwarded-Scheme=https"
- "traefik.http.middlewares.photos-headers.headers.customresponseheaders.X-Frame-Options=SAMEORIGIN"
- "traefik.http.middlewares.photos-headers.headers.customresponseheaders.X-Content-Type-Options=nosniff"
- "traefik.http.middlewares.photos-headers.headers.customresponseheaders.X-XSS-Protection=1; mode=block"
# ==========================================
# Middleware: Tamaño máximo de body (500MB para fotos grandes y ZIP)
# ==========================================
- "traefik.http.middlewares.photos-body-size.buffering.maxrequestbodybytes=524288000"
# ==========================================
# Service
# ==========================================
- "traefik.http.services.photos-nucleoriofrio-service.loadbalancer.server.port=3001"
- "traefik.http.services.photos-nucleoriofrio-service.loadbalancer.passhostheader=true"
networks:
principal:
external: true