Merge pull request #206 from theta42/docs-multi-site-website
docs(site): publish multi-site + gateway mesh to the docs website
This commit is contained in:
+5
-4
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 1–254) 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
@@ -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`).
|
||||
|
||||
@@ -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).
|
||||
Reference in New Issue
Block a user