Runbook — serve the vault at vault.pragalva.me (Cloudflare Pages + Access)
This is the Phase B the DNS runbook (cloudflare-migration-runbook.md) deferred. Phase A
(move pragalva.me DNS to Cloudflare) is already done: dig NS pragalva.me returns
aragorn.ns.cloudflare.com / stevie.ns.cloudflare.com.
Decision (recorded 2026-06-27): host the Quartz vault on Cloudflare Pages, delivered by Git-connect (Cloudflare builds on every push to GitHub), with Cloudflare Access as the login gate. Pages was chosen over self-hosting on devata because the cluster has no public ingress / TLS / GitOps backbone yet. When that backbone exists, this can migrate to a self-hosted origin behind a Cloudflare Tunnel and the Access app + DNS stay unchanged (only the origin moves).
Repo: PragalvaXFREZ/homelab-vault, production branch master.
Build facts (verified locally 2026-06-27)
- Build command:
npx quartz plugin install && npx quartz buildnpx quartz buildALONE FAILS in CI:.quartz/(where plugins install) is gitignored and the config pulls a remote plugin (github:quartz-community/created-modified-date), so plugins must be installed at build time. The Dockerfile does the same two-step. Cloudflare’s build image has git, so thegithub:plugin installs fine.
- Build output directory:
public - Node version:
.node-versionpinsv22.16.0; Cloudflare Pages reads it automatically. If a build ever picks the wrong Node, set env varNODE_VERSION=22.16.0to force it. - Verified: clean build emits
public/index.html(14 notes published,private/excluded).
B1 — create the Pages project (Git-connect)
- Cloudflare dashboard -> Workers & Pages -> Create -> Pages -> Connect to Git.
- Authorize the Cloudflare GitHub app, select repo
PragalvaXFREZ/homelab-vault. - Production branch:
master. - Build settings:
- Framework preset: None
- Build command:
npx quartz plugin install && npx quartz build - Build output directory:
public - Root directory:
/(default)
- (Optional) Environment variables:
NODE_VERSION=22.16.0. - Save and Deploy. Watch the build log; first build takes a few minutes (plugin install + build).
Verify B1: the project’s https://<project>.pages.dev URL serves the vault homepage.
B2 — custom domain vault.pragalva.me
- In the Pages project -> Custom domains -> Set up a custom domain ->
vault.pragalva.me. - Because Cloudflare is authoritative for
pragalva.me, it auto-creates the proxiedCNAMEvault -> <project>.pages.devand issues a managed TLS cert. No manual DNS record needed.
Verify B2:
dig +short vault.pragalva.meresolves (Cloudflare-proxied IPs).https://vault.pragalva.meserves the vault with a valid cert.
B3 — Cloudflare Access (the login gate)
First-time Zero Trust setup: Cloudflare dashboard -> Zero Trust. Pick a team name
(<team>.cloudflareaccess.com). The free plan covers up to 50 users; onboarding may ask for a card
even though it stays free at this scale.
- Zero Trust -> Settings -> Authentication -> add a login method. Simplest is One-time PIN (email OTP, no IdP setup). Google login also works well since the allowed account is a Gmail.
- Zero Trust -> Access -> Applications -> Add an application -> Self-hosted.
- Name:
Homelab Vault - Session duration: 1 week (personal site, low risk).
- Public hostname:
vault.pragalva.me(leave path blank to gate the whole site).
- Name:
- Add a policy:
- Action: Allow
- Include: Emails ->
dhirajs6342@gmail.com(add more later to share).
- Save.
Verify B3: open https://vault.pragalva.me in a private window -> redirected to the Cloudflare
Access login -> after email OTP / Google, the vault loads. Without auth, no access.
Update flow after this is set up
Edit notes under content/, commit, push to master. Cloudflare rebuilds and redeploys
automatically. Nothing to run by hand.
Rollback
- Remove the gate: Zero Trust -> Access -> Applications -> delete the
Homelab Vaultapp (the site becomes public but still served). - Take the site down: Pages project -> Custom domains -> remove
vault.pragalva.me, or delete the Pages project. ThevaultCNAME disappears with the custom domain. - None of this touches the apex blog or the zone’s other records.
Watch-item (not blocking the vault)
The apex A pragalva.me currently resolves to Cloudflare proxy IPs (104.21.70.28 /
172.67.218.205), i.e. it is proxied (orange cloud), not the DNS-only Vercel IP the DNS runbook
specified. The blog still returns HTTP 200 through the proxy, so it is working, but the runbook’s
caution about Vercel + Cloudflare proxy (SSL / redirect-loop edge cases) stands. If the blog ever
misbehaves, set the apex record to DNS only (grey cloud) in the Cloudflare DNS panel.