Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,16 @@
.vscode/
.DS_Store
Thumbs.db

# mdBook output. Cloudflare Pages builds it on demand from src/.
book/

# Local mdBook binary cache if a contributor installs into the repo.
.mdbook-bin/

# Chapter copies in src/ are generated by scripts/build.sh from the
# canonical top-level Markdown files. They exist locally after the
# first build, but they are not source-of-truth and should not be
# committed. The only file in src/ that is tracked is SUMMARY.md.
src/*.md
!src/SUMMARY.md
112 changes: 112 additions & 0 deletions DEPLOY_CLOUDFLARE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Deploying to Cloudflare Pages

This is the exact configuration the documentation site uses on
Cloudflare Pages. It is reproduced here so a future deployer can
rebuild the project from scratch without guessing at settings.

## Project settings

In the Cloudflare dashboard under Pages > Create a project > Connect
to Git, point at the `vyrox-security/vyrox-docs` repository and set
the following build configuration.

| Field | Value |
|---|---|
| Production branch | `main` |
| Build command | `bash scripts/build.sh` |
| Build output directory | `book` |
| Root directory | `/` |
| Environment variable | `MDBOOK_VERSION=v0.4.40` |

The build command downloads a pinned mdBook release into
`.mdbook-bin/` if the binary is not already on PATH, syncs the
top-level Markdown into `src/`, and runs `mdbook build`. Output goes
to `book/`, which is what Cloudflare Pages publishes.

You can change the pinned mdBook version by updating
`MDBOOK_VERSION` either in the Cloudflare environment variables or
inline in `scripts/build.sh`. We keep one source of truth so a
release bump is one edit.

## Custom domain

Cloudflare Pages serves the project at `<project>.pages.dev` by
default. The production deployment maps to `docs.vyrox.dev` via a
CNAME under the `vyrox.dev` zone. Configure that under Pages > the
project > Custom domains.

## Headers and redirects

Both files live at the repo root and are copied into `book/` by the
build script:

- `_headers` carries the security headers (CSP, HSTS, frame-ancestors,
referrer policy, permissions policy) plus aggressive caching for
hashed assets and short revalidation for HTML.
- `_redirects` maps the friendly path aliases (`/architecture`,
`/api`, etc) to the mdBook-generated chapter URLs.

The header CSP allows Google Fonts because the site loads Fraunces,
Geist, and JetBrains Mono from `fonts.googleapis.com` and
`fonts.gstatic.com`. Removing those allowances breaks typography.

## Preview deployments

Cloudflare Pages builds every branch automatically. A pull request
gets a preview URL of the form
`<commit-sha>.<project>.pages.dev`. The default behaviour is fine
for our use case; we do not gate previews behind authentication
because the docs are public anyway.

If a contributor adds private documentation in the future, gate the
preview environments via Cloudflare Access. The setting lives under
Pages > the project > Settings > Access policy.

## Local reproduction

Run the exact build that Cloudflare Pages runs:

```bash
bash scripts/build.sh
```

That fetches mdBook into `.mdbook-bin/` (so your global install is
not touched), syncs the top-level Markdown into `src/`, and writes
the site into `book/`. Serve it with anything that serves static
files:

```bash
python -m http.server -d book 8080
```

Or use `mdbook serve` for the watch loop while editing.

## Troubleshooting

**Build fails with "mdbook not found".** The script tries to fetch a
binary from GitHub Releases. Cloudflare Pages build hosts have
outbound HTTPS so this works by default. If you see a download
failure, check the GitHub Releases page for the pinned tag and
verify the URL pattern. Newer mdBook releases sometimes change the
archive naming.

**Build succeeds but the deploy 404s.** The output directory is
`book`, not `dist` or `public`. Double-check the Cloudflare project
settings.

**Headers are not applied.** Cloudflare Pages reads `_headers` from
the root of the published directory. If you do not see your CSP on
production, confirm that `_headers` ended up inside `book/` after the
build. The build script copies it; if you ran `mdbook build`
directly without the script, the copy will not have happened.

**Fonts render as the system default.** Either the CSP is blocking
the Google Fonts CDN, or the build is missing the Google Fonts link
tag. The link tag is injected by `theme/head.hbs`. Confirm with
`grep fonts.googleapis.com book/index.html` that the link is present.

## Cross-references

- [`README.md`](README.md) for the project overview.
- [`CONTRIBUTING.md`](CONTRIBUTING.md) for the docs contribution
workflow.
33 changes: 33 additions & 0 deletions _headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Cloudflare Pages headers.
#
# This file is copied into the build output at deploy time. The hosting
# layer applies these headers to every matched request. Reference:
# https://developers.cloudflare.com/pages/configuration/headers/
#
# We keep the rule set tight. Defaults are deny-by-default for the
# things that should never be there; explicit allows where the site
# legitimately reaches off-host (Google Fonts only).

/*
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

# Aggressive caching on hashed asset files. mdBook fingerprints every
# CSS, JS, and font filename so this is safe for them.
/css/*
Cache-Control: public, max-age=31536000, immutable

/fonts/*
Cache-Control: public, max-age=31536000, immutable

/FontAwesome/*
Cache-Control: public, max-age=31536000, immutable

# HTML revalidates fast so a docs update lands within minutes of a
# Cloudflare Pages deploy without users seeing a stale page.
/*.html
Cache-Control: public, max-age=0, must-revalidate
29 changes: 29 additions & 0 deletions _redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Cloudflare Pages redirects.
#
# Lines are `<source> <destination> <status>`. mdBook publishes every
# chapter at /<NAME>.html where NAME is the source filename without
# the extension. We redirect the friendlier /<name> paths (and the
# .md form a developer might type) to the canonical .html URL.
#
# Reference: https://developers.cloudflare.com/pages/configuration/redirects/

# Root convenience aliases.
/architecture /ARCHITECTURE.html 301
/threat-model /THREAT_MODEL.html 301
/audit-chain /AUDIT_CHAIN.html 301
/api /API_REFERENCE.html 301
/api-reference /API_REFERENCE.html 301
/adapters /ADAPTERS.html 301
/quickstart /QUICKSTART.html 301
/contributing /CONTRIBUTING.html 301
/security /SECURITY.html 301
/roadmap /ROADMAP.html 301
/code-of-conduct /CODE_OF_CONDUCT.html 301

# Anyone typing the canonical filename with .md gets the rendered page.
/*.md /:splat.html 301

# Legacy SETUP_GUIDE.md is moved to vyrox-design-partners. Redirect the
# old public URL to a friendly explainer page.
/SETUP_GUIDE.html /QUICKSTART.html 308
/setup /QUICKSTART.html 308
63 changes: 63 additions & 0 deletions book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# mdBook configuration for the Vyrox public documentation site.
#
# The canonical source for every chapter is a top-level Markdown file
# in the repo root (README.md, ARCHITECTURE.md, etc). `scripts/build.sh`
# copies them into src/ before invoking `mdbook build`, so editing the
# top-level file is the only place a contributor needs to touch.
#
# Output goes to `book/`. Cloudflare Pages serves the contents of
# `book/` as the static site.

[book]
title = "Vyrox Security"
description = "Engineering documentation for the Vyrox security platform: architecture, API contracts, threat model, audit-log spec, EDR adapter guide."
authors = ["Vyrox Security"]
language = "en"
src = "src"

[build]
build-dir = "book"
create-missing = false

[output.html]
# Use the brand colour for the in-page accent and the website meta tags.
# Light theme is the daylight reading mode (bone palette). Dark theme
# is the void palette. Both are styled by theme/css/variables.css.
default-theme = "light"
preferred-dark-theme = "navy"

# Smarter punctuation handling. mdBook would otherwise turn the "--"
# sequences that appear in CLI examples into en-dashes, which breaks
# copy-paste. Leaving curly-quotes on for prose readability.
smart-punctuation = false

additional-css = ["theme/css/variables.css", "theme/css/typography.css"]
additional-js = []

# Edit-this-page link on every chapter. Points at the top-level file
# the chapter mirrors, so an external contributor who clicks "edit"
# lands on the canonical source.
git-repository-url = "https://github.com/vyrox-security/vyrox-docs"
git-repository-icon = "fab-github"
edit-url-template = "https://github.com/vyrox-security/vyrox-docs/edit/main/{path}"

# Site-wide footer text. Single line because mdBook expects it.
[output.html.print]
enable = true

[output.html.search]
enable = true
limit-results = 30
teaser-word-count = 30
use-boolean-and = true
boost-title = 2
boost-hierarchy = 1
boost-paragraph = 1
expand = true
heading-split-level = 3
copy-js = true

# Custom hook into the document head: pulls in the three Google Fonts
# (Fraunces, Geist, JetBrains Mono) and adds the favicon.
[preprocessor.links]
[preprocessor.index]
Loading
Loading