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 mgt CLI 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:

  1. Adds the hostname to the cloudflared tunnel configuration
  2. Creates the DNS CNAME record in Cloudflare pointing to the tunnel
  3. 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 noTLSVerify flag 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>