Runbook: Cloudflare Pages New Site Setup
- Last Updated
-
2026-02-17
- Owner
-
Evan Rosado
- Frequency
-
As needed (new site deployment)
Purpose
Deploy a new Antora documentation site to Cloudflare Pages with custom domain and proper security settings.
Two deployment strategies:
| Strategy | Description | Best For |
|---|---|---|
CLI + CI (Recommended) |
Create project via |
Multi-forge portability, full automation |
Dashboard + Git Integration |
Cloudflare pulls from GitHub/GitLab, builds internally |
Simple setup, single-forge projects |
Prerequisites
| Requirement | Details | Verified |
|---|---|---|
Cloudflare account |
Access to dashboard.cloudflare.com |
[ ] |
GitHub repository |
Public or private, contains Antora playbook |
[ ] |
Domain in Cloudflare |
DNS managed by Cloudflare |
[ ] |
Repository builds locally |
|
[ ] |
No secrets in repo |
Run security audit (see below) |
[ ] |
Security Audit (Pre-Deployment)
Before deploying any site publicly, verify no sensitive data:
# Set repo path
REPO_PATH="/path/to/your/repo"
# Scan for secrets/tokens
grep -rIE '(password|secret|token|api.?key|private.?key|BEGIN.*(RSA|PRIVATE))' \
--include="*.adoc" --include="*.yml" --include="*.yaml" --include="*.json" \
"$REPO_PATH" | grep -v node_modules
# Scan for internal IPs/hostnames
grep -rIE '(inside\.|\.internal|10\.50\.|192\.168\.[0-9]+\.[0-9]+)' \
--include="*.adoc" "$REPO_PATH"
# Find sensitive files
find "$REPO_PATH" -name ".env*" -o -name "*.pem" -o -name "*.key" -o -name "credentials*" \
| grep -v node_modules
Expected result: No matches, or only safe references (example IPs, ${{ secrets.* }} patterns).
CLI Workflow (Recommended)
Full programmatic deployment - zero dashboard interaction.
Prerequisites (CLI)
# Load Cloudflare credentials
dsource d000 dev/app
# Verify token works
netapi cloudflare zones
Step 2: Configure GitHub Actions
Create .github/workflows/build.yml:
name: Build Docs
on:
push:
branches: [main]
repository_dispatch:
types: [spoke-updated]
workflow_dispatch:
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx antora antora-playbook.yml
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: $\{{ secrets.CF_API_TOKEN }}
accountId: $\{{ secrets.CF_ACCOUNT_ID }}
command: pages deploy build/site --project-name=architectus-docs
Step 3: Set GitHub Secrets
# Use CI-specific token (no IP filter)
gh secret set CF_API_TOKEN --repo EvanusModestus/architectus-docs --body "<ci-pages-deploy-only-token>"
gh secret set CF_ACCOUNT_ID --repo EvanusModestus/architectus-docs --body "<account-id>"
Step 5: Create DNS Record
# If using separate DNS token
CF_API_TOKEN=$CF_DNS_TOKEN netapi cloudflare dns add architectus.dev \
-t CNAME -n docs -c architectus-docs.pages.dev --proxied
Step 6: Verify
# Trigger deployment
git push origin main
# Watch workflow
gh run watch --repo EvanusModestus/architectus-docs
# Verify site
curl -sI https://docs.architectus.dev | head -5
API Token Strategy
Create separate tokens for security:
| Token | Permissions | Notes |
|---|---|---|
|
Pages:Read, Access:Edit, Cache Purge |
IP-filtered to your machine |
|
Zone:Zone:Read, Zone:DNS:Edit |
IP-filtered to your machine |
|
Account:Cloudflare Pages:Edit |
No IP filter (CI runners need access) |
Dashboard Workflow (Alternative)
Use this if you prefer GUI or need git-connected builds where Cloudflare runs the build.
Step 1: Create Pages Project (Dashboard)
1.1 Navigate to Pages
-
Login to dash.cloudflare.com
-
Select account (if multiple)
-
Left sidebar → Workers & Pages
-
Click Create → Pages → Connect to Git
1.2 Connect Repository
-
Select GitHub (or GitLab)
-
If first time: Authorize Cloudflare to access repos
-
Select repository (e.g.,
EvanusModestus/architectus-docs) -
Click Begin setup
1.3 Configure Build Settings
| Setting | Value |
|---|---|
Project name |
|
Production branch |
|
Framework preset |
None (leave blank) |
Build command |
|
Build output directory |
|
Root directory |
|
1.4 Environment Variables
Click Environment variables → Add:
| Variable | Value | Purpose |
|---|---|---|
|
|
Use Node.js 20.x |
|
|
Faster installs (optional) |
For private UI bundles (Cloudflare Access protected):
| Variable | Value |
|---|---|
|
Service token ID from Cloudflare Access |
|
Service token secret |
1.5 Deploy
-
Click Save and Deploy
-
Wait for build (2-5 minutes for Antora sites)
-
Verify deployment at
<project-name>.pages.dev
Step 2: Custom Domain
2.1 Add Domain
-
Go to project → Custom domains tab
-
Click Set up a custom domain
-
Enter domain:
docs.architectus.dev -
Click Continue
Step 3: Access Control (Optional)
Step 4: Verify Deployment
Troubleshooting
Build Fails: Module Not Found
Error: Cannot find module '@antora/lunr-extension'
Fix: Ensure package.json includes all dependencies:
npm install @antora/lunr-extension --save
git add package.json package-lock.json
git commit -m "fix: add missing Antora extension"
git push
Build Fails: Node Version
Error: Syntax errors or API incompatibilities
Fix: Set NODE_VERSION=20 in environment variables.