Add Cloudflare Route
This runbook covers adding a new hostname route to the Cloudflare tunnel so that a new subdomain or application is publicly accessible.
Prerequisites
- Access to the
mgtCLI tool (located at/home/lucas/paas/bin/) - The Kubernetes service for the application must already be deployed
- A Traefik IngressRoute must be configured for the hostname
Overview
When you add a new route, the following chain is established:
New hostname (e.g., newapp.m3gatr0n.com)
│
v
Cloudflare DNS (CNAME to tunnel)
│
v
Cloudflare Tunnel (6d8885c4-...)
│
v
cloudflared -> https://localhost:32672
│
v
Traefik IngressRoute (matches Host header)
│
v
K8s Service -> Pod
Step 1: Deploy the Application
Ensure the application is running in K8s with a Service:
# Verify the service exists
kubectl get svc -n <namespace> <service-name>
# Verify pods are running
kubectl get pods -n <namespace> -l app=<app-name>
Step 2: Create Traefik IngressRoute
Create an IngressRoute so Traefik knows how to route traffic for the new hostname:
# ingressroute.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: newapp-route
namespace: <namespace>
spec:
entryPoints:
- websecure
routes:
- match: Host(`newapp.m3gatr0n.com`)
kind: Rule
services:
- name: <service-name>
port: <service-port>
tls:
certResolver: letsencrypt-prod
# Or reference a specific secret:
# secretName: newapp-tls
Apply:
kubectl apply -f ingressroute.yaml
Step 3: Add Cloudflare Tunnel Route
Use the mgt CLI to add the route:
mgt route add newapp.m3gatr0n.com
This command:
- Adds the hostname to the cloudflared tunnel configuration
- Creates the DNS CNAME record in Cloudflare pointing to the tunnel
- Reloads the tunnel configuration
Manual Alternative
If mgt is unavailable, edit the configuration directly:
# Edit the tunnel config
sudo vim /etc/cloudflared/config.yml
Add the new hostname entry under ingress:
ingress:
# ... existing routes ...
- hostname: newapp.m3gatr0n.com
service: https://localhost:32672
originRequest:
noTLSVerify: true
# The catch-all rule must remain last
- service: http_status:404
Then restart cloudflared:
sudo systemctl restart cloudflared
And create the DNS record in Cloudflare:
# Using cloudflared CLI
cloudflared tunnel route dns 6d8885c4-97d9-43fd-8426-78a00c2834f1 newapp.m3gatr0n.com
Step 4: Create TLS Certificate (if needed)
If using cert-manager (with the DNS-01 solver):
# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: newapp-tls
namespace: <namespace>
spec:
secretName: newapp-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- newapp.m3gatr0n.com
kubectl apply -f certificate.yaml
# Wait for certificate
kubectl get certificate newapp-tls -n <namespace> -w
Note: Since Cloudflare handles public TLS, the internal certificate is optional. The
noTLSVerifyflag in the tunnel config means cloudflared accepts any certificate from Traefik.
Step 5: Verify
# Check DNS resolution
dig newapp.m3gatr0n.com
# Test HTTPS access
curl -v https://newapp.m3gatr0n.com/
# Check Traefik routing
kubectl get ingressroute -n <namespace> newapp-route
# Verify in tunnel route list
mgt route list | grep newapp
Checklist
[ ] Application deployed and Service created
[ ] Traefik IngressRoute applied
[ ] Cloudflare tunnel route added (mgt route add)
[ ] DNS record created (automatic with mgt)
[ ] TLS certificate issued (if using cert-manager)
[ ] HTTPS access verified from external network
[ ] Route appears in mgt route list
Removing a Route
# Remove the tunnel route
mgt route remove newapp.m3gatr0n.com
# Remove the IngressRoute
kubectl delete ingressroute newapp-route -n <namespace>
# Remove the certificate (optional)
kubectl delete certificate newapp-tls -n <namespace>