Authentik and protecting SaxDocs
Authentik is the SSO layer for homelab apps. It runs at auth.saxobroko.com.
SaxDocs login uses Cloudflare Access → Authentik OIDC. You get the same username/password prompt as other Authentik apps (not email one-time PIN).
Current status
| Step | Status |
|---|---|
Cloudflare Access app for docs.saxobroko.com |
Live |
| Authentik OIDC identity provider in Cloudflare | Live — named "Authentik" |
| Allow policy | Live — any Authentik user |
| Matching OAuth2 provider in Authentik | Live — slug cloudflare-access |
WAF skip rules for auth + docs |
Done |
Cloud Cursor cannot finish the Authentik step. Cloud agents have no route to 192.168.2.203 and auth.saxobroko.com API hits Cloudflare bot challenges from outside Australia. Run the setup script from your PC or TrueNAS shell instead.
Client ID: Zero Trust → Integrations → Identity providers → Authentik (or Settings → Authentication). Cloudflare never shows an existing client secret after save — only ********. To get a usable secret, click Rotate secret / Regenerate in that IdP panel (or rotate via API), copy the new value immediately, then paste the same secret into Authentik. Store in Vaultwarden too.
Login flow
Browser → docs.saxobroko.com
→ Cloudflare Access (Authentik IdP only)
→ auth.saxobroko.com login (username + password)
→ back to docs
Same credentials as Homepage / dash when those use Authentik.
One-time Authentik setup
Create an OAuth2/OpenID provider that matches the Cloudflare IdP.
Option A — Authentik UI (easiest)
- Open auth.saxobroko.com → Admin interface
- Applications → Create with Provider
- Provider type: OAuth2/OpenID Provider
- Settings:
- Name:
Cloudflare Access - Slug:
cloudflare-access(must match JWKS URL in Cloudflare) - Client type: Confidential
- Grant types:
authorization_code(required — Cloudflare uses the auth-code flow) - Client ID / Secret: copy from Cloudflare Zero Trust → Authentik login method
- Redirect URI:
https://saxobroko.cloudflareaccess.com/cdn-cgi/access/callback - Authorization flow: default provider authorization flow
- Invalidation flow: default provider invalidation flow
- Signing key: any active certificate
- Scopes (under Advanced protocol settings): add
openid,email, andprofile - Include claims in ID token: enabled (checked)
- Save
Also confirm your Authentik user has an email address set under Directory → Users — Cloudflare Access requires it.
Option B — Script from home LAN (recommended)
On your Windows PC or TrueNAS (not Cloud Cursor):
cd /path/to/SaxDocs # or clone the repo
export AUTHENTIK_URL='http://192.168.2.203:30140'
export AUTHENTIK_TOKEN='your-authentik-admin-api-token'
export AUTHENTIK_CLIENT_ID='from-cloudflare-zero-trust-authentik-idp'
export AUTHENTIK_CLIENT_SECRET='from-cloudflare-zero-trust-authentik-idp'
./scripts/setup-authentik-provider.sh
Get an admin API token in Authentik: Admin → Directory → Tokens → Create (or use an existing token).
PowerShell on Windows (Git Bash or WSL):
$env:AUTHENTIK_URL='http://192.168.2.203:30140'
$env:AUTHENTIK_TOKEN='your-token'
$env:AUTHENTIK_CLIENT_ID='from-cloudflare'
$env:AUTHENTIK_CLIENT_SECRET='from-cloudflare'
bash scripts/setup-authentik-provider.sh
Option C — Re-run Cloudflare script
If starting fresh:
Then complete Option A or B with the printed client credentials.
Verify
- Incognito → docs.saxobroko.com
- Should land on Authentik login (username/password), not MkDocs
- After login → SaxDocs loads
- GitHub Actions deploy still works (uses API token, not browser Access)
Cloudflare Zero Trust → Access → Applications → SaxDocs → Test on the Authentik login method.
What uses Authentik today
| App | URL | Notes |
|---|---|---|
| Homepage | dash.saxobroko.com | Forward auth / proxy |
| SaxDocs | docs.saxobroko.com | Cloudflare Access + OIDC |
| Authentik | auth.saxobroko.com | Must stay reachable for callbacks |
Credentials for Authentik admin live in Vaultwarden. Do not commit passwords to this repo.
Troubleshooting
Cloudflare challenge / JS check instead of login: Turn off Bot Fight Mode for the zone (Zero Trust → Settings → Network, or zone Security). Bot Fight Mode cannot be skipped with WAF rules and blocks the Access login handshake.
Authentik shows "Not Found": Cloudflare was pointing at the wrong authorize URL (/application/o/cloudflare-access/authorize/ — 404). Correct auth URL is the generic endpoint below. If you still see Not Found, hard-refresh or use incognito — an old tab may have cached the bad redirect.
Script returns 403 Forbidden: The AUTHENTIK_TOKEN is wrong, expired, or lacks permissions. Create a fresh token in Authentik Admin → Directory → Tokens and App passwords → Create — set Intent to API Token, assign your admin user, then copy the secret value shown once (not the Identifier label shown later). Export it and re-run without sudo:
export AUTHENTIK_TOKEN='the-long-random-string-from-create-screen'
curl -H "Authorization: Bearer $AUTHENTIK_TOKEN" http://192.168.2.203:30140/api/v3/root/config/
If that curl returns JSON with a version number, the token works. If it returns 403, create another token.
Easier alternative — skip the script: Admin → Applications → Cloudflare Access → Provider → paste Client ID, Client Secret, redirect URI, and scopes from below.
"User email was not returned" after Authentik login: Cloudflare got no email claim in the OIDC token. In the Authentik provider, under Advanced protocol settings, add scopes openid, email, profile, and enable Include claims in ID token. Also check Directory → Users → your account has an email address filled in. Save the provider, then retry incognito.
export AUTHENTIK_URL='http://192.168.2.203:30140'
export AUTHENTIK_TOKEN='your-token'
export AUTHENTIK_CLIENT_ID='from-cloudflare'
export AUTHENTIK_CLIENT_SECRET='from-cloudflare'
./scripts/setup-authentik-provider.sh
Login loop: Authentik (auth.saxobroko.com) must not itself be behind Cloudflare Access.
IdP test fails in Cloudflare: Slug must be cloudflare-access, redirect URI must match exactly (no trailing slash), client ID/secret must match both sides.
403 challenge instead of login: Usually bot/challenge from curl — test in a real browser from Australia.
OIDC endpoints (reference):
| Setting | URL |
|---|---|
| Auth URL | https://auth.saxobroko.com/application/o/authorize/ |
| Token URL | https://auth.saxobroko.com/application/o/token/ |
| JWKS | https://auth.saxobroko.com/application/o/cloudflare-access/jwks/ |
| Redirect | https://saxobroko.cloudflareaccess.com/cdn-cgi/access/callback |
Official guide: Authentik + Cloudflare Access
Content hygiene
Access stops casual browsing. It is not encryption at rest.
- Avoid full street addresses in markdown (defense in depth)
- Finance screenshots remain in git history on GitHub
- Page history links point to public GitHub commits
Related
- Cloudflare — tunnels, WAF, Pages deploy
- Network — subdomain list
- This docs site — build and deploy