Cloudflare Tunnel¶
Overview¶
Cloudflare Tunnel provides secure, zero-trust access to internal services without exposing ports to the internet.
Architecture¶
graph LR
subgraph Internet
Users[Users]
CF[Cloudflare Edge]
end
subgraph HomeLab
Tunnel[cloudflared]
Services[K8s Services]
end
Users -->|HTTPS| CF
CF <-->|Tunnel| Tunnel
Tunnel --> Services
How It Works¶
cloudflaredcreates outbound connection to Cloudflare- Cloudflare routes traffic to tunnel endpoint
- Tunnel forwards to internal services
- No inbound firewall rules required
Deployment¶
Kubernetes Resources¶
| Resource | Name | Namespace |
|---|---|---|
| Deployment | cloudflared | cloudflared |
| ConfigMap | cloudflared | cloudflared |
| Secret | cloudflared-creds | cloudflared |
Configuration¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflared
namespace: cloudflared
spec:
replicas: 2
template:
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:latest
args:
- tunnel
- --config
- /etc/cloudflared/config.yaml
- run
volumeMounts:
- name: config
mountPath: /etc/cloudflared
Tunnel Configuration¶
Ingress Rules¶
tunnel: <tunnel-id>
credentials-file: /etc/cloudflared/credentials.json
ingress:
- hostname: ajandrews.pro
service: http://hub-web.hub.svc:80
- hostname: api.ajandrews.pro
service: http://hub-api.hub.svc:8080
- hostname: grafana.ajandrews.pro
service: http://grafana.monitoring.svc:3000
- hostname: kibana.ajandrews.pro
service: http://kibana.monitoring.svc:5601
- hostname: prometheus.ajandrews.pro
service: http://prometheus.monitoring.svc:9090
- hostname: argocd.ajandrews.pro
service: https://argocd-server.argocd.svc:443
- hostname: wiki.ajandrews.pro
service: http://wiki.wiki.svc:80
- service: http_status:404
Exposed Services¶
| Hostname | Service | Port |
|---|---|---|
| ajandrews.pro | Hub Web | 80 |
| api.ajandrews.pro | Hub API | 8080 |
| grafana.ajandrews.pro | Grafana | 3000 |
| kibana.ajandrews.pro | Kibana | 5601 |
| prometheus.ajandrews.pro | Prometheus | 9090 |
| argocd.ajandrews.pro | ArgoCD | 443 |
| wiki.ajandrews.pro | Wiki | 80 |
Adding New Service¶
1. Create Kubernetes Service¶
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: my-namespace
spec:
selector:
app: my-app
ports:
- port: 80
2. Update Cloudflared Config¶
Add to ingress rules:
3. Create DNS Record¶
In Cloudflare dashboard:
- Type: CNAME
- Name: myapp
- Target:
4. Apply Changes¶
Security Features¶
Zero Trust Access¶
- No exposed ports
- Encrypted tunnel
- Cloudflare Access policies
- Per-hostname authentication
Access Policies¶
Configure in Cloudflare Access:
| Application | Policy |
|---|---|
| ArgoCD | Require auth |
| Grafana | Require auth |
| Public site | Allow all |
High Availability¶
Replicas¶
Run multiple tunnel instances:
Health Checks¶
Monitoring¶
Metrics¶
cloudflared exposes Prometheus metrics:
| Metric | Description |
|---|---|
| cloudflared_tunnel_connections | Active connections |
| cloudflared_tunnel_requests | Total requests |
| cloudflared_tunnel_errors | Error count |
Logs¶
Troubleshooting¶
Common Issues¶
| Issue | Cause | Resolution |
|---|---|---|
| 502 Bad Gateway | Service down | Check target service |
| Connection refused | Wrong service URL | Verify service name |
| Certificate error | HTTPS backend | Use http or skip verify |
| Tunnel offline | Pod crash | Check pod logs |
Debug Commands¶
# Check tunnel status
cloudflared tunnel info
# Test connectivity
cloudflared tunnel route dns <tunnel-id> test.example.com
# View logs
kubectl logs -n cloudflared -l app=cloudflared
Maintenance¶
Updating Tunnel¶
# Update image
kubectl set image deployment/cloudflared \
cloudflared=cloudflare/cloudflared:latest \
-n cloudflared
Rotating Credentials¶
- Generate new credentials in Cloudflare
- Update Kubernetes secret
- Restart deployment