Skip to content

Cloudflare

Cloudflare is the service I use for pretty much everything on the outside of the home network. It is the registrar for saxobroko.com, handles DNS, SSL, WAF, Cloudflare Tunnels (because I am behind CGNAT), and hosts SaxDocs on Cloudflare Pages.

How to login

  1. Go to dash.cloudflare.com
  2. Enter account details
  3. It should come up with a 2FA prompt. It'll use the Yubikey
  4. Now you're logged in

How homelab traffic works (CGNAT + tunnels)

I cannot port-forward from the internet anymore. Instead:

Browser → Cloudflare edge (DNS, SSL, WAF) → Tunnel → cloudflared on LAN → app on TrueNAS

Most homelab subdomains use the block no aus WAF rule (Australia only). SaxDocs on Pages is public unless Cloudflare Access is enabled.

Full subdomain list: Network

Hosting SaxDocs on Cloudflare Pages

SaxDocs used to deploy to GitHub Pages and also ran locally on the PC behind NPM. The current setup builds in GitHub Actions and hosts on Cloudflare Pages instead.

One-time setup

1. Create a Cloudflare API token

  1. In Cloudflare, go to My Profile > API Tokens
  2. Click Create Token
  3. Use the Edit Cloudflare Workers template, or create a custom token with:
  4. Account > Cloudflare Pages > Edit
  5. Account > Account Settings > Read
  6. Zone > DNS > Edit (needed to remove old home-network DNS records)
  7. Zone > Zone > Read (optional fallback for DNS cleanup)
  8. Copy the token. You won't see it again.

2. Get your Account ID

  1. Open the Cloudflare dashboard
  2. Select any site (e.g. saxobroko.com)
  3. On the right sidebar under API, copy the Account ID

3. Add GitHub secrets

In github.com/saxobroko/SaxDocs/settings/secrets/actions, add:

Secret Value
CLOUDFLARE_API_TOKEN The token from step 1
CLOUDFLARE_ACCOUNT_ID The account ID from step 2
CLOUDFLARE_ZONE_ID Optional. Zone ID for saxobroko.com if DNS cleanup fails

4. Create the Pages project

Push to main once the secrets are set. GitHub Actions will run wrangler pages deploy and create a project called saxdocs automatically on the first successful deploy.

Or create it manually:

  1. Go to Workers & Pages > Create > Pages > Connect to Git
  2. Select the SaxDocs repo
  3. Set build command to pip install -r requirements.txt && mkdocs build
  4. Set build output directory to site
  5. Set PYTHON_VERSION environment variable to 3.12

The GitHub Actions workflow is preferred because it keeps the build in one place and doesn't need Cloudflare to install Python dependencies on every deploy.

5. Attach the custom domain

  1. Open the saxdocs Pages project
  2. Go to Custom domains
  3. Add docs.saxobroko.com
  4. Cloudflare will create or update the DNS record for you since saxobroko.com is already on Cloudflare

6. Remove the old local proxy setup

If docs.saxobroko.com still points at the home network, fix the DNS:

  1. Go to Websites > saxobroko.com > DNS
  2. Find the docs record
  3. If it is a CNAME to local.saxobroko.com or a tunnel hostname, delete it
  4. Let Cloudflare Pages recreate it when you add the custom domain in step 5

Also remove the docs proxy host from NPM if it is still there. It is no longer needed.

7. WAF rules

Most of my subdomains use the block no aus rule. Public docs probably should not be geo-blocked. When adding docs.saxobroko.com to Cloudflare rules, skip the WAF geo rule for docs unless you actually want it restricted to Australia.

The localnet full strict ssl rule is for tunnel-backed services at home. Cloudflare Pages handles SSL on its own, so docs does not need that rule.

Consider Cloudflare Access on SaxDocs if personal pages should require login.

Checking deploys

How to add a new homelab site (tunnel era)

The old workflow was CNAME → local.saxobroko.com. That does not work behind CGNAT. Use a tunnel instead.

1. Run the app on TrueNAS

Deploy via Docker/Apps on the NAS at 192.168.2.203. Note the internal hostname and port.

2. Add a Cloudflare Tunnel public hostname

  1. Cloudflare dashboard → Zero TrustNetworksTunnels
  2. Open the existing tunnel (or create one with cloudflared on TrueNAS)
  3. Public Hostname → Add:
  4. Subdomain: e.g. example
  5. Domain: saxobroko.com
  6. Service: internal URL, e.g. http://192.168.2.203:8080 or http://npm:81 if going through NPM
  7. Save

Cloudflare creates DNS automatically for tunnel hostnames — no manual CNAME to local needed.

3. Optional — route through NPM

If the app needs a custom path, multiple backends, or a single entry point, add a Proxy Host in NPM first, then point the tunnel at NPM's internal port.

4. WAF rules

Add the new hostname to existing rules so SSL and geo-blocking match the rest of homelab:

  1. Websitessaxobroko.comRulesConfiguration Ruleslocalnet full strict ssl
  2. Edit the expression — append:
 or (http.host eq "EXAMPLE.saxobroko.com")
  1. SecurityWAFCustom rulesblock no aus
  2. Same append (skip this step for intentionally public sites like docs or blog)

Replace EXAMPLE with your subdomain.

Legacy: CNAME to local (pre-CGNAT)

If you ever regain a routable public IP, the old steps were:

  1. Add a CNAME record: EXAMPLElocal.saxobroko.com
  2. Add the hostname to localnet full strict ssl and block no aus as above

This is kept for reference only. Current setup uses tunnels — see Network.