Hosting Plan
Where each public surface lives. Cloudflare Pages for static; Cloudflare Access for private docs; the preview-deployment-access gotcha that bites everyone once.
The hosting plan is small on purpose. Three Cloudflare Pages projects cover the entire 5-year brand surface: the public portfolio + blog at abukix.dev, the private ROOT docs at root.abukix.dev, and the Year-5 Studio demo at studio.abukix.dev. Everything else (DNS, email routing, private-doc auth) is Cloudflare-native and free at the scale a solo operator needs. The whole architecture is designed so that the daily workflow is git push and nothing else.
The one trap worth surfacing immediately is the preview-deployment-access default. Cloudflare Pages serves preview URLs publicly even when a zone-level Access policy is configured — the policy doesn’t enforce on <commit>.<project>.pages.dev until you flip a setting that’s off by default. Anyone who’s been bitten by this remembers it; everyone else needs the warning before they connect their first private repo.
Architecture
abukix.dev → Custom HTML portfolio + blog (public) Repo: github.com/abukix/portfolio (public) Build: bash build.sh; output: _site/
abukix.dev/blog → MkDocs Material blog (public) Repo: github.com/abukix/portfolio (public) Source: posts/
studio.abukix.dev → Abukix Studio public surface (Y5 P29 launch) Repo: github.com/abukix/studio-frontend (public) Stack: Next.js + Tailwind on Cloudflare Pages
root.abukix.dev → ROOT private docs (private; behind Cloudflare Access) Repo: github.com/abukix/root (private — this repo) Build root: / Stack: TBD (Astro + Tailwind candidate)The studio.abukix.dev surface is the public face of the Studio Plan and the demo home for the composition recipes. It’s the only one of the four with a moving backend (Cloud Run / Fargate); the others are static.
Stack per surface
| Component | Tool | Why |
|---|---|---|
| Domain + DNS | Cloudflare | Already planned for email routing |
| Static hosting | Cloudflare Pages | Free, fast, deploys from GitHub on every push |
| Private docs auth | Cloudflare Access (Zero Trust) | Free for <50 users, email OTP login |
| Portfolio | Custom HTML / vanilla CSS+JS | Terminal-style brand, no framework |
| Blog | MkDocs Material | Renders posts/ markdown, RSS feed |
| ROOT private | Astro + Tailwind (planned) | More flexibility than MkDocs |
| Studio frontend | Next.js + Tailwind on Pages | Production-shape demo surface |
Cloudflare Pages auto-sync behavior
Once a project is connected to a GitHub repo:
| Event | What Cloudflare does |
|---|---|
Push to main (production branch) | Builds + deploys to live URL automatically (~30-90s) |
| Push to other branches | Creates preview deployment at <commit-hash>.<project>.pages.dev |
| Build script fails | Skips deploy, previous version stays live |
| Manual rebuild needed | Click “Retry deployment” in dashboard |
Daily workflow: git push. No manual deploy steps.
CRITICAL: Preview deployment access (the gotcha)
When you create a Cloudflare Pages project AND apply a Cloudflare Access policy at the zone level (e.g., root.abukix.dev), the Access app DOES NOT enforce on preview deployments by default.
The default for “Preview deployment access” is Public. Pages serves all your <commit-hash>.<project>.pages.dev URLs publicly even though the zone-level Access app exists. Without changing this setting, your private content is publicly accessible at the preview URL.
Fix it:
Cloudflare Dashboard → Pages → <project> → Settings → Deployments → Deployment access
Change "Preview deployment access" from "Public" to: ⊙ "Private — require Access policy"
Save.Without this, the zone-level Access app does NOT enforce on preview deployments — Pages bypasses it, serving traffic publicly even though the Access app exists. This single setting is the most common reason “my Access policy isn’t working” — no error, just public.
Verify after setting: visit a preview URL in incognito → should see Access login screen.
Cloudflare Pages setup: per project
Project 1: Portfolio + Blog (abukix.dev)
Cloudflare Pages project: abukix-portfolioGitHub repo: abukix/portfolioBuild settings: Build command: bash build.sh Output directory: _site Root directory: /
Custom domain: abukix.dev (apex) + www.abukix.dev (redirect to apex)Access policy: none (public)Preview deployment: (default Public is fine — public anyway)Project 2: ROOT private docs (root.abukix.dev)
Cloudflare Pages project: abukix-rootGitHub repo: abukix/root (this repo)Build settings: Build command: (depends on chosen stack — Astro: npm run build; MkDocs: bash build.sh) Output directory: (Astro: dist; MkDocs: site) Root directory: /
Custom domain: root.abukix.devAccess policy: Cloudflare Zero Trust → Access → Application → root.abukix.dev Identity: One-time PIN (email OTP) Allow: me@abukix.dev (add backups if desired)
★★★ Preview deployment access: PRIVATE — require Access policy ★★★Project 3: Abukix Studio (studio.abukix.dev: Y5 P29)
Cloudflare Pages project: abukix-studioGitHub repo: abukix/studio-frontend (public)Build settings: Build command: npm run build Output directory: .next (or out for static export) Root directory: /
Custom domain: studio.abukix.devAccess policy: none (public, but rate-limited)Backend: Cloud Run / Fargate (separate; not Pages)Setup checklist (when each project goes live)
Pre-Phase-1 — Domain:[ ] Buy abukix.dev on Cloudflare Registrar (or transfer)[ ] Confirm Cloudflare DNS is the active nameserver[ ] Set up email routing (Google Workspace MX records)
Pre-Phase-1 — ROOT private docs (root.abukix.dev):[ ] Confirm abukix/root pushed to GitHub (private)[ ] Cloudflare Pages → Create project → Connect to GitHub[ ] Select repo: abukix/root[ ] Build command + output directory (per chosen stack)[ ] Save → first build runs (verify on *.pages.dev URL)[ ] Custom domain: root.abukix.dev[ ] Cloudflare Zero Trust → Access → Applications → New[ ] Self-hosted, Domain: root.abukix.dev[ ] Identity provider: One-Time PIN[ ] Policy: Allow me@abukix.dev[ ] ★★★ Pages → Settings → Deployment access → "Private — require Access policy" ★★★[ ] Test: visit root.abukix.dev → login screen → OTP → docs render[ ] Test: visit a preview URL (find in Pages dashboard) → login required
Y2 P9 — Portfolio + Blog (abukix.dev):[ ] Confirm abukix/portfolio pushed to GitHub (public)[ ] Cloudflare Pages → Create project → Connect to GitHub[ ] Build command: bash build.sh[ ] Output directory: _site[ ] Root directory: /[ ] Save → first build[ ] Custom domain: abukix.dev (apex) + www redirect[ ] Test: visit abukix.dev → portfolio[ ] Test: visit abukix.dev/blog → blog index[ ] Test: visit abukix.dev/blog/01-terralabs-launch → first post renders
Y5 P29 — Abukix Studio (studio.abukix.dev):[ ] Confirm abukix/studio-frontend pushed (public)[ ] Cloudflare Pages → new project[ ] Build: npm run build[ ] Custom domain: studio.abukix.dev[ ] Cloud Run / Fargate backend deployed separately[ ] Rate limit: per-IP via Cloudflare Workers[ ] Cost cap: budget alert at $50/month[ ] Demo data seeded (sanitized)Cost
Cloudflare Pages: Free (unlimited sites, 500 builds/month per project)Cloudflare Access: Free (up to 50 users)abukix.dev domain: ~$10-12/yearGoogle Workspace: ~$72/year (Business Starter, 1 user)Studio backend (Y5): ~$30-50/month, capped (Cloud Run + scheduled cleanup)
Total before Y5: ~$80-85/yearTotal during Y5 demo: ~$80 + $360-600 = ~$440-680When to actually deploy
Per the brand strategy, the portfolio repo lives publicly on GitHub from day 1 but the Cloudflare Pages connection is deferred until:
- 5+ blog posts in
posts/ - At least one shipped Year 1 project (
ops-handbookwith real runbooks) - ROOT Phase 1-3 complete or in progress
Avoids launching abukix.dev as a brochure for work that hasn’t started.
The private root.abukix.dev can be deployed earlier (it’s behind Access, no public-visibility risk) — useful for accessing your own docs from any device once homelab is rich enough to need them.
Cross-references
- accounts-setup.md — the accounts that own these surfaces
- identity.md — what the surfaces represent
- content-playbook.md — what gets published to which surface
- launch-playbook.md — when each surface gets a loud moment
- Studio Plan — what
studio.abukix.devis fronting - Studio composition recipes — the demos hosted on the Studio surface
- Master Plan — the curriculum the surfaces document
- homelab/hardware — the substrate behind the brand