Skip to content

Cloudflare Tunnel

Jenkins needs a stable public HTTPS URL for two things:

  • GitHub webhooks — so GitHub can notify Jenkins of pushes and PRs
  • GitHub OAuth callback — so GitHub can redirect users back after login

Cloudflare Tunnel creates a secure outbound-only connection from your machine to Cloudflare's edge — no open firewall ports required.


Prerequisites

  • A domain managed by Cloudflare (free plan works)
  • cloudflared installed
winget install Cloudflare.cloudflared
brew install cloudflare/cloudflare/cloudflared
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb

Step 1 — Authenticate

cloudflared tunnel login

Opens a browser to authorize cloudflared against your Cloudflare account. Select the domain you want to use.


Step 2 — Create a named tunnel

cloudflared tunnel create jenkins

Note the tunnel ID in the output (UUID format).


Step 3 — Create the config file

%USERPROFILE%\.cloudflared\config.yml

~/.cloudflared/config.yml

tunnel: <your-tunnel-id>
credentials-file: <credentials-path>

ingress:
  - hostname: jenkins.yourdomain.com
    service: http://localhost:8080
  - service: http_status:404

Set credentials-file to the path of your tunnel credentials JSON:

C:\Users\<your-username>\.cloudflared\<tunnel-id>.json
~/.cloudflared/<tunnel-id>.json

Replace jenkins.yourdomain.com with your actual subdomain.


Step 4 — Create the DNS record

cloudflared tunnel route dns jenkins jenkins.yourdomain.com

Creates a CNAME in Cloudflare DNS pointing your subdomain at the tunnel. Takes effect immediately.


Step 5 — Run as a service

For Jenkins to always be reachable without manually starting the tunnel:

cloudflared service install
net start cloudflared
sudo cloudflared service install
sudo launchctl start com.cloudflare.cloudflared
sudo cloudflared service install
sudo systemctl enable --now cloudflared

Verify the tunnel is active in the Cloudflare dashboard under Zero Trust → Access → Tunnels.


Step 6 — Update .env

JENKINS_URL=https://jenkins.yourdomain.com

This value is used by:

  • casc.yml to set Jenkins' own address (for webhook URL construction)
  • The Jenkins CI App webhook URL: https://jenkins.yourdomain.com/github-webhook/
  • The Jenkins Login App callback URL: https://jenkins.yourdomain.com/securityRealm/finishLogin

Temporary tunnel (testing only)

No domain yet? Use a temporary tunnel:

cloudflared tunnel --url http://localhost:8080

Not for permanent use

This gives a random *.trycloudflare.com URL that expires when the process stops. You'll need to update the GitHub App webhook URL, OAuth callback URL, and JENKINS_URL in .env every time you restart it.


Troubleshooting

Tunnel shows as inactive in dashboard

Check the service is running:

sc query cloudflared
sudo launchctl list | grep cloudflared
sudo systemctl status cloudflared

502 / 503 from the tunnel URL

Jenkins may not be running. Check: docker compose ps

OAuth callback mismatch error

The URL in your Jenkins Login App settings must exactly match JENKINS_URL/securityRealm/finishLogin including the protocol (https://).


Cloudflare Pages (docs hosting)

This documentation is hosted on Cloudflare Pages, deployed automatically on every push to main.

Create a Pages project

  1. Cloudflare dashboard → Workers & Pages → Create
  2. Pages → Connect to Git
  3. Authorize Cloudflare to access GitHub and select the magi repo

Configure the build

Setting Value
Production branch main
Build command pip install -r requirements-docs.txt && mkdocs build
Build output directory site
Root directory /

Save and Deploy. Every push to main triggers a new deployment automatically. Every pull request gets a unique preview URL.

Custom domain (optional)

Pages project settings → Custom domains → add a subdomain, e.g. jenkins-docs.yourdomain.com. Cloudflare creates the DNS record automatically.

Once live, update mkdocs.yml:

site_url: https://jenkins-docs.yourdomain.com