# ADR-001: Matrix/Conduit Deployment Scaffold | Field | Value | |-------|-------| | **Status** | Accepted | | **Date** | 2026-04-05 | | **Decider** | Ezra (Architekt) | | **Stakeholders** | Allegro, Timmy, Alexander | | **Parent Issues** | #166, #183 | --- ## 1. Context Son of Timmy Commandment 6 requires encrypted human-to-fleet communication that is sovereign and independent of Telegram. Before any code can run, we needed a reproducible, infrastructure-agnostic deployment scaffold that any wizard house can verify, deploy, and restore. ## 2. Decision: Conduit over Synapse **Chosen:** [Conduit](https://conduit.rs) as the Matrix homeserver. **Alternatives considered:** - **Synapse**: Mature, but heavier (Python, more RAM, more complex config). - **Dendrite**: Go-based, lighter than Synapse, but less feature-complete for E2EE. **Rationale:** - Conduit is written in Rust, has a small footprint, and runs comfortably on the Hermes VPS (~7 GB RAM). - Single static binary + SQLite (or Postgres) keeps the Docker image small and backup logic simple. - E2EE support is production-grade enough for a closed fleet. ## 3. Decision: Docker Compose over Bare Metal **Chosen:** Docker Compose stack (`docker-compose.yml`) with explicit volume mounts. **Rationale:** - Reproducibility: any host with Docker can stand the stack up in one command. - Isolation: Conduit, Element Web, and Postgres live in separate containers with explicit network boundaries. - Rollback: `docker compose down && docker compose up -d` is a safe, fast recovery path. - Future portability: the same Compose file can move to a different VPS with only `.env` changes. ## 4. Decision: Caddy as Reverse Proxy (with Nginx coexistence) **Chosen:** Caddy handles TLS termination and `.well-known/matrix` delegation inside the Compose network. **Rationale:** - Caddy automates Let’s Encrypt TLS via on-demand TLS. - On hosts where Nginx already binds 80/443 (e.g., Hermes VPS), Nginx can reverse-proxy to Caddy or Conduit directly. - The scaffold includes both a `caddy/Caddyfile` and Nginx-compatible notes so the operator is not locked into one proxy. ## 5. Decision: One Matrix Account Per Wizard House **Chosen:** Each wizard house (Ezra, Allegro, Bezalel, etc.) gets its own Matrix user ID (`@ezra:domain`, `@allegro:domain`). **Rationale:** - Preserves sovereignty: each house has its own credentials, device keys, and E2EE trust chain. - Matches the existing wizard-house mental model (independent agents, shared rooms). - Simplifies debugging: message provenance is unambiguous. ## 6. Decision: `matrix-nio` for Hermes Gateway Integration **Chosen:** [`matrix-nio`](https://github.com/poljar/matrix-nio) with the `e2e` extra. **Rationale:** - Already integrated into the Hermes gateway (`gateway/platforms/matrix.py`). - Asyncio-native, matching the Hermes gateway architecture. - Supports E2EE, media uploads, threads, and replies. ## 7. Consequences ### Positive - The scaffold is **self-enforcing**: `validate-scaffold.py` and Gitea Actions CI guard integrity. - Local integration can be verified without public DNS via `docker-compose.test.yml`. - The path from "host decision" to "fleet online" is fully scripted. ### Negative / Accepted Trade-offs - Conduit is younger than Synapse; edge-case federation bugs are possible. Mitigation: the fleet will run on a single homeserver initially. - SQLite is the default Conduit backend. For >100 users, Postgres is recommended. The Compose file includes an optional Postgres service. ## 8. References - `infra/matrix/CANONICAL_INDEX.md` — canonical artifact map - `infra/matrix/scripts/validate-scaffold.py` — automated integrity checks - `.gitea/workflows/validate-matrix-scaffold.yml` — CI enforcement - `infra/matrix/HERMES_INTEGRATION_VERIFICATION.md` — adapter-to-scaffold mapping