Merge pull request #206 from theta42/docs-multi-site-website
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Has been skipped

docs(site): publish multi-site + gateway mesh to the docs website
This commit is contained in:
2026-08-10 16:57:09 -07:00
committed by GitHub
5 changed files with 177 additions and 6 deletions
+5 -4
View File
@@ -10,8 +10,9 @@ Theta Suite is your one-line solution to replacing fragmented, hard-to-wire
authentication setups with a unified security stack. It wires together OIDC
authentication, LDAP user directories, automated host enrollment, and
centralized secret management in a single command. It eliminates the manual
configuration friction so you get secure access, auditability, and multi-site
replication running in seconds.
configuration friction so you get secure access, auditability, and
[multi-site](sso/multi-site.html) replication when you need more than one
location.
## Who This Is For
* **Self-Hosters & Homelab Engineers:** Anyone running local bare metal,
@@ -24,8 +25,8 @@ replication running in seconds.
lock-in.
* **DevOps & Systems Operators:** Engineers who value idempotent, single-command
deployments (`./setup.sh`) and need a production-grade baseline supporting
zero-trust proxying, SSH jump-host access control, and multi-site replication
out of the box.
zero-trust proxying, SSH jump-host access control, and
[multi-site](sso/multi-site.html) replication out of the box.
## Screenshots
+1 -1
View File
@@ -84,7 +84,7 @@ Theta Gateway answers both from your directory:
inventory, not a static list
- **Per-user key injection** — no downstream changes, no key distribution
- **Shell, exec, and SFTP** bridging
- **WireGuard mesh routing** — cross-site network access alongside SSH
- **[WireGuard mesh routing](mesh.html)** — cross-site network access alongside SSH
- **Web UI + HTTP API** for auditing and metrics — active sessions, a searchable
audit log, per-user/per-host counters
- **Full audit trail** — who, target, method, result, bytes, duration, and the
+60
View File
@@ -0,0 +1,60 @@
---
layout: default
title: Gateway Mesh
---
# Gateway Mesh
Theta Gateway can mesh with other Theta Gateway instances over real
site-to-site WireGuard tunnels — separate from its [SSH jump
host](connecting.html) role, and separate from the roaming-client/exit-node
WireGuard feature (individual peer configs for laptops/phones). This is
gateway-to-gateway: two sites' networks reaching each other directly.
## Why and when to use this
- **Direct site-to-site networking**, not just SSH. Once two gateways are
meshed, hosts behind each can reach each other over the tunnel using the
mesh addressing scheme below — not limited to jumping through SSH.
- **No manual WireGuard config.** Meshing is a join-token exchange; both
sides come out with a live, working peer entry for each other
automatically.
- **Works without a kernel WireGuard module.** Prefers in-kernel WireGuard,
falls back to the userspace `wireguard-go` implementation automatically —
useful for older kernels, some container/cloud images, or hosts where the
kernel module isn't available.
## How it works
1. On the gateway you want others to join, mint a join token: **Mesh** page
**Mint a Join Token**. It's single-use and expires in 15 minutes.
2. On the new gateway, use **Join a Remote Gateway's Mesh**: paste the other
gateway's URL and the token.
3. Both sides now have a live WireGuard peer for each other. The **Meshed
Gateways** table shows every peer, its assigned mesh subnet, and when it
was last seen.
Each gateway is assigned a **mesh index** (an integer 1254) the first time
it either mints a token or is registered by another gateway. That index
determines its subnet: `172.24.<index>.0/24` for the mesh tunnel itself, plus
`10.<index>.0.0/16` reserved for that site's own local network — 254 sites is
the hard ceiling this addressing scheme supports.
## Requirements
- Both gateways need a reachable endpoint (host:port) for the WireGuard
handshake — typically the same public host the SSH/web ports are already
on, with UDP 51820 reachable.
- `NET_ADMIN` capability (or equivalent) on the container/host running the
gateway, to create the WireGuard interface.
## Not yet connected to directory sync
This mesh is a networking layer on its own. [Theta Directory's multi-site
join](../sso/multi-site.html) (catalog + LDAP replication between a master
and its spokes) does not currently route its traffic over this mesh — the
two features work independently today. Routing directory sync over the mesh,
and using the mesh to reach a spoke site with no inbound access of its own,
are both designed but not yet automated — see the [architecture
spec](https://github.com/theta42/theta-suite/blob/master/docs/MULTI_SITE_SPEC.md)
for current status.
+2 -1
View File
@@ -45,7 +45,8 @@ stack with one command.
- **Direct LDAP binds** — anything that binds LDAP directly (Linux hosts
via PAM/SSSD, Gitea, Emby, …) uses LDAPS/StartTLS against the same
directory.
- **Geo-Location Scaling** — built-in support for N-Way Multi-Master OpenLDAP [replication](replication.html) across physical sites.
- **[Multi-Site](multi-site.html)** — one master site, any number of read-only spokes that join with a single key and stay live-synced, with god_admin-gated promotion if the master goes down for good.
- **Geo-Location Scaling** — built-in support for N-Way Multi-Master OpenLDAP [replication](replication.html) across physical sites (a different, lower-level mechanism — see [Multi-Site](multi-site.html) for how the two compare).
- **[Directory & Inventory](directory.html)** — map sites, hosts, and services as a graph with rich metadata (IP/MAC, OS/kernel, ports, git repos), auto-provisioned access groups, and automatic registration from theta-suite's agents and discovery plugins. Drives directory-aware tools like the [SSH jump host](../jump-host/).
- **Subtype metrics & lifecycle drivers** — telemetry, log streaming, and remote control for resources tagged with a `subType` (`systemd`, `docker`, `proxmox`, `wireguard`, `postgresql`, `redis`, `k8s`, …).
- **OpenBao-backed secrets** — per-resource and per-user secrets with explicit upward inheritance (`Resource → Host → Cluster → Site`).
+109
View File
@@ -0,0 +1,109 @@
---
layout: default
title: Multi-Site (Master/Spoke Join)
---
# Multi-Site (Master/Spoke Join)
If you run more than one physical site, Theta Directory can run one site as
the **master** (single write authority for the shared catalog) and any
number of **spokes** — read-only replicas that stay in sync automatically and
run local authentication with zero WAN dependency.
This is a different, higher-level mechanism than [raw LDAP N-way
replication](replication.html) — see [How this relates to LDAP
replication](#how-this-relates-to-ldap-replication) below if you're deciding
between the two.
## Why and when to use this
- **Zero-touch spoke setup.** One join key, one URL, and a spoke adopts the
whole directory (users, groups, resource catalog) in one step — no manual
`syncrepl` configuration.
- **Single write authority, no split-brain.** Only the master accepts
directory writes. A spoke that loses WAN connectivity keeps working for
local reads/auth and unconditionally stays read-only — it never silently
promotes itself. Changing which site is master always requires an explicit,
authenticated action by a `god_admin`.
- **Stays in sync, not just a one-time copy.** Once joined, a spoke keeps
receiving live updates whenever the master's catalog changes — you don't
re-run the join to pick up new hosts/apps/users.
## How it works
1. **On the master**, an admin mints a **site join key** (Directory → the
Master Site modal → **Site Join Keys** → Mint key). It's shown once,
stored hashed, and revocable.
2. **On the spoke** (must be a fresh install — no users beyond the bootstrap
admin, no enrolled agents), either:
- Paste the master's URL and the join key into the Master Site modal's
**Join an Existing Site** form, or
- Set `CFG_MASTER_DIRECTORY_URL` / `CFG_MASTER_DIRECTORY_JOIN_KEY` in
`setup.env` before the first `./setup.sh` run.
3. The spoke pulls the master's full export (LDAP tree, resource catalog,
agent-signing key) and adopts it, then registers its own reachable URL
with the master so it can receive live updates going forward.
4. From then on, every change to the master's catalog pushes to every
registered spoke automatically. A spoke's own directory-write requests are
rejected with a `403` pointing at the master — writes always go there.
### Promoting a spoke to master
If the master site goes down for good (or you're relocating write
authority), a `god_admin` can promote any spoke from its own Master Site
modal. Promotion is one coordinated action: it demotes the previous master as
part of the same request (best-effort — an unreachable old master never
blocks the promotion, since that's exactly the scenario this exists for), and
every other spoke gets pointed at the new master automatically.
## What replicates
| Data | How |
|---|---|
| LDAP (users, groups) | Full export on join; live push on every master change |
| Resource catalog (hosts, apps, sites) | Same |
| Agent-signing key | Same — every site can validly sign a command for any agent enrolled at *any* site |
The agent-signing key being identical everywhere is a deliberate tradeoff for
small, trusted deployments (a handful of sites, not hundreds) — it means
compromising the least-secured spoke has the same agent-command blast radius
as compromising the master. If that tradeoff doesn't fit your deployment,
don't rely on this mechanism as-is.
Secrets *beyond* the agent-signing key (LDAP admin password, JWT secret, and
so on) are **not** currently synced — each site still generates its own.
## Requirements and current limits
- Both sites need a network path to each other's HTTP(S) API — the master to
pull an export from, the spoke to push replication updates back to. A site
with no inbound path at all (e.g. behind CGNAT) can't join yet on its own;
a relay mechanism for that case is designed but not automated (see the
[architecture spec](https://github.com/theta42/theta-suite/blob/master/docs/MULTI_SITE_SPEC.md)
for the current status).
- Joining only ever happens on a **fresh install**. There's no way to merge
an already-populated directory into a master's — re-provision the host
first.
## How this relates to LDAP replication
[N-way LDAP replication](replication.html) is a *lower-level*, different
mechanism: every site runs a fully independent, fully writable `slapd`, wired
together with raw `syncrepl` environment variables, and there's no concept of
a master or a managed join. It predates this feature and is still there for
deployments that specifically want every site independently writable.
Multi-site join (this page) is the opposite design: one write authority, a
managed onboarding flow, and automatic ongoing sync — closer to what most
"add a second office" or "add a home-lab spoke" setups actually want. **Don't
combine the two** — pick one per deployment.
## See also
- Full architecture and current implementation status:
[`MULTI_SITE_SPEC.md`](https://github.com/theta42/theta-suite/blob/master/docs/MULTI_SITE_SPEC.md)
in the `theta-suite` repo.
- Endpoint-level detail: [`docs/site-join.md`](https://github.com/theta42/theta-directory/blob/master/docs/site-join.md)
in the `theta-directory` repo.
- Site-to-site networking (WireGuard mesh between gateways, independent of
directory sync): [Theta Gateway → Mesh](../jump-host/mesh.html).