Cloudflare Pages Deployment
This site is deployed to Cloudflare Pages with Zero Trust authentication.
Architecture
| Component | Value |
|---|---|
URL |
|
Platform |
Cloudflare Pages |
Build Tool |
Antora |
Authentication |
Cloudflare Access (Zero Trust) |
Build Configuration
Cloudflare Pages Settings
| Setting | Value |
|---|---|
Build command |
|
Output directory |
|
Node version |
22 (auto-detected) |
Environment Variables
| Variable | Description | Location |
|---|---|---|
|
GitHub PAT for cloning private repos |
Cloudflare Pages → Settings → Environment Variables |
Token Requirements
Fine-grained GitHub PAT with:
-
Repository access: All 15 domus-* repos
-
Permissions: Contents (read-only)
Repos requiring access:
-
domus-docs
-
domus-infra-ops
-
domus-ise-linux
-
domus-ise-windows
-
domus-ise-ops
-
domus-netapi-docs
-
domus-secrets-ops
-
domus-linux-ops
-
domus-python
-
domus-identity-ops
-
domus-captures
-
domus-automation-ops
-
domus-siem-ops
-
domus-o11y-ops
-
domus-windows-ops
Build Script
The build.sh script orchestrates the full build pipeline:
-
Validates required environment variables (
CF_ANTORA_GIT_TOKEN,CF_ACCESS_CLIENT_ID,CF_ACCESS_CLIENT_SECRET) -
Downloads the UI bundle from
ui.domusdigitalis.devwith Cloudflare Access authentication -
Validates the bundle (minimum 50 KB, ZIP integrity, theme CSS presence)
-
Creates a temporary playbook with GitHub token injected into URLs
-
Runs Antora with
--quietto prevent token exposure in logs -
Cleans up the temporary playbook on exit (via trap)
#!/bin/bash
set -euo pipefail
# Required environment variables
: "${CF_ANTORA_GIT_TOKEN:?Missing GitHub PAT}"
: "${CF_ACCESS_CLIENT_ID:?Missing Cloudflare Access Client ID}"
: "${CF_ACCESS_CLIENT_SECRET:?Missing Cloudflare Access Client Secret}"
# Download UI bundle with Cloudflare Access auth + retry logic
curl -fsSL -o ui-bundle.zip \
-H "CF-Access-Client-Id: ${CF_ACCESS_CLIENT_ID}" \
-H "CF-Access-Client-Secret: ${CF_ACCESS_CLIENT_SECRET}" \
"https://ui.domusdigitalis.dev/ui-bundle.zip?v=$(date +%s)"
# Create temp playbook with token injection (never modify original)
PLAYBOOK_TMP=$(mktemp)
trap "rm -f $PLAYBOOK_TMP" EXIT
sed "s|https://github.com/EvanusModestus/|https://${CF_ANTORA_GIT_TOKEN}@github.com/EvanusModestus/|g" \
antora-playbook.yml > "$PLAYBOOK_TMP"
# Build (--quiet prevents token in logs)
npx antora --quiet "$PLAYBOOK_TMP"
The --quiet flag and temporary playbook pattern prevent token exposure in build logs.
|
Cloudflare Access
The site is protected by Cloudflare Zero Trust Access.
Configuration
| Setting | Value |
|---|---|
Application name |
Domus Docs |
Domain |
docs.domusdigitalis.dev |
Authentication |
Email-based |
Access Applications
Two Access applications are required for proper operation:
| Application | Domain | Purpose |
|---|---|---|
|
|
Protects documentation content (requires authentication) |
|
|
Bypasses authentication for static assets (CSS, JS, fonts) |
|
Without the static assets bypass, the site will appear white/unstyled because CSS files return 302 redirects to the Access login page. |
Managing Access via netapi
# List all Access applications
netapi cloudflare access apps
# List policies for an application
netapi cloudflare access policies <app-id>
# Create static assets bypass (one command)
netapi cloudflare access bypass-static docs.domusdigitalis.dev
See netapi cloudflare commands for full documentation.
Managing Access via API
# List Access applications
curl -s "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/access/apps" \
-H "Authorization: Bearer ${CF_API_TOKEN}" | jq '.result[] | {id, name, domain}'
# Create static bypass app
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/access/apps" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "domus-docs-static", "type": "self_hosted", "domain": "docs.domusdigitalis.dev/_/*"}'
# Add bypass policy
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/access/apps/<APP_ID>/policies" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "Bypass Static Assets", "decision": "bypass", "include": [{"everyone": {}}]}'
Deployment Workflow
-
Make changes to any domus-* repo
-
Push to GitHub
-
Cloudflare Pages automatically rebuilds (via deploy hooks)
All content repos have webhooks configured to trigger rebuilds on push.
Deploy Hooks
Deploy hooks enable automatic rebuilds when any content repo is updated.
Architecture
domus-infra-ops ──┐
domus-ise-linux ──┤
domus-ise-windows ──┤
domus-ise-ops ──┤
domus-netapi-docs ──┤
domus-secrets-ops ──┼──→ GitHub Webhook ──→ Cloudflare Deploy Hook ──→ Rebuild
domus-linux-ops ──┤
domus-python ──┤
domus-identity-ops ──┤
domus-captures ──┤
domus-automation-ops──┤
domus-siem-ops ──┤
domus-o11y-ops ──┤
domus-windows-ops ──┘
Configured Webhooks
| Repository | Webhook Status |
|---|---|
domus-infra-ops |
✓ Active |
domus-ise-linux |
✓ Active |
domus-ise-windows |
✓ Active |
domus-ise-ops |
✓ Active |
domus-netapi-docs |
✓ Active |
domus-secrets-ops |
✓ Active |
domus-linux-ops |
✓ Active |
domus-python |
✓ Active |
domus-identity-ops |
✓ Active |
domus-captures |
✓ Active |
domus-automation-ops |
✓ Active |
domus-siem-ops |
✓ Active |
domus-o11y-ops |
✓ Active |
domus-windows-ops |
✓ Active |
Setup (For Reference)
1. Create Deploy Hook in Cloudflare
-
Cloudflare Dashboard → Pages → domus-docs → Settings → Builds & deployments
-
Scroll to Deploy hooks
-
Click Add deploy hook
-
Name:
github-content-repos -
Copy the generated URL
2. Add Webhook to GitHub Repos
HOOK_URL="https://api.cloudflare.com/client/v4/pages/webhooks/deploy_hooks/YOUR_HOOK_ID"
for repo in domus-infra-ops domus-ise-linux domus-ise-windows domus-ise-ops domus-netapi-docs domus-secrets-ops domus-linux-ops domus-python domus-identity-ops domus-captures domus-automation-ops domus-siem-ops domus-o11y-ops domus-windows-ops; do
gh api repos/EvanusModestus/$repo/hooks \
--method POST \
-f name=web \
-f "config[url]=$HOOK_URL" \
-f "config[content_type]=json" \
-F "events[]=push" \
-F active=true
done
Troubleshooting
Webhook Not Triggering
-
Check GitHub → Repo → Settings → Webhooks → Recent Deliveries
-
Look for failed deliveries (red X)
-
Verify Cloudflare deploy hook URL is still valid
Manual Rebuild
If webhooks fail or you need to force a rebuild after pushing to spoke repos:
# One-liner: Empty commit + push to all remotes
cd /home/evanusmodestus/atelier/_bibliotheca/domus-docs && \
git commit --allow-empty -m "chore: trigger rebuild" && \
git remote | xargs -I {} git push {} main
[main 13b190b] chore: trigger rebuild To gitea-01.inside.domusdigitalis.dev:evanusmodestus/domus-docs.git 1daa4d7..13b190b main -> main To gitlab.com:EvanusModestus/domus-docs.git 1daa4d7..13b190b main -> main To github.com:EvanusModestus/domus-docs.git 6f5e816..13b190b main -> main
Alternative methods:
# Option 2: Push to GitHub only (triggers Cloudflare)
git push origin main
# Option 3: Cloudflare Dashboard
# Pages → domus-docs → Deployments → Retry deployment
# Option 4: Cloudflare API (see CI Trigger Endpoint below)
CI Trigger Endpoint (Roadmap)
| Not yet implemented. This section outlines the planned automation. |
Goal
Create a dedicated endpoint or script that can be called to trigger rebuilds programmatically, useful for:
-
Post-merge hooks from spoke repos
-
Scheduled rebuilds (e.g., daily to catch dependency updates)
-
Integration with CI/CD pipelines
-
Slack/Discord bot commands
Planned Implementation
Option A: Direct Cloudflare API
# Trigger rebuild via Cloudflare Pages API
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/domus-docs/deployments" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json"
Option B: netapi Integration
# Planned: netapi cloudflare pages rebuild domus-docs
netapi cloudflare pages rebuild domus-docs
Option C: GitHub Actions Workflow Dispatch
# .github/workflows/rebuild.yml
name: Trigger Rebuild
on:
workflow_dispatch:
repository_dispatch:
types: [rebuild]
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- run: |
curl -X POST "${{ secrets.CF_DEPLOY_HOOK_URL }}"
Then trigger from any repo:
gh workflow run rebuild.yml --repo EvanusModestus/domus-docs