Cloudflare (Pages + Access)¶
Owner: Bryan · Every docs site we run is a Cloudflare Pages project gated by Cloudflare Access.
Values that never change¶
| Item | Value |
|---|---|
| GitHub org | Dalayon-Reports (repos private) |
| Pages build command | pip install -r requirements.txt && mkdocs build |
| Pages output dir | site |
| Pages env var | PYTHON_VERSION = 3.12 |
| Zero Trust team | dalayon |
| Zero Trust team domain | dalayon.cloudflareaccess.com |
| Plan | Free (50 Access seats) |
| Google OAuth redirect URI | https://dalayon.cloudflareaccess.com/cdn-cgi/access/callback |
| Login methods | One-time PIN + Google (account-wide, already set up) |
| Session duration | 24 hours |
Deploy a Pages project¶
- Cloudflare dashboard → Compute → Workers & Pages → Create application.
- It defaults to the Worker flow. Click "Looking to deploy Pages? Get started" to switch to Pages. (The Worker flow /
npx wrangler deployis wrong for a static site.) - Connect to Git → GitHub → Dalayon-Reports → select the repo → Begin setup.
- Enter the build settings from the table above. Framework preset =
None. - Save and Deploy. Site goes live at
<project>.pages.dev. - Custom domains tab → Set up a domain → enter the subdomain → Activate. DNS auto-creates (dalayon.work is on Cloudflare); SSL active in a few minutes.
Gate a site with Access¶
- Zero Trust → Access → Applications → Add an application → Self-hosted, inner tab Public DNS → Continue.
- Destinations → Public hostnames. Add both:
- the custom hostname (subdomain +
dalayon.work, no path), and - the
.pages.devhostname (use "Switch to custom input"). Gating both closes the public.pages.devback door. Never skip the second one.
- the custom hostname (subdomain +
- Access policy → Create new policy:
- Action Allow.
- Include →
Emails ending infor a domain, and/or Include →Emailsfor specific addresses. - Always include your own and the team's emails so you do not lock yourselves out.
- Authentication: leave "Accept all available identity providers" on (One-time PIN + Google already exist account-wide; no IdP setup per site).
- Session duration 24 hours. Create.
- Verify in incognito: the custom domain and the
.pages.devURL should both require login; an allowed email gets in; a non-listed email is denied.
Two gating patterns¶
| Site | Policy = who gets in |
|---|---|
Client hub (<slug>.dalayon.work) |
The client's email domain (or specific emails) plus the team. |
This ops manual (ops.dalayon.work) |
Team emails only. No client domains, ever. |
Gate ops.dalayon.work and ops-manual.pages.dev. Same two-destination rule.
Access rules (do not break these)¶
- Never add clients as Cloudflare account Members. That grants dashboard admin. Clients only go on the Access policy email list; they consume an Access seat (50 free) on first login.
- Confidential content (KPIs, revenue) goes live only after the gate is confirmed. Keep placeholders until then.
- One-time PIN must exist as an identity provider or only account members can log in. It is already set account-wide.
Cache after deploy¶
docs/_headers sets no-cache on /stylesheets/* and /assets/* so edited CSS/JS/data revalidate after a deploy. Locally, hard-refresh (Ctrl+Shift+R) to beat stale CSS.