# Configuración Cloudflare Tunnel + Multi-dominio (.test + .dev)

## 📋 Resumen Ejecutivo

Configuración completa para que el sistema funcione en dos entornos simultáneamente:
- **Local (.kuup.test)**: HTTP directo para desarrollo
- **Externo (.kuup.dev)**: HTTPS vía Cloudflare Tunnel para demos con clientes

### Capacidades implementadas:
✅ QR codes generados desde .kuup.test contienen URLs .kuup.dev (accesibles externamente)  
✅ Signed URLs válidas entre ambos dominios (.test ↔ .dev)  
✅ Upload de fotos móviles hasta 10MB con validación cross-domain  
✅ Producción (.kuup.cl) no afectada  

---

## 1️⃣ Configuración Docker

### 1.1. Docker Compose (`docker-compose.yaml`)

#### Servicio: cloudflared
```yaml
cloudflared:
    image: cloudflare/cloudflared:2026.2.0
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel --config /etc/cloudflared/config.yml run kuup
    volumes:
        - /home/rodrigo/Proyectos/Docker/cloudflared:/etc/cloudflared
    networks:
        - pos
        - e-comm
        - saas
        - page-kuup
```

**Función**: Conecta tráfico externo (*.kuup.dev) desde Cloudflare con nginx-proxy

**Archivos requeridos** en `/home/rodrigo/Proyectos/Docker/cloudflared/`:
- `config.yml` → Ver sección 1.2
- `kuup-credentials.json` → Credenciales del tunnel (obtenidas de Cloudflare)
- `cert.pem` → Certificado de autenticación (`cloudflared login`)

---

#### Servicio: nginx-proxy
```yaml
nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
        - "80:80"
        - "443:443"
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock:ro
        - ../Docker/nginx-proxy/vhost.d/:/etc/nginx/vhost.d
        - ../Docker/nginx-proxy/html/:/usr/share/nginx/html
        - ../Docker/nginx-proxy/conf.d/my_custom_config.conf:/etc/nginx/conf.d/my_custom_config.conf:ro
    networks:
        - pos
        - e-comm
        - saas
        - page-kuup
    environment:
        - CLIENT_MAX_BODY_SIZE=2M  # ⚠️ Sobrescrito por my_custom_config.conf
```

**Función**: 
- Proxy reverso automático (jwilder/nginx-proxy)
- Lee variable `VIRTUAL_HOST` de otros containers
- Genera configuración nginx dinámica y rutea tráfico

---

#### Servicio: pos-www (nginx del tenant POS)
```yaml
pos-www:
    image: nginx:alpine
    volumes:
        - ./pos/:/var/www
        - ../Docker/nginx/pos/conf.d/:/etc/nginx/conf.d
    environment:
        - VIRTUAL_HOST=qr.kuup.test,media.kuup.test,dioses.kuup.test,demo.kuup.test,demo2.kuup.test,webhooks.kuup.test,api.kuup.test,qr.kuup.dev,media.kuup.dev,dioses.kuup.dev,demo.kuup.dev,demo2.kuup.dev,webhooks.kuup.dev,api.kuup.dev
        - CLIENT_MAX_BODY_SIZE=2M  # ⚠️ Sobrescrito por default.conf
    networks:
        - pos
    depends_on:
        - php-pos
        - nginx-proxy
        - mysql
        - redis
```

**🚨 CRÍTICO**: 
- `VIRTUAL_HOST` debe incluir **TODOS** los subdominios en **AMBOS** formatos (.test **Y** .dev)
- nginx-proxy usa esto para rutear requests al container correcto
- Si agregas nuevo subdominio: `nuevo.kuup.test,nuevo.kuup.dev`

---

### 1.2. Cloudflare Tunnel Config

**Archivo**: `/home/rodrigo/Proyectos/Docker/cloudflared/config.yml`

```yaml
tunnel: 714058c3-12d8-4c05-afc4-1be6505ea83e
credentials-file: /etc/cloudflared/kuup-credentials.json
origincert: /etc/cloudflared/cert.pem

ingress:
  # Vite Dev Server - debe estar ANTES del wildcard
  - hostname: vite.kuup.dev
    service: http://nginx-proxy:5051
  
  # Wildcard para todos los demás subdominios
  - hostname: "*.kuup.dev"
    service: http://nginx-proxy:80

  # Catch-all para requests no coincidentes
  - service: http_status:404
```

**Reglas de ingress**:
- ⚠️ **Orden importa**: Reglas específicas primero, wildcard después
- `vite.kuup.dev` → Puerto 5051 (hot reload de Vite)
- `*.kuup.dev` → Puerto 80 (todo lo demás → nginx-proxy → routing automático)
- Catch-all → 404

**Cómo replicar en otro computador**:
```bash
# 1. Login a Cloudflare (abre browser)
cloudflared login

# 2. Crear tunnel (si es nuevo)
cloudflared tunnel create kuup

# 3. Se genera ~/.cloudflared/<tunnel-id>.json
# Copiar ese archivo como kuup-credentials.json

# 4. Configurar DNS en Cloudflare Dashboard:
# CNAME: *.kuup.dev → <tunnel-id>.cfargotunnel.com

# 5. Copiar cert.pem desde ~/.cloudflared/cert.pem
```

---

### 1.3. Nginx Proxy Custom Config

**Archivo**: `/home/rodrigo/Proyectos/Docker/nginx-proxy/conf.d/my_custom_config.conf`

```nginx
client_max_body_size 20M;

# Detectar esquema HTTPS desde Cloudflare
map $http_cf_visitor $forwarded_proto {
    default $scheme;
    "~*https" "https";
}
```

**Por qué es necesario**:
1. `client_max_body_size 20M`: Sobrescribe límite de 2M del environment variable
2. `map $http_cf_visitor`: Cloudflare envía header `CF-Visitor: {"scheme":"https"}`
3. Sin esto, Laravel pensaría que todos los requests son HTTP

---

### 1.4. Nginx del Tenant

**Archivo**: `/home/rodrigo/Proyectos/Docker/nginx/pos/conf.d/default.conf`

```nginx
server {
    listen 80;
    listen [::]:80 ipv6only=on;
    
    # 🚨 CRÍTICO: Ambos dominios para cada subdominio
    server_name localhost
                qr.kuup.test qr.kuup.dev
                media.kuup.test media.kuup.dev
                dioses.kuup.test dioses.kuup.dev
                demo.kuup.test demo.kuup.dev
                demo2.kuup.test demo2.kuup.dev
                webhooks.kuup.test webhooks.kuup.dev
                api.kuup.test api.kuup.dev
                delifast-admin.kuup.test delifast-admin.kuup.dev
                _;  # catch-all

    root /var/www/public;
    index index.php index.html;
    
    # Preservar IP real del cliente
    real_ip_header X-Forwarded-For;
    set_real_ip_from nginx-proxy;

    # 🚨 CRÍTICO: Permitir uploads de 10MB
    client_max_body_size 20M;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~* \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-pos:9000;  # Nombre del service en docker-compose
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

**Puntos críticos**:
- `server_name` sincronizado con `VIRTUAL_HOST`
- `set_real_ip_from nginx-proxy`: nombre del container proxy  
- `fastcgi_pass php-pos:9000`: nombre del service PHP
- `client_max_body_size 20M`: Debe ser ≥ PHP upload_max_filesize

---

## 2️⃣ Flujo de Tráfico

### Request Local (.kuup.test):
```
Browser
  ↓ http://demo.kuup.test:80
nginx-proxy (puerto 80 host)
  ↓ routing por VIRTUAL_HOST
pos-www container (nginx:alpine)
  ↓ fastcgi_pass php-pos:9000
php-pos container (PHP-FPM)
  ↓
Laravel App
```

### Request Externo (.kuup.dev):
```
Mobile Browser
  ↓ https://demo.kuup.dev:443
Cloudflare Edge (terminación SSL)
  ↓ Headers: CF-Visitor, X-Forwarded-*
Cloudflare Tunnel (ID: 714058c3-12d8-4c05-afc4-1be6505ea83e)
  ↓ config.yml: *.kuup.dev → nginx-proxy:80
cloudflared container
  ↓ HTTP interno (red Docker)
nginx-proxy:80
  ↓ routing por VIRTUAL_HOST
pos-www container (nginx:alpine)
  ↓ fastcgi_pass php-pos:9000
php-pos container (PHP-FPM)
  ↓
Laravel App
```

**Notas**:
- HTTPS solo en Cloudflare Edge (más eficiente)
- Tráfico interno Docker es HTTP
- Headers preservan contexto original (protocolo, IP, etc.)

---

## 3️⃣ Archivos Laravel Modificados