Files
Portainer/cloudflared/README.md
T
2026-07-25 11:20:27 +00:00

197 lines
6.1 KiB
Markdown

# Cloudflare Tunnel (cloudflared)
Conecta el servidor a Cloudflare sin abrir puertos. Todo el tráfico entra por la red de Cloudflare,
llega al contenedor `cloudflared`, y este lo reenvía a Traefik.
```
Internet → Cloudflare Edge → cloudflared → Traefik → servicios
```
**Ventajas sobre exposición directa:**
- Tu IP pública nunca es visible — CrowdSec solo ve IPs de Cloudflare (allowlisteadas)
- Funciona desde redes con CGNAT, CG-NAT corporativo o sin IPv4 fija
- Cloudflare absorbe DDoS y filtra bots antes de que lleguen al servidor
> **Estado actual**: el tunnel está **parado** (`docker stop cloudflared`).
> Los DNS apuntan directo a `193.70.84.224` (registros A, sin proxy Cloudflare).
> Ver sección [Activar / desactivar el tunnel](#activar--desactivar-el-tunnel).
---
## Configuración inicial (una sola vez)
### 1. Crear el tunnel en Cloudflare
1. Ve a [dash.cloudflare.com](https://dash.cloudflare.com) → **Zero Trust****Networks****Conectores**
2. **Create connector** → nombre: `homeserver`
3. Selecciona **Docker** → copia el **token** (cadena larga tras `--token`)
### 2. Crear un API Token
En [dash.cloudflare.com](https://dash.cloudflare.com) → **My Profile****API Tokens****Create Token**
Permisos mínimos necesarios:
| Scope | Recurso | Permiso |
|---------|----------------------------|---------|
| Account | Cloudflare Tunnel | Edit |
| Zone | DNS (sherlockhomeless.net) | Edit |
> El API Token también lo usa `add-domain.sh` en modo directo (solo necesita Zone > DNS > Edit).
### 3. Configurar el `.env`
```bash
nano .env
```
Variables obligatorias para **ambos modos**:
```env
CLOUDFLARE_API_TOKEN=<token del paso 2>
CLOUDFLARE_ZONE_ID=f7c4e16f9a434a947ad0f266b2e1f894
CLOUDFLARE_DOMAIN=sherlockhomeless.net
CLOUDFLARE_SERVER_IP=193.70.84.224 # IP para registros A directos
```
Variables adicionales solo necesarias **con tunnel activo**:
```env
CLOUDFLARE_TUNNEL_TOKEN=<token del paso 1>
CLOUDFLARE_ACCOUNT_ID=328f4b942827169b11f7d1f11c640522
CLOUDFLARE_TUNNEL_ID=d405a2a2-69a1-40f1-b939-04cea5d60a50
```
---
## Añadir un nuevo subdominio
### Modo directo (sin tunnel, estado actual)
Crea un registro `A` apuntando a la IP del servidor, sin proxy de Cloudflare:
```bash
cd cloudflared
./add-domain.sh immich
./add-domain.sh immich recipes calibre # varios a la vez
```
El script:
1. Detecta la IP del servidor desde `CLOUDFLARE_SERVER_IP` (o la autodetecta via `api.ipify.org`)
2. Crea o actualiza el registro DNS `A` con proxy desactivado (nube gris)
### Modo tunnel (cuando el tunnel esté activo)
Crea un registro `CNAME` al tunnel con proxy naranja y añade el hostname al ingress:
```bash
cd cloudflared
./add-domain.sh --tunnel immich
./add-domain.sh --tunnel immich recipes calibre
```
El script:
1. Lee el ingress actual del tunnel desde la API de Cloudflare
2. Añade el hostname apuntando a `https://traefik:443` (noTLSVerify)
3. Guarda el ingress actualizado
4. Crea o actualiza el registro DNS `CNAME` con proxy naranja
---
## Activar / desactivar el tunnel
### Activar
```bash
# 1. Levantar el contenedor
cd cloudflared
docker compose --env-file .env up -d
# 2. Migrar los DNS al tunnel (convierte A records → CNAME proxied)
./add-domain.sh --tunnel auth traefik gitea n8n nextcloud paperless paperless-ai \
notas memos vikunja karakeep kasm remote beszel dozzle crowdsec grafana llm \
ocode adblock onlyoffice www cockpit coolify kopia notes portainer \
uptimekuma webtop wg
# 3. Verificar conexión
docker logs cloudflared | grep "Registered tunnel"
```
### Desactivar
```bash
# 1. Parar el contenedor (no se levantará solo al reiniciar)
docker stop cloudflared
# 2. Revertir DNS a registros A directos
./add-domain.sh auth traefik gitea n8n nextcloud paperless paperless-ai \
notas memos vikunja karakeep kasm remote beszel dozzle crowdsec grafana llm \
ocode adblock onlyoffice www cockpit coolify kopia notes portainer \
uptimekuma webtop wg
```
---
## Subdominios registrados
| Subdominio | Servicio |
|------------|----------|
| `auth` | Authentik SSO |
| `traefik` | Traefik Dashboard |
| `gitea` | Gitea |
| `n8n` | n8n |
| `nextcloud` | Nextcloud |
| `paperless` | Paperless-ngx |
| `paperless-ai` | Paperless AI |
| `notas` | Trilium |
| `memos` | Memos |
| `vikunja` | Vikunja |
| `karakeep` | Karakeep |
| `kasm` | Kasm Workspaces |
| `remote` | Guacamole |
| `beszel` | Beszel |
| `dozzle` | Dozzle |
| `crowdsec` | CrowdSec Grafana |
| `grafana` | Grafana |
| `llm` | LiteLLM |
| `ocode` | OpenCode |
| `adblock` | AdGuard |
| `onlyoffice` | OnlyOffice |
| `www` | Homepage |
| `cockpit` | Cockpit |
| `coolify` | Coolify |
| `kopia` | Kopia |
| `notes` | Notes |
| `portainer` | Portainer |
| `uptimekuma` | Uptime Kuma |
| `webtop` | Webtop |
| `wg` | WireGuard |
---
## Comandos útiles
```bash
# Ver estado del tunnel
docker logs cloudflared
# Ver todos los subdominios en DNS de Cloudflare
curl -s "https://api.cloudflare.com/client/v4/zones/${CLOUDFLARE_ZONE_ID}/dns_records?per_page=100" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | \
python3 -c "import sys,json; [print(r['type'].ljust(6), r['name']) for r in json.load(sys.stdin)['result']]"
# Ver ingress del tunnel configurado en Cloudflare
curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/cfd_tunnel/${CLOUDFLARE_TUNNEL_ID}/configurations" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | \
python3 -c "import sys,json; [print(r.get('hostname','*'), '->', r['service']) for r in json.load(sys.stdin)['result']['config']['ingress']]"
```
---
## Seguridad
- **API Token**: permisos mínimos (Tunnel Edit + DNS Edit). Rótalo periódicamente.
- **Tunnel Token**: si se compromete, regénéralo en el dashboard y reinicia el contenedor con el nuevo token en `.env`.
- **CrowdSec con tunnel activo**: las IPs de Cloudflare están en la allowlist `cloudflare`. El bouncer usa `forwardedHeadersTrustedIPs` con los rangos de CF para ver la IP real del cliente.
- **CrowdSec sin tunnel**: el bouncer ve la IP pública directa del cliente. El bot de Telegram (`/allow <ip>`) puede desbanear y allowlistear en CrowdSec, fail2ban y firewalld simultáneamente.