- core/: reverse proxy Traefik v3 (HTTP 80 / HTTPS 443) - traefik.yml con provider Docker (exposedByDefault: false) y provider file - dynamic_tls.yml sanitizado con certificados .local comentados - certs/README.md con procedimiento de certificados auto-firmados - init_project.sh: generador de proyectos base (SRV_DIR configurable) - plantilla compose con redireccion HTTP->HTTPS + Let's Encrypt - bloque alternativo comentado para dominios .local - README.md: documentacion integral (puesta en marcha, HTTP/HTTPS, troubleshooting y seguridad) - docs/arquitectura.md: guia de instalacion y gestion de URLs - docs/http-https.md: referencia de etiquetas Traefik, TLS y certresolver - .gitignore: excluye .env, acme.json, certificados, datos y respaldos
188 lines
7.4 KiB
Bash
Executable File
188 lines
7.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# ==============================================================================
|
|
# Script de aprovisionamiento de proyectos Docker (Estructura Limpia)
|
|
# ==============================================================================
|
|
# Uso: ./init_project.sh <nombre-del-proyecto> <dominio-o-url> [puerto-interno]
|
|
#
|
|
# Genera en $SRV_DIR/projects/<proyecto> la estructura base:
|
|
# app/ -> código fuente, repo o Dockerfile
|
|
# data/{db,storage}/ -> volúmenes persistentes
|
|
# .env -> variables de entorno (chmod 600)
|
|
# docker-compose.yml -> plantilla conectada a proxy_network + etiquetas Traefik
|
|
#
|
|
# La plantilla incluye HTTP con redirección a HTTPS y HTTPS con Let's Encrypt,
|
|
# más un bloque comentado alternativo para dominios .local con certificado
|
|
# auto-firmado (ver docs/http-https.md).
|
|
# ==============================================================================
|
|
set -euo pipefail
|
|
|
|
# Directorio base de los proyectos. Configurable con SRV_DIR.
|
|
BASE_DIR="${SRV_DIR:-$HOME/srv}"
|
|
PROJECTS_DIR="$BASE_DIR/projects"
|
|
NETWORK_NAME="proxy_network"
|
|
|
|
# Colores para salida de terminal
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
YELLOW='\033[1;33m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m'
|
|
|
|
# Validar argumentos
|
|
if [ $# -lt 2 ]; then
|
|
echo -e "${RED}Uso:${NC} $0 <nombre-del-proyecto> <dominio-o-url> [puerto-interno]"
|
|
echo -e "Ejemplo: $0 api-ventas api.midominio.com 80"
|
|
exit 1
|
|
fi
|
|
|
|
PROJECT_NAME="$1"
|
|
PROJECT_DOMAIN="$2"
|
|
INTERNAL_PORT="${3:-80}"
|
|
TARGET_DIR="$PROJECTS_DIR/$PROJECT_NAME"
|
|
|
|
echo -e "${BLUE}==>${NC} Inicializando entorno para: ${GREEN}$PROJECT_NAME${NC}"
|
|
|
|
# 1. Asegurar red compartida externa
|
|
if ! docker network ls --format '{{.Name}}' | grep -wq "$NETWORK_NAME"; then
|
|
echo -e "${YELLOW}Creando red externa $NETWORK_NAME...${NC}"
|
|
docker network create "$NETWORK_NAME"
|
|
fi
|
|
|
|
# 2. Comprobar que no exista el proyecto
|
|
if [ -d "$TARGET_DIR" ]; then
|
|
echo -e "${RED}Error:${NC} El directorio $TARGET_DIR ya existe."
|
|
exit 1
|
|
fi
|
|
|
|
# 3. Crear árbol de carpetas limpias
|
|
# - app/: Destino para clonar repositorios o poner tu código fuente / Dockerfile
|
|
# - data/: Para persistencia de volúmenes de base de datos o archivos
|
|
mkdir -p "$PROJECTS_DIR"
|
|
mkdir -p "$TARGET_DIR/app"
|
|
mkdir -p "$TARGET_DIR/data/db"
|
|
mkdir -p "$TARGET_DIR/data/storage"
|
|
|
|
# Asignar permisos restrictivos al directorio raíz del proyecto
|
|
chmod 700 "$TARGET_DIR"
|
|
|
|
# 4. Crear archivo .env base personalizable
|
|
cat <<EOF > "$TARGET_DIR/.env"
|
|
# ==============================================================================
|
|
# Variables de entorno - $PROJECT_NAME
|
|
# ==============================================================================
|
|
APP_NAME=$PROJECT_NAME
|
|
APP_DOMAIN=$PROJECT_DOMAIN
|
|
PORT=$INTERNAL_PORT
|
|
|
|
# Agrega aquí las variables y secretos de tu proyecto.
|
|
# Este archivo tiene permisos 600 y NO debe subirse a Git.
|
|
EOF
|
|
|
|
chmod 600 "$TARGET_DIR/.env"
|
|
|
|
# 5. Crear plantilla docker-compose.yml lista para tu propia imagen o build local
|
|
cat <<EOF > "$TARGET_DIR/docker-compose.yml"
|
|
services:
|
|
# Servicio principal conectado al Proxy Reverso
|
|
web:
|
|
# Opción A: Construir tu propio Dockerfile dentro de app/
|
|
build:
|
|
context: ./app
|
|
dockerfile: Dockerfile
|
|
|
|
# Opción B: Usar una imagen existente de tu registro o Docker Hub
|
|
# (comentá el bloque build: de arriba y descomentá la línea image:)
|
|
|
|
image: ${PROJECT_NAME}:latest
|
|
container_name: ${PROJECT_NAME}-web
|
|
restart: unless-stopped
|
|
env_file:
|
|
- .env
|
|
volumes:
|
|
- ./app:/app
|
|
- ./data/storage:/app/storage
|
|
networks:
|
|
- default
|
|
- ${NETWORK_NAME}
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.docker.network=${NETWORK_NAME}"
|
|
|
|
# ======================================================================
|
|
# MODO A — Dominio público con Let's Encrypt
|
|
# ======================================================================
|
|
|
|
# 1. Middleware de redirección HTTP -> HTTPS
|
|
- "traefik.http.middlewares.${PROJECT_NAME}-redirect.redirectscheme.scheme=https"
|
|
- "traefik.http.middlewares.${PROJECT_NAME}-redirect.redirectscheme.permanent=true"
|
|
|
|
# 2. Router HTTP (puerto 80): redirige al HTTPS
|
|
- "traefik.http.routers.${PROJECT_NAME}-http.rule=Host(\`${PROJECT_DOMAIN}\`)"
|
|
- "traefik.http.routers.${PROJECT_NAME}-http.entrypoints=web"
|
|
- "traefik.http.routers.${PROJECT_NAME}-http.middlewares=${PROJECT_NAME}-redirect"
|
|
|
|
# 3. Router HTTPS (puerto 443): atiende el tráfico seguro
|
|
- "traefik.http.routers.${PROJECT_NAME}-https.rule=Host(\`${PROJECT_DOMAIN}\`)"
|
|
- "traefik.http.routers.${PROJECT_NAME}-https.entrypoints=websecure"
|
|
- "traefik.http.routers.${PROJECT_NAME}-https.tls=true"
|
|
- "traefik.http.routers.${PROJECT_NAME}-https.tls.certresolver=letsencrypt"
|
|
- "traefik.http.routers.${PROJECT_NAME}-https.service=${PROJECT_NAME}-svc"
|
|
|
|
# 4. Servicio: puerto interno del contenedor
|
|
- "traefik.http.services.${PROJECT_NAME}-svc.loadbalancer.server.port=${INTERNAL_PORT}"
|
|
|
|
# ======================================================================
|
|
# MODO B — Dominio .local con certificado auto-firmado
|
|
# ======================================================================
|
|
# Reemplazá los routers de arriba por estos, agregá el certificado en
|
|
# ~/srv/core/data/dynamic_tls.yml y quitá el certresolver (el certificado
|
|
# lo aporta el provider "file"). Ver docs/http-https.md
|
|
#
|
|
# - "traefik.http.routers.${PROJECT_NAME}.rule=Host(\`${PROJECT_DOMAIN}\`)"
|
|
# - "traefik.http.routers.${PROJECT_NAME}.entrypoints=websecure"
|
|
# - "traefik.http.routers.${PROJECT_NAME}.tls=true"
|
|
# - "traefik.http.services.${PROJECT_NAME}.loadbalancer.server.port=${INTERNAL_PORT}"
|
|
|
|
# ==============================================================================
|
|
# Servicios internos (base de datos, colas, etc.)
|
|
# ==============================================================================
|
|
# IMPORTANTE: conectalos solo a la red "default" para que queden aislados
|
|
# del proxy inverso y no sean accesibles desde internet.
|
|
#
|
|
# db:
|
|
# image: postgres:14
|
|
# container_name: ${PROJECT_NAME}-pg
|
|
# restart: unless-stopped
|
|
# networks:
|
|
# - default
|
|
# environment:
|
|
# POSTGRES_USER: \${POSTGRES_USER}
|
|
# POSTGRES_PASSWORD: \${POSTGRES_PASSWORD}
|
|
# POSTGRES_DB: \${POSTGRES_DB}
|
|
# volumes:
|
|
# - ./data/db:/var/lib/postgresql
|
|
# # Exponer solo en localhost, nunca público:
|
|
# ports:
|
|
# - "127.0.0.1:5432:5432"
|
|
|
|
# Redes: default (aislada para servicios internos) y proxy_network (para el reverse proxy)
|
|
networks:
|
|
default:
|
|
driver: bridge
|
|
${NETWORK_NAME}:
|
|
external: true
|
|
EOF
|
|
|
|
echo -e "${GREEN}✓${NC} Estructura limpia creada en: ${BLUE}$TARGET_DIR${NC}"
|
|
echo -e " ├── ${BLUE}app/${NC} <- Pega aquí tu código, Dockerfile o clona tu repo"
|
|
echo -e " ├── ${BLUE}data/${NC} <- Directorio para volúmenes persistentes"
|
|
echo -e " ├── ${YELLOW}.env${NC} <- Variables de entorno"
|
|
echo -e " └── ${YELLOW}docker-compose.yml${NC}<- Orquestación enlazada al proxy"
|
|
echo ""
|
|
echo -e "${YELLOW}Próximos pasos:${NC}"
|
|
echo -e " 1. Copia tus archivos en: ${BLUE}$TARGET_DIR/app/${NC}"
|
|
echo -e " 2. Ajusta ${YELLOW}$TARGET_DIR/docker-compose.yml${NC} según tu imagen o build"
|
|
echo -e " 3. Levanta el proxy si aún no está: ${GREEN}cd $HOME/srv/core && docker compose up -d${NC}"
|
|
echo -e " 4. Inicia el proyecto: ${GREEN}cd $TARGET_DIR && docker compose up -d${NC}"
|