# 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`](http-https.md). --- ## 1. Configuración inicial del host ### 1.1 Estructura base y red Docker ```bash mkdir -p ~/srv/core ~/srv/projects docker network create proxy_network ``` Permisos para usar Docker sin `sudo`: ```bash sudo usermod -aG docker "$USER" newgrp docker ``` ### 1.2 Habilitar el script generador ```bash 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`: ```yaml 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`: ```yaml 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: ```bash mkdir -p ~/srv/core/data touch ~/srv/core/data/acme.json chmod 600 ~/srv/core/data/acme.json ``` Arranque: ```bash 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://: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 ```bash ~/srv/init_project.sh api-ventas api.midominio.com 80 ``` Genera: ```text ~/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 ```bash # 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 ```yaml build: context: ./app dockerfile: Dockerfile ``` - **Imagen ya publicada:** reemplazar `image: :latest` - **Servicios adicionales** (Postgres, Redis): agregarlos en el mismo archivo usando la red `default`, así quedan aislados del proxy. ### Paso 4 — Levantar ```bash cd ~/srv/projects/api-ventas docker compose up -d ``` ### Paso 5 — Post-instalación (opcional, apps Laravel) ```bash docker exec -it -web composer install --no-interaction --prefer-dist docker exec -it -web php artisan key:generate --force docker exec -it -web php artisan migrate --force docker exec -it -web php artisan optimize:clear ``` Verificar permisos si el usuario `www-data` no puede escribir: ```bash docker exec -it -web chown -R www-data:www-data /var/www//storage docker exec -it -web chmod -R 775 /var/www//storage /var/www//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: ```yaml 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](#opción-b--nginx-proxy-manager-panel-web). --- ## 5. Copias de seguridad Los respaldos se guardan **fuera** de los repositorios Git: ```bash # PostgreSQL docker exec pg_dump -U > ~/srv/backups/-$(date +%F).sql # MySQL docker exec mysqldump -u -p > ~/srv/backups/-$(date +%F).sql # Archivos tar czf ~/srv/backups/-files-$(date +%F).tar.gz ~/srv/projects//data ``` Sugerencia de rotación (crontab diario a las 3:00): ```cron 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 del contenedor | `-web` | | Red del proxy | `proxy_network` (externa) | | Red interna | `default` (bridge, aislada) | | Secretos | `~/srv/projects//.env` con `chmod 600` | | Dominios locales | `.local` | | Certificados `.local` | `~/srv/core/data/certs/` + `dynamic_tls.yml` | | Certificados públicos | Let's Encrypt vía `acme.json` |