TrafficServerLocal/docs/arquitectura.md
merios c324093c0a docs: autoria institucional del laboratorio
Agrega el credito "Laboratorio de investigacion en Software Libre
Gugler - FCyT" en el encabezado y la seccion Licencia del README, y
como pie en ambos documentos de docs/.

Se documenta la exencion institucional en la politica de publicacion
anonima: el nombre del laboratorio y git.gugler.com.ar son publicos por
decision propia y no se anonimizan. El verificador recibe una lista
blanca que separa autores institucionales de los que hay que revisar, y
excluye el dominio del laboratorio del filtro de emails.
2026-10-15 11:59:23 -03:00

6.0 KiB

Arquitectura del servidor y gestión de URLs

Guía de instalación del entorno base en el host (~/srv), despliegue de la infraestructura común y alta de proyectos Docker enlazados al proxy inverso.

Documento de referencia. Para el detalle fino de etiquetas TLS ver http-https.md.


1. Configuración inicial del host

1.1 Estructura base y red Docker

mkdir -p ~/srv/core ~/srv/projects
docker network create proxy_network

Permisos para usar Docker sin sudo:

sudo usermod -aG docker "$USER"
newgrp docker

1.2 Habilitar el script generador

chmod +x ~/srv/init_project.sh

2. Puesta en marcha del reverse proxy (~/srv/core)

Opción A — Traefik (detección automática por etiquetas)

~/srv/core/docker-compose.yml:

services:
  traefik:
    image: traefik:v3.0
    container_name: core-proxy
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
    networks:
      - proxy_network

networks:
  proxy_network:
    external: true

Configuración estática ~/srv/core/data/traefik.yml:

api:
  dashboard: true
  insecure: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    network: "proxy_network"
    exposedByDefault: false
  file:
    filename: "/etc/traefik/dynamic_tls.yml"
    watch: true

Inicialización del almacenamiento de certificados:

mkdir -p ~/srv/core/data
touch ~/srv/core/data/acme.json
chmod 600 ~/srv/core/data/acme.json

Arranque:

cd ~/srv/core && docker compose up -d

Opción B — Nginx Proxy Manager (panel web)

Misma idea, pero la configuración se hace desde la interfaz:

  1. Entrar a http://<IP-SERVIDOR>:81.
  2. Hosts → Proxy Hosts → Add Proxy Host.
    • Domain Names: api.midominio.com
    • Scheme: http
    • Forward Hostname / IP: nombre del contenedor en proxy_network
    • Forward Port: puerto interno del contenedor
    • Block Common Exploits: activado
  3. Pestaña SSL → Request a new SSL Certificate → Force SSL.
  4. Save.

3. Alta de proyectos

Paso 1 — Crear la estructura limpia

~/srv/init_project.sh api-ventas api.midominio.com 80

Genera:

~/srv/projects/api-ventas/
├── app/                  # Código, repo o Dockerfile
├── data/
│   ├── db/
│   └── storage/
├── .env                  # Variables de entorno (chmod 600)
└── docker-compose.yml    # Plantilla conectada a proxy_network

Paso 2 — Colocar el proyecto

# Clonando un repositorio
git clone https://github.com/tu-usuario/api-ventas.git ~/srv/projects/api-ventas/app/

# O copiando archivos locales
cp -r /ruta/a/tus/archivos/* ~/srv/projects/api-ventas/app/

Paso 3 — Ajustar docker-compose.yml

  • Build local: descomentar
    build:
      context: ./app
      dockerfile: Dockerfile
    
  • Imagen ya publicada: reemplazar image: <proyecto>:latest
  • Servicios adicionales (Postgres, Redis): agregarlos en el mismo archivo usando la red default, así quedan aislados del proxy.

Paso 4 — Levantar

cd ~/srv/projects/api-ventas
docker compose up -d

Paso 5 — Post-instalación (opcional, apps Laravel)

docker exec -it <proyecto>-web composer install --no-interaction --prefer-dist
docker exec -it <proyecto>-web php artisan key:generate --force
docker exec -it <proyecto>-web php artisan migrate --force
docker exec -it <proyecto>-web php artisan optimize:clear

Verificar permisos si el usuario www-data no puede escribir:

docker exec -it <proyecto>-web chown -R www-data:www-data /var/www/<app>/storage
docker exec -it <proyecto>-web chmod -R 775 /var/www/<app>/storage /var/www/<app>/bootstrap/cache

4. Dónde y cómo se registran las URLs

Traefik (automático)

El registro se hace con etiquetas en el docker-compose.yml del proyecto:

labels:
  - "traefik.enable=true"
  - "traefik.docker.network=proxy_network"
  - "traefik.http.routers.api-ventas.rule=Host(`api.midominio.com`)"
  - "traefik.http.routers.api-ventas.entrypoints=websecure"
  - "traefik.http.routers.api-ventas.tls=true"
  - "traefik.http.routers.api-ventas.tls.certresolver=letsencrypt"
  - "traefik.http.services.api-ventas.loadbalancer.server.port=80"

Traefik lee el socket de Docker, detecta el contenedor, genera el enrutamiento y solicita el certificado SSL automáticamente.

Nginx Proxy Manager (panel web)

Ver Opción B.


5. Copias de seguridad

Los respaldos se guardan fuera de los repositorios Git:

# PostgreSQL
docker exec <cont-pg> pg_dump -U <user> <db> > ~/srv/backups/<proyecto>-$(date +%F).sql

# MySQL
docker exec <cont-mysql> mysqldump -u<user> -p <db> > ~/srv/backups/<proyecto>-$(date +%F).sql

# Archivos
tar czf ~/srv/backups/<proyecto>-files-$(date +%F).tar.gz ~/srv/projects/<proyecto>/data

Sugerencia de rotación (crontab diario a las 3:00):

0 3 * * * /usr/local/bin/backup-proyectos.sh >> ~/srv/backups/backup.log 2>&1

6. Resumen de convenciones

Elemento Convención
Carpeta de proyecto ~/srv/projects/<nombre>/
Nombre del contenedor <nombre>-web
Red del proxy proxy_network (externa)
Red interna default (bridge, aislada)
Secretos ~/srv/projects/<nombre>/.env con chmod 600
Dominios locales <proyecto>.local
Certificados .local ~/srv/core/data/certs/ + dynamic_tls.yml
Certificados públicos Let's Encrypt vía acme.json

Autoría: Laboratorio de investigacion en Software Libre Gugler - FCyT. Distribuido bajo GPL-3.0 (ver LICENSE).