ADR-0029: Deployment targets from a single repository¶
- Status: Accepted
- Date: 2026-08-17
- Deciders: El, Lachlan
- Relates to: ADR-0011, ADR-0022, ADR-0024, ADR-0025, ADR-0028
Context¶
This repository holds three things with different release cadences and different runtime requirements: the documentation site, the BOS Console, and the Ansible tree that provisions everything. "Deploy the repo" is not a coherent instruction — each has a different target, and one of them must be independent of the others by design.
Decision¶
1. Documentation → Cloudflare Pages, its own project¶
A single repository can back several Pages projects, each with its own build command, output directory and domain.
| Setting | Value |
|---|---|
| Project | octopodia-abos-docs |
| Production branch | main |
| Build command | pip install mkdocs-material && mkdocs build |
| Output directory | site |
| Domain | docs.octopodia.com.au (ADR-0022) |
| Access | Cloudflare Access, same identity policy as the Console |
Branch pushes produce preview URLs, so a documentation change is reviewable rendered, not only as a diff.
2. The BOS Console → the VPS, deployed by Ansible¶
Not Cloudflare Pages. Pages serves static assets; the Console is an application that reads and writes the registry, and the registry is a container on the host with no public route (ADR-0025 §2). The Console therefore runs in the core stack, behind Caddy at console.octopodia.com.au, deployed by an Ansible run rather than by a git push.
Its frontend could in principle be served statically with the API on the box, but splitting one surface across two hosting models to save a container introduces a seam for no benefit.
3. Ansible → not deployed at all¶
infra/ is executed from a control machine (ADR-0024 §4). It is never pushed to a host and never built.
4. The docs site must not depend on the VPS¶
This is the constraint that makes the first two answers differ, and it is not negotiable: a runbook has to survive the outage it is used in (ADR-0028). Documentation is therefore hosted somewhere with no dependency on the infrastructure it documents. Moving the docs site onto the box "for consistency" would defeat its purpose.
5. Path filters on every deployment trigger¶
Three release cadences in one repository means a change to one must not deploy the others.
- The docs build ignores changes outside
docs/andmkdocs.yml. - Console deployment ignores changes to
docs/andinfra/.
Without this, an Ansible commit triggers a documentation rebuild — burning free-tier build minutes on no-op builds — and a documentation typo can redeploy the Console at an awkward moment.
Consequences¶
Each surface deploys on its own trigger and its own schedule, from one repository with one review path. Documentation stays readable when the host is down, which is when it is needed most. Console releases stay deliberate: an Ansible run, not a side effect of pushing a branch.
The cost is configuration in three places — two Pages/CI projects plus the Ansible tree — and path filters that must be maintained as directories move. A monorepo makes cross-cutting changes easy to review and easy to over-deploy; the filters are what keep that in check.
Alternatives considered¶
- Everything on the VPS, including docs — rejected: the docs site would be unavailable during exactly the incidents its runbooks exist for.
- Console on Cloudflare Pages with the API on the box — rejected: splits one surface across two hosting models and two deployment paths for no gain.
- Separate repositories per surface — rejected: three review paths for changes that frequently cross boundaries (an ADR, its runbook, and the role implementing it are one logical change).
- No path filters — rejected: every commit deploying everything is how an unrelated release goes out during an incident.