Deploying this site¶
This page documents how the Bedrock Docs site itself is built and hosted: a Material for MkDocs static site on Cloudflare Pages, gated behind Google SSO with Cloudflare Zero Trust Access.
This is about the documentation site, not the Bedrock product. For Bedrock operator tasks, see Operator training.
How the build works¶
The markdown source lives at the repo root (architecture/, security/, protocol/,
training/, plus README.md) so it stays readable as raw markdown on GitHub and the
AGENTS.md relative-link contract keeps working.
MkDocs 1.6 refuses to treat the repo root as its docs_dir, so build.sh
syncs the doc tree verbatim into a generated site_src/ (gitignored) and runs
mkdocs build from there. The directory layout is copied unchanged, so every relative
link resolves identically.
The sync auto-discovers content: every top-level *.md file and content directory
is published except the infra/tooling entries (site/, site_src/, .venv-mkdocs/,
.git/, .github/, .claude/, docs/). Add a new section directory and it appears in
the build automatically — you only need to add it to the nav: in mkdocs.yml.
build.sh builds --strict by default, and mkdocs.yml has a validation: block that
promotes broken links and bad anchors to warnings. A broken link therefore fails the
build — and since build.sh is the Cloudflare build command, it fails the deploy. That
is the link gate; there is no separate CI.
git push main
└─> Cloudflare Pages: pip install -r requirements.txt
└─> bash build.sh (sync root docs -> site_src/, then mkdocs build -> site/)
└─> deploy site/ -> Pages domain
└─> request -> Access (Google SSO gate) -> static site
Build locally¶
python3 -m venv .venv-mkdocs
.venv-mkdocs/bin/pip install -r requirements.txt
source .venv-mkdocs/bin/activate
bash serve.sh # live preview at http://127.0.0.1:8000 — edits to the
# root source live-reload (plain `mkdocs serve` would only
# watch the generated site_src/ and miss them)
bash build.sh # one-off production build; --strict, fails on broken links
serve.sh mirrors the root source into site_src/ while mkdocs watches it, so editing
e.g. security/pki.md reloads the browser. site_src/, site/, and .venv-mkdocs/ are
gitignored — never commit them, and never edit site_src/ by hand (it is regenerated on
every build).
Cloudflare Pages¶
One-time setup in the Cloudflare dashboard:
- Workers & Pages → Create → Pages → Connect to Git. Pick the
docsrepo. - Production branch:
main. - Build settings:
- Framework preset: None.
- Build command:
bash build.sh(strict — a broken link fails the deploy). - Build output directory:
site - Cloudflare detects
requirements.txtand installs Python dependencies automatically. If the build image defaults to an old Python, set the environment variablePYTHON_VERSIONto3.12(or newer) in the Pages project settings. - Save and Deploy. Every push to
mainnow builds and deploys; pull requests get preview deployments automatically.
Set site_url in mkdocs.yml
to the final Pages URL (or custom domain) once it exists.
Google SSO with Cloudflare Zero Trust Access¶
This gates the whole site so only your Google Workspace accounts can reach it. It is all click-ops in the Cloudflare Zero Trust dashboard — no code.
Before you start¶
- The Pages project is deployed and you know its domain (e.g.
bedrock-docs.pages.dev, plus any custom domain). - You can create an OAuth client in your Google account (Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application), or you use the Google Workspace integration.
- You know which accounts should have access — a whole email domain
(
@bedrockdefence.com) or an explicit list.
Steps¶
-
Add Google as a login method. Cloudflare Zero Trust → Settings → Authentication → Login methods → Add new → Google (or Google Workspace). Paste the OAuth Client ID and Client secret from Google. In the Google OAuth client, set the authorized redirect URI to the callback Cloudflare shows you (
https://<your-team>.cloudflareaccess.com/cdn-cgi/access/callback). Save, then Test the connection. -
Create the Access application. Zero Trust → Access → Applications → Add an application → Self-hosted. Name it Bedrock Docs. Under Application domain, add the Pages domain (and your custom domain if you have one — add a row for each).
-
Add the policy. Create a policy named Allow workspace, action Allow, with an include rule:
- For a whole domain: selector Emails ending in →
@bedrockdefence.com. -
For specific people: selector Emails → list the addresses.
-
Pick the identity provider. In the application's Authentication settings, select the Google login method you added in step 1 (and deselect any you don't want, so the login page goes straight to Google).
-
Save. Access now sits in front of every request to the site.
How to know it worked¶
- Open the site in a private window: you're redirected to Google sign-in, not the docs.
- Sign in with an allowed account → you reach the site.
- Sign in with a disallowed account → Access shows denied.
- The
*.pages.devdefault domain is covered too — add it as an application domain (or disable it in the Pages project) so there's no unauthenticated back door.
If something goes wrong¶
- Login loops or "callback mismatch". The redirect URI in the Google OAuth client must exactly match the Cloudflare callback URL from step 1.
- Everyone is denied. Check the policy include rule — a trailing space or wrong domain in Emails ending in is the usual cause.
- Site loads with no login prompt. The Access application domain doesn't match the URL
being visited (e.g. the
*.pages.devdomain isn't listed). Add every domain that serves the site.
See also¶
- Material for MkDocs — theme + setup reference
- Cloudflare Pages · Zero Trust Access
AGENTS.md— why the source stays at the repo root