# Cloudflare DNS Mapping to Proxmox LXC Containers

**Last Updated:** 2025-01-20  
**Document Version:** 1.0  
**Status:** Implementation Guide

---

## Overview

This guide explains how to map Cloudflare DNS records to Proxmox VE LXC containers using Cloudflare Zero Trust tunnels (cloudflared). This provides secure, public access to your containers without exposing them directly to the internet.

---

## Architecture

```
Internet → Cloudflare DNS → Cloudflare Tunnel → cloudflared LXC → Target Container
```

### Components

1. **Cloudflare DNS** - DNS records pointing to tunnel
2. **Cloudflare Tunnel** - Secure connection between Cloudflare and your network
3. **cloudflared LXC** - Tunnel client running in a container
4. **Target Containers** - Your application containers (web servers, APIs, etc.)

---

## Prerequisites

1. **Cloudflare Account** with Zero Trust enabled
2. **Domain** managed by Cloudflare
3. **Proxmox Host** with network access
4. **Target Containers** running and accessible on local network

---

## Step-by-Step Guide

### Step 1: Set Up Cloudflare Tunnel

#### 1.1 Create Tunnel in Cloudflare Dashboard

1. **Access Cloudflare Zero Trust:**
   - Navigate to: https://one.dash.cloudflare.com
   - Sign in with your Cloudflare account

2. **Create Tunnel:**
   - Go to **Zero Trust** → **Networks** → **Tunnels**
   - Click **Create a tunnel**
   - Select **Cloudflared**
   - Enter tunnel name (e.g., `proxmox-primary`)
   - Click **Save tunnel**

3. **Copy Tunnel Token:**
   - After creation, you'll see installation instructions
   - Copy the tunnel token (you'll need this in Step 2)

#### 1.2 Deploy cloudflared LXC Container

**Option A: Create New Container**

```bash
# Assign VMID (e.g., 8000)
VMID=8000

# Create container
pct create $VMID local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
  --hostname cloudflared \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.11.80/24,gw=192.168.11.1 \
  --memory 512 \
  --cores 1 \
  --storage local-lvm \
  --rootfs local-lvm:4

# Start container
pct start $VMID
```

**Option B: Use Existing Container**

If you already have a container for cloudflared (e.g., VMID 102), skip to installation.

#### 1.3 Install cloudflared

```bash
# Replace $VMID with your container ID
pct exec $VMID -- bash -c "
  wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
  dpkg -i cloudflared-linux-amd64.deb
  cloudflared --version
"
```

#### 1.4 Configure Tunnel

```bash
# Install tunnel with token (replace <TUNNEL_TOKEN> with actual token)
pct exec $VMID -- cloudflared service install <TUNNEL_TOKEN>

# Enable and start service
pct exec $VMID -- systemctl enable cloudflared
pct exec $VMID -- systemctl start cloudflared

# Check status
pct exec $VMID -- systemctl status cloudflared
```

---

### Step 2: Map DNS to Container

#### 2.1 Identify Container Information

**Get Container IP and Port:**

```bash
# List containers and their IPs
pct list

# Get specific container IP
pct config <VMID> | grep ip

# Or check running containers
pct exec <VMID> -- ip addr show eth0
```

**Example Container:**
- **VMID**: 2500 (besu-rpc-1)
- **IP**: 192.168.11.250
- **Port**: 8545 (RPC port)
- **Service**: HTTP JSON-RPC API

#### 2.2 Configure Tunnel Ingress Rules

**In Cloudflare Dashboard:**

1. **Navigate to Tunnel Configuration:**
   - Go to **Zero Trust** → **Networks** → **Tunnels**
   - Click on your tunnel name
   - Click **Configure**

2. **Add Public Hostname:**
   - Click **Public Hostname** tab
   - Click **Add a public hostname**

3. **Configure Route:**
   ```
   Subdomain: rpc
   Domain: yourdomain.com
   Service: http://192.168.11.250:8545
   ```

4. **Save Configuration**

**Example Configuration:**

For multiple containers, add multiple hostname entries:

```
Subdomain: rpc-core
Domain: yourdomain.com
Service: http://192.168.11.250:8545

Subdomain: rpc-sentry
Domain: yourdomain.com
Service: http://192.168.11.251:8545

Subdomain: blockscout
Domain: yourdomain.com
Service: http://192.168.11.100:4000
```

#### 2.3 Create DNS Records

**In Cloudflare DNS Dashboard:**

1. **Navigate to DNS:**
   - Go to your domain in Cloudflare
   - Click **DNS** → **Records**

2. **Create CNAME Record:**
   - Click **Add record**
   - **Type**: CNAME
   - **Name**: `rpc` (or your subdomain)
   - **Target**: `<tunnel-id>.cfargotunnel.com`
     - Or use: `proxmox-primary.yourteam.cloudflareaccess.com` (if using Zero Trust)
   - **Proxy status**: 🟠 Proxied (orange cloud) - **Important!**

3. **Save Record**

**DNS Record Examples:**

| Service | Type | Name | Target | Proxy |
|---------|------|------|--------|-------|
| RPC Core | CNAME | `rpc-core` | `<tunnel-id>.cfargotunnel.com` | 🟠 Proxied |
| RPC Sentry | CNAME | `rpc-sentry` | `<tunnel-id>.cfargotunnel.com` | 🟠 Proxied |
| Blockscout | CNAME | `blockscout` | `<tunnel-id>.cfargotunnel.com` | 🟠 Proxied |
| FireFly | CNAME | `firefly` | `<tunnel-id>.cfargotunnel.com` | 🟠 Proxied |

**Important Notes:**
- ✅ **Always enable proxy** (orange cloud) for tunnel-based DNS records
- ✅ Use CNAME records (not A records) for tunnel endpoints
- ✅ Target should be the tunnel's cloudflareaccess.com domain or cfargotunnel.com

---

### Step 3: Verify Configuration

#### 3.1 Check Tunnel Status

```bash
# Check cloudflared service
pct exec $VMID -- systemctl status cloudflared

# View tunnel logs
pct exec $VMID -- journalctl -u cloudflared -f
```

**In Cloudflare Dashboard:**
- Go to **Zero Trust** → **Networks** → **Tunnels**
- Tunnel status should show "Healthy"

#### 3.2 Test DNS Resolution

```bash
# Test DNS resolution
dig rpc-core.yourdomain.com
nslookup rpc-core.yourdomain.com

# Should resolve to Cloudflare IPs (if proxied)
```

#### 3.3 Test Container Access

```bash
# Test from container network (should work directly)
curl http://192.168.11.250:8545

# Test via public DNS (should work through tunnel)
curl https://rpc-core.yourdomain.com
```

---

## Common Container Types & Examples

### Web Applications (HTTP/HTTPS)

**Example: Blockscout Explorer**

```
DNS Record:
  Name: blockscout
  Target: <tunnel-id>.cfargotunnel.com
  Proxy: Enabled

Tunnel Ingress:
  Subdomain: blockscout
  Domain: yourdomain.com
  Service: http://192.168.11.100:4000
```

### API Services (JSON-RPC, REST)

**Example: Besu RPC Node**

```
DNS Record:
  Name: rpc
  Target: <tunnel-id>.cfargotunnel.com
  Proxy: Enabled

Tunnel Ingress:
  Subdomain: rpc
  Domain: yourdomain.com
  Service: http://192.168.11.250:8545
```

### Databases (Optional - Not Recommended)

**⚠️ Warning:** Never expose databases directly through tunnels unless absolutely necessary. Use Cloudflare Access with strict policies if needed.

### Monitoring Dashboards

**Example: Grafana**

```
DNS Record:
  Name: grafana
  Target: <tunnel-id>.cfargotunnel.com
  Proxy: Enabled

Tunnel Ingress:
  Subdomain: grafana
  Domain: yourdomain.com
  Service: http://192.168.11.200:3000
```

**Security:** Add Cloudflare Access policy to restrict access (see Step 4).

---

## Step 4: Add Cloudflare Access (Optional but Recommended)

For additional security, add Cloudflare Access policies to restrict who can access your containers.

### 4.1 Create Access Application

1. **Navigate to Applications:**
   - Go to **Zero Trust** → **Access** → **Applications**
   - Click **Add an application**

2. **Configure Application:**
   - **Application Name**: RPC Core API
   - **Application Domain**: `rpc-core.yourdomain.com`
   - **Session Duration**: 24 hours

3. **Add Policy:**
   ```
   Rule Name: RPC Access
   Action: Allow
   Include:
     - Email domain: @yourdomain.com
     - OR Email: admin@yourdomain.com
   Require:
     - MFA (optional)
   ```

4. **Save Application**

### 4.2 Apply to Multiple Services

Create separate applications for each service that needs access control:
- Blockscout (public or restricted)
- Grafana (admin only)
- FireFly (team access)
- RPC nodes (API key authentication recommended in addition)

---

## Advanced Configuration

### Multiple Tunnels (Redundancy)

For high availability, deploy multiple cloudflared instances:

**Primary Tunnel:**
- Container: VMID 8000 (cloudflared-1)
- IP: 192.168.11.80
- Tunnel: `proxmox-primary`

**Secondary Tunnel:**
- Container: VMID 8001 (cloudflared-2)
- IP: 192.168.11.81
- Tunnel: `proxmox-secondary`

**DNS Configuration:**
- Use same DNS records for both tunnels
- Cloudflare will automatically load balance
- If one tunnel fails, traffic routes to the other

### Custom cloudflared Configuration

For advanced routing, use a config file:

```yaml
# /etc/cloudflared/config.yml
tunnel: <tunnel-id>
credentials-file: /etc/cloudflared/credentials.json

ingress:
  # Specific routes
  - hostname: rpc-core.yourdomain.com
    service: http://192.168.11.250:8545
  
  - hostname: rpc-sentry.yourdomain.com
    service: http://192.168.11.251:8545
  
  - hostname: blockscout.yourdomain.com
    service: http://192.168.11.100:4000
  
  # Catch-all
  - service: http_status:404
```

**Apply Configuration:**
```bash
pct exec $VMID -- systemctl restart cloudflared
```

### Using Reverse Proxy (Nginx Proxy Manager)

**Architecture:**
```
Internet → Cloudflare → Tunnel → cloudflared → Nginx Proxy Manager → Containers
```

**Benefits:**
- Centralized SSL/TLS termination
- Advanced routing rules
- Rate limiting
- Request logging

**Configuration:**

1. **Tunnel Points to Nginx:**
   ```
   Subdomain: *
   Service: http://192.168.11.105:80  # Nginx Proxy Manager
   ```

2. **Nginx Routes to Containers:**
   - Create proxy hosts in Nginx Proxy Manager
   - Configure upstream servers (container IPs)
   - Add SSL certificates

See: **[CLOUDFLARE_NGINX_INTEGRATION.md](../05-network/CLOUDFLARE_NGINX_INTEGRATION.md)**

---

## Current Container Mapping Examples

Based on your deployment, here are example mappings:

### Besu Validators (1000-1004)

**Recommendation:** ⚠️ Do not expose validators publicly. Keep them private.

**If Needed (VPN/Internal Access Only):**
```
Internal Access: 192.168.11.100-104 (via VPN)
```

### Besu RPC Nodes (2500-2502)

**Example Configuration:**

```
DNS Record:
  Name: rpc
  Target: <tunnel-id>.cfargotunnel.com
  Proxy: Enabled

Tunnel Ingress:
  - hostname: rpc-1.yourdomain.com
    service: http://192.168.11.250:8545
  
  - hostname: rpc-2.yourdomain.com
    service: http://192.168.11.251:8545
  
  - hostname: rpc-3.yourdomain.com
    service: http://192.168.11.252:8545
```

---

## Troubleshooting

### Tunnel Not Connecting

**Symptoms:** Tunnel shows as "Unhealthy" in dashboard

**Solutions:**
```bash
# Check service status
pct exec $VMID -- systemctl status cloudflared

# View logs
pct exec $VMID -- journalctl -u cloudflared -f

# Verify token is correct
pct exec $VMID -- cat /etc/cloudflared/config.yml
```

### DNS Not Resolving

**Symptoms:** DNS record doesn't resolve or resolves incorrectly

**Solutions:**
1. Verify DNS record type is CNAME
2. Verify proxy is enabled (orange cloud)
3. Check target is correct tunnel domain
4. Wait for DNS propagation (up to 5 minutes)

### Container Not Accessible

**Symptoms:** DNS resolves but container doesn't respond

**Solutions:**
1. Verify container is running: `pct status <VMID>`
2. Test direct access: `curl http://<container-ip>:<port>`
3. Check tunnel ingress configuration matches DNS record
4. Verify firewall allows traffic from cloudflared container
5. Check container logs for errors

### SSL/TLS Errors

**Symptoms:** Browser shows SSL certificate errors

**Solutions:**
1. Verify proxy is enabled (orange cloud) in DNS
2. Check Cloudflare SSL/TLS mode (Full or Full Strict)
3. Ensure service URL uses `http://` not `https://` (Cloudflare handles SSL)
4. If using self-signed certs, set SSL mode to "Full" not "Full (strict)"

---

## Best Practices

### Security

1. ✅ **Use Cloudflare Access** for sensitive services
2. ✅ **Enable MFA** for admin access
3. ✅ **Use IP allowlists** in addition to Cloudflare Access
4. ✅ **Monitor access logs** in Cloudflare dashboard
5. ✅ **Never expose databases** directly
6. ✅ **Keep containers updated** with security patches

### Performance

1. ✅ **Use proxy** (orange cloud) for DDoS protection
2. ✅ **Enable Cloudflare caching** for static content
3. ✅ **Use multiple tunnels** for redundancy
4. ✅ **Monitor tunnel health** regularly

### Management

1. ✅ **Document all DNS mappings** in a registry
2. ✅ **Use consistent naming** conventions
3. ✅ **Version control** tunnel configurations
4. ✅ **Backup** cloudflared configurations

---

## DNS Mapping Registry Template

Keep track of your DNS mappings:

| Service | Subdomain | Container VMID | Container IP | Port | Tunnel | Access Control |
|---------|-----------|----------------|--------------|------|--------|----------------|
| RPC Core | rpc-core | 2500 | 192.168.11.250 | 8545 | proxmox-primary | API Key |
| Blockscout | blockscout | 5000 | 192.168.11.100 | 4000 | proxmox-primary | Cloudflare Access |
| Grafana | grafana | 6000 | 192.168.11.200 | 3000 | proxmox-primary | Admin Only |

---

## Quick Reference Commands

### Check Container Status
```bash
pct list
pct status <VMID>
pct config <VMID>
```

### Check Tunnel Status
```bash
pct exec <VMID> -- systemctl status cloudflared
pct exec <VMID> -- journalctl -u cloudflared -f
```

### Test DNS Resolution
```bash
dig <subdomain>.yourdomain.com
nslookup <subdomain>.yourdomain.com
curl -I https://<subdomain>.yourdomain.com
```

### Test Container Direct Access
```bash
curl http://<container-ip>:<port>
pct exec <VMID> -- curl http://<target-ip>:<port>
```

---

## Related Documentation

- **[CLOUDFLARE_ZERO_TRUST_GUIDE.md](CLOUDFLARE_ZERO_TRUST_GUIDE.md)** - Complete Cloudflare Zero Trust setup
- **[CLOUDFLARE_NGINX_INTEGRATION.md](../05-network/CLOUDFLARE_NGINX_INTEGRATION.md)** - Using Nginx Proxy Manager
- **[NETWORK_ARCHITECTURE.md](../02-architecture/NETWORK_ARCHITECTURE.md)** - Network architecture overview
- **[DEPLOYMENT_STATUS_CONSOLIDATED.md](../03-deployment/DEPLOYMENT_STATUS_CONSOLIDATED.md)** - Current container inventory

---

**Document Status:** Complete (v1.0)  
**Maintained By:** Infrastructure Team  
**Review Cycle:** Quarterly  
**Last Updated:** 2025-01-20

