Add docs/adr/ with a chronological ADR set reconstructed from the project history (no orchestrator, one storage format, derived-state sync, SQL-over-SSH contract, WireGuard beneath SSH, IaC boundaries, non-root image, runtime data paths, bounded lake scans), an index README, and a template. Distinguish repo-local ADRs from ecosystem-wide ASRs. Expand AGENTS.md with a decision-records section and a runtime/operations guide (service URLs, rebuild workflow, CPU budget knobs). Reference the ADRs from README, CONTRIBUTING, and the affected design docs, and add an open question for T1 partition pruning.
41 lines
1.7 KiB
Markdown
41 lines
1.7 KiB
Markdown
# ADR-0005: WireGuard beneath SSH for the mesh transport
|
|
|
|
## Status
|
|
|
|
Accepted (2026-07-08)
|
|
|
|
## Context
|
|
|
|
Peer bulk sync and SQL-over-SSH ([ADR-0004](ADR-0004-sql-over-ssh-contract.md))
|
|
need an encrypted, authenticated channel across an ad-hoc radio mesh. SSH alone
|
|
would work at the application layer, but it leaves the drones' listening
|
|
surface (sshd, any other service port) exposed on the raw mesh network, and it
|
|
gives no cheap, uniform way to authenticate *the peer* before the application
|
|
handshake.
|
|
|
|
## Options
|
|
|
|
| Option | Pros | Cons |
|
|
| --- | --- | --- |
|
|
| A — SSH only | One daemon, familiar | Service ports exposed on the raw mesh; per-service auth; no network-layer peer identity |
|
|
| B — WireGuard tunnel, SSH inside it | Network-layer peer auth via static keys; only the WG port is exposed; SSH speaks over a private, encrypted subnet | Two layers to provision |
|
|
|
|
## Decision
|
|
|
|
Run **WireGuard as the network layer** and **SSH on top of it**. WireGuard
|
|
authenticates peers by pre-shared static public keys and presents a private
|
|
encrypted subnet; SSH forced commands then carry the SQL and bulk-sync contract
|
|
over that subnet. Keys are issued **per device before deployment** — nothing
|
|
joins the mesh at runtime (design principle 5).
|
|
|
|
## Consequences
|
|
|
|
- The only thing exposed on the raw radio is the WireGuard port; sshd and the
|
|
data services listen only on the WG interface.
|
|
- Peer identity is established once, at the network layer, and reused by every
|
|
application above it.
|
|
- Provisioning must place both WG and SSH keys during host prep — handled by
|
|
`infra/ansible/drone-provision.yml` ([ADR-0006](ADR-0006-iac-boundaries.md)).
|
|
- Rationale and the "why not SSH alone" argument live in
|
|
[`../05-network-security.md`](../05-network-security.md).
|