# ───────────────────────────────────────────────────────────────────────────── # spoke.env — join this stack to an existing Theta Directory as a read-only # spoke, instead of seeding a fresh master (MULTI_SITE_SPEC.md). # # This is the ONE place the join-a-cluster vars live -- split out of # setup.env.example (which still has every option, including these, for a # single-file bring-up) purely for clarity: standing up a spoke is a distinct # operation from configuring a fresh install, so it gets its own small file # instead of being buried among unrelated options. Set what you need here; # everything else (domain, admin creds, SMTP, ...) still comes from setup.env # as normal -- copy setup.env.example too and fill in CFG_DOMAIN there first. # # Same first-run-only rule as setup.env: read once (layered on top of # setup.env, so a var set in both places takes this file's value), then # ignored once ./config/ exists -- an already-running directory can never be # merged into a master's this way. The one exception is the no-inbound relay # vars at the bottom, which setup.sh re-checks on every run (see their # comment) since mesh peering usually finishes after the first bring-up. # # cp setup.env.example setup.env # if you haven't already -- set CFG_DOMAIN # cp spoke.env.example spoke.env # $EDITOR spoke.env # set CFG_MASTER_DIRECTORY_URL + _JOIN_KEY below # ./setup.sh # # Copying this file to spoke.env (gitignored) keeps your join key out of git. # ───────────────────────────────────────────────────────────────────────────── # The master's URL and a site join key. Mint a key on the master: # Directory -> the Master Site modal -> Site Join Keys -> Mint key. # Both required to join; if either is unset this stack seeds a fresh master # instead (setup.env.example's normal behavior). CFG_MASTER_DIRECTORY_URL=https://sso.master.example.com CFG_MASTER_DIRECTORY_JOIN_KEY=stj_9f2e... # This spoke's own public web domain, if it needs one independent of the # master's (an inbound spoke serving its own traffic directly -- see # CFG_SPOKE_NO_INBOUND below for the opposite case). Optional: CFG_DOMAIN # (in setup.env) is the shared LDAP identity namespace and must be identical # across every site in the cluster -- this only changes where THIS site's own # web hostnames (sso.*, proxy.*) point, never the LDAP base DN. #CFG_PUBLIC_DOMAIN=branch2.example.com # No public IP at all (CGNAT, etc.)? The master can still reach this spoke by # relaying over the gateway-to-gateway WireGuard mesh instead of the open # internet (MULTI_SITE_SPEC.md §5.2) -- but the mesh peering itself is a # manual, out-of-band step on BOTH jump-hosts (mint a mesh join token on the # master's jump-host, paste it into this site's jump-host "Join a mesh" UI # action) that can't run unattended inside this script. Once that's done, set # these two and re-run setup.sh: it discovers this jump-host's assigned mesh # IP and registers it with the master, which then auto-creates the relay # route on its own theta-proxy. Safe to leave set before meshing -- setup.sh # just reports "not meshed yet" and skips until a later re-run finds the IP. #CFG_SPOKE_NO_INBOUND=true #CFG_SPOKE_PUBLIC_HOST=sso-branch2.master-domain.example.com