boma/docs/decisions/001-architecture.md
sjat 188882449d docs(adr): restructure ADRs 001,002,004,005,012,014,015 to ADR-023 conformance
Add dated Status sections and (where missing) Consequences sections assembled
from each ADR's already-stated implications. No decision substance changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:39:00 +02:00

89 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-001 — Architecture overview
## Status
Accepted (2026-05-30)
## Context
This document describes the overall architecture of the homelab infrastructure
and the boundaries of what this Ansible monorepo manages.
## Infrastructure
- **Hypervisor**: Proxmox cluster (2+ nodes)
- **Guest OS**: Debian 13 (all managed hosts)
- **Scale**: 25 VMs, small fleet — treated as individuals, not cattle
- **Control node**: `ubongo` — a dedicated always-on **physical** x86-64 machine
**outside** the cluster. Ansible runs from here. It cannot be created by the
Terraform it hosts, so it is provisioned manually (see ADR-015 and
`docs/runbooks/new-host.md`).
## What this repo manages
| Layer | Managed by | Notes |
|--------------------|--------------------|--------------------------------------------|
| VM existence | Terraform (`terraform/`) | Clones the cloud-init template; `ubongo` (control node) is a physical box outside the cluster, the one manual exception (see ADR-009/ADR-015) |
| Internal DNS records | Ansible `dns` role | Internal zone rendered from inventory (see ADR-007/009) |
| OS baseline | Ansible `base` role | Users, SSH, firewall, updates, audit |
| Docker runtime | Ansible `docker_host` role | Engine, daemon config, log driver |
| Service deployment | Ansible per-service roles | Compose rendered from templates |
| Secrets | Ansible Vault | Encrypted `vault.yml` files in repo |
The Terraform↔Ansible boundary and handoff are defined in ADR-009. This table
describes the *intended* design — see STATUS.md for what is actually built.
## Host groups
```
all
├── control # ubongo — physical control node outside the cluster; baseline config only, runs no services
├── docker_hosts # VMs running Docker services (most hosts)
├── proxmox_hosts # Proxmox nodes themselves (limited management scope)
└── offsite_hosts # askari (off-site Hetzner) — NetBird coordinator + external watchdog
```
The `control` group holds the single manually-provisioned control node; it is
managed for baseline config (SSH, firewall, updates) but never runs the
`docker_host` role. The `offsite_hosts` group holds `askari`, the off-site Hetzner
host — also manually provisioned (ADR-016), managed for baseline config plus the
`netbird_coordinator` service role. Proxmox nodes are managed only for basic baseline tasks (SSH).
Proxmox configuration itself (storage, clustering, networking)
is out of scope.
## Service interaction model
Services run as Docker containers on one or more `docker_hosts`. Where services
need to interact, they do so via:
- Docker networks (same host)
- Internal DNS / hostname resolution (cross-host)
- Explicitly defined published ports (external access)
All Compose files are rendered by Ansible from Jinja2 templates. No hand-edited
Compose files exist on hosts — they are always regenerated on deploy.
## Decision
This architecture prioritises:
- **Simplicity**: few moving parts, no orchestration layer (no Kubernetes, no Swarm)
- **Reproducibility**: any host can be rebuilt from scratch via Ansible
- **Legibility**: a human reading the repo can understand what runs where
## Consequences
Drawn from the boundaries this ADR already states:
- The small fleet (25 VMs) is treated as individuals, not cattle (per Infrastructure),
and forgoing an orchestration layer is the cost of the simplicity priority (per
Decision).
- The control node `ubongo` cannot be created by the Terraform it hosts, so it is
provisioned manually — the one documented exception to Terraform-owned VM existence
(per Infrastructure / Host groups; ADR-009, ADR-015).
- Management scope is deliberately bounded: Proxmox configuration itself (storage,
clustering, networking) is out of scope, and the `control` group never runs the
`docker_host` role (per Host groups).
- Compose files are always regenerated by Ansible on deploy; no hand-edited Compose
files exist on hosts (per Service interaction model).
- The "What this repo manages" table describes the *intended* design — STATUS.md
records what is actually built (per that section).