From eb10aee93b4d06e2a5c615106f9903e846495bca Mon Sep 17 00:00:00 2001 From: Ilker Manap Date: Sun, 4 Oct 2026 12:12:35 +0200 Subject: [PATCH] Document TLS between the store's machines, and close section A of the backlog Co-Authored-By: Claude Opus 5.5 (1M context) --- BACKLOG.md | 21 +++++++-------------- CHANGELOG.md | 13 +++++++++++++ docs/install.md | 9 +++++++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/BACKLOG.md b/BACKLOG.md index 5b391d2..3453e2b 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -19,20 +19,13 @@ Conventions this codebase keeps, which every item here must keep too: ## A. Security — do first -**Status (2026-10-04, branch `security-a`):** done — A1, A2, A3, A4, A5 -(token on loopback rather than a unix socket), A6 except the item below, A7, -A8, A9. **Left:** -- **A6b** — etcd client/peer TLS with `--client-cert-auth`, and Patroni's - REST API over TLS, for new clusters and as a rolling change for running - ones. Until then the firewall (A9) keeps 2379/2380/8008 to the cluster's - networks and Patroni's API asks for a password. -- From A8: thread ids are bounded and documented as project-wide, but not - scoped per user; Python engines are resolved with an explicit PyTorch - index and a PEP 751 lock, but locks are not shipped per engine version. -- A9 is live on the PoC (140, 149, 150, 148): llmgw's ports answer - 10.0.0.0/24, are dropped from outside it (tested over IPv6), and ssh, - :8080 and other services are untouched. The other nodes get it on their - next `node add`. +**Status (2026-10-04): done and merged.** A1–A9, A6b included — etcd and +Patroni's API on TLS, the PoC moved in maintenance mode without a failover. +Deliberately narrower than written: the admin API is a token on loopback +rather than a unix socket (A5); thread ids are bounded and documented as +project-wide rather than scoped per user (A8); Python engines resolve with an +explicit PyTorch index and a PEP 751 lock rather than locks shipped per engine +version (A8). All of A is live on the PoC. ### A1. Toolchain (S, hours) `govulncheck` finds 11 standard-library vulnerabilities reachable from this diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb471f..2d19c90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -211,6 +211,19 @@ APIs change between minors without a deprecation period. already has are left as they were. Extra networks go in `firewall_networks`; `--no-firewall` skips it; `llmgw doctor` says when a node lacks it. +- **etcd and Patroni's API speak TLS.** etcd's peers and clients use + certificates from the cluster's authority, and a client must present one; + Patroni reaches it with its member's certificate and serves its API over + TLS. `server init --patroni`, run again, moves an existing cluster: with + Patroni in maintenance mode, so PostgreSQL serves on and nothing fails + over, etcd is rebuilt on TLS and Patroni's keys carried into it. The + control plane asks the API over HTTPS, verified, and over HTTP only where a + member has not moved yet. +- **A cluster keeping its access rules per member got no `hostssl`.** The + TLS step looked only at the shared configuration, and on a cluster set up + before the rules moved there said the rules were `hostssl` while + plaintext was still accepted. Each member's own rules are now made + `hostssl` too. ### Fixed diff --git a/docs/install.md b/docs/install.md index 579d947..64aa014 100644 --- a/docs/install.md +++ b/docs/install.md @@ -152,6 +152,15 @@ promoted within about thirty seconds of the primary being lost, and the control plane follows it by itself. `llmgw ctl status` says who leads; see [deploy/ha](../deploy/ha/README.md) for what it sets up. +Everything between the machines is TLS, with certificates from the cluster's +own authority: PostgreSQL (every remote rule is `hostssl`, and the control +plane verifies the member it reaches), etcd (peers and clients, and a client +must present a certificate), and Patroni's API, which also asks for a +password before a change. A cluster set up by an earlier llmgw is moved to +this by running the same command again, on the control plane that holds the +authority: etcd is rebuilt on TLS with Patroni in maintenance mode, so +PostgreSQL serves throughout and no failover happens. + Every step looks before it acts. Running it again finishes an install that stopped halfway and changes nothing on one that did not; it never overwrites `server.yaml`, the authority, or an existing account's password.