- 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
111 lines
2.9 KiB
Markdown
111 lines
2.9 KiB
Markdown
# Certificados locales (`.local`)
|
|
|
|
Este directorio aloja los certificados **auto-firmados** que usan los dominios
|
|
internos (`*.local`). Está montado en el contenedor de Traefik como:
|
|
|
|
```yaml
|
|
- ./data/certs:/etc/traefik/certs:ro
|
|
```
|
|
|
|
⚠️ **El contenido de esta carpeta NO se versiona** (ver `.gitignore`):
|
|
las claves privadas no deben salir del servidor.
|
|
|
|
---
|
|
|
|
## 1. Generar un certificado auto-firmado
|
|
|
|
Desde la raíz del repositorio:
|
|
|
|
```bash
|
|
cd core/data/certs
|
|
|
|
openssl req -x509 -nodes -days 3650 \
|
|
-newkey rsa:2048 \
|
|
-keyout miapp.local.key \
|
|
-out miapp.local.crt \
|
|
-subj "/CN=miapp.local" \
|
|
-addext "subjectAltName=DNS:miapp.local"
|
|
```
|
|
|
|
Archivos resultantes:
|
|
|
|
| Archivo | Descripción |
|
|
|---|---|
|
|
| `miapp.local.crt` | Certificado público (se puede distribuir) |
|
|
| `miapp.local.key` | **Clave privada** — permisos `600`, nunca se comparte |
|
|
|
|
Si el certificado debe cubrir **varios** nombres en un solo `.crt`:
|
|
|
|
```bash
|
|
openssl req -x509 -nodes -days 3650 \
|
|
-newkey rsa:2048 \
|
|
-keyout intranet.local.key \
|
|
-out intranet.local.crt \
|
|
-subj "/CN=intranet.local" \
|
|
-addext "subjectAltName=DNS:intranet.local,DNS:app.intranet.local,DNS:api.intranet.local"
|
|
```
|
|
|
|
## 2. Declararlo en Traefik
|
|
|
|
Editar `../dynamic_tls.yml` y descomentar el bloque **con la ruta interna**:
|
|
|
|
```yaml
|
|
tls:
|
|
certificates:
|
|
- certFile: /etc/traefik/certs/miapp.local.crt
|
|
keyFile: /etc/traefik/certs/miapp.local.key
|
|
```
|
|
|
|
## 3. Recargar el proxy
|
|
|
|
```bash
|
|
cd ../../ # desde core/
|
|
docker compose restart traefik
|
|
docker logs -f core-proxy
|
|
```
|
|
|
|
`dynamic_tls.yml` tiene `watch: true`, pero reiniciar es la forma más segura de
|
|
confirmar que el certificado se cargó.
|
|
|
|
## 4. Etiquetar el proyecto
|
|
|
|
El router debe declarar `tls=true` **sin** certresolver (el certificado ya lo
|
|
aporta el provider `file`):
|
|
|
|
```yaml
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.docker.network=proxy_network"
|
|
- "traefik.http.routers.miapp.rule=Host(`miapp.local`)"
|
|
- "traefik.http.routers.miapp.entrypoints=websecure"
|
|
- "traefik.http.routers.miapp.tls=true"
|
|
- "traefik.http.services.miapp.loadbalancer.server.port=80"
|
|
```
|
|
|
|
## 5. Resolver el nombre en el cliente
|
|
|
|
En cada máquina que deba acceder al sitio:
|
|
|
|
```bash
|
|
echo "192.168.1.50 miapp.local" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
## 6. Evitar el aviso del navegador
|
|
|
|
El navegador mostrará "certificado no confiable" porque es auto-firmado.
|
|
Opciones:
|
|
|
|
- **Windows**: `certutil -addstore -f "ROOT" miapp.local.crt` (PowerShell admin).
|
|
- **Linux (systemd)**: copiar a `/usr/local/share/ca-certificates/` y ejecutar
|
|
`sudo update-ca-certificates`.
|
|
- **macOS**: doble clic sobre el `.crt` → *Añadir al llavero* → *Confiar*.
|
|
- **Firefox** no usa el almacén del sistema:Settings → Certificates → Import.
|
|
|
|
---
|
|
|
|
## Certificados reales que usa este servidor
|
|
|
|
Los certificados de producción de los dominios públicos **no** viven acá: los
|
|
emite Let's Encrypt y Traefik los guarda en `../acme.json` (también excluido
|
|
del repositorio).
|