Compare commits

..

10 Commits

Author SHA1 Message Date
wmantly b799d59672 chore: bump submodules to sso-manager-node v1.31.0 and theta-agent v1.6.0
CI/CD / build-theta-agent (push) Successful in 42s
CI/CD / docker-push (push) Failing after 12s
2026-08-07 23:43:08 -04:00
wmantly f46ef31ca9 Merge pull request #175 from theta42/release/v1.46.0
chore: release v1.46.0
2026-08-07 23:29:38 -04:00
wmantly 8451d3f12d feat: release v1.46.0 theta-suite with Zero-View secrets engine, theta-agent get-secret CLI, and LDAP tunnel
CI/CD / docker-push (push) Failing after 16s
CI/CD / build-theta-agent (push) Successful in 45s
2026-08-07 23:27:00 -04:00
wmantly 67e7e4eb34 Fix --seed-node-secret path/stdin bugs; docs title casing
seed_node_conf() (added for sso-manager-node's node-scoped secrets
engine, DESIGN.md §5) had two bugs that made it fail on every call:

- Path had an extra "data/" segment (secret/data/nodes/<id>/<name>).
  bao kv put takes the mount-relative path and inserts "data/" itself
  for KV v2 -- same convention seed_app_conf already uses just above it
  (secret/${vault_path}, not secret/data/${vault_path}). Fixed to
  secret/nodes/<id>/<name>, which resolves under the hood to the
  secret/data/nodes/<id>/* path api_agent_ops.js's node-scope check
  expects.
- It piped "key=value\n" lines to `bao kv put path -`, but `-` there
  means "read a JSON object from stdin", not KV lines -- failed with
  "invalid key/value pair \"-\"" before ever reaching OpenBao. Fixed to
  pass key=value pairs as ordinary CLI args.

Verified against a real OpenBao round-trip (write via the fixed
function, read back both via the CLI and the same HTTP path the SSO's
node-scope check uses).

docs/_config.yml: "theta-suite" -> "Theta Suite" in the Jekyll site title.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 17:20:01 -04:00
wmantly 403e1a3cd4 Merge pull request #174 from theta42/docs/index-page-update
Update docs home page copy
2026-08-07 00:10:34 -04:00
wmantly 28fad8a49e Update docs home page copy
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:09:42 -04:00
wmantly 70fc19e37f Merge pull request #173 from theta42/docs/readme-update
Update README intro and repo layout diagram
2026-08-06 23:58:15 -04:00
wmantly 5bb2c19fec Update README intro and repo layout diagram
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:54:02 -04:00
wmantly ff9b62d331 Merge pull request #172 from theta42/chore/add-site-analytics
Add site analytics tracking script
2026-08-06 23:48:05 -04:00
wmantly fabb250887 Add site analytics tracking script to docs layout
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:45:37 -04:00
9 changed files with 152 additions and 99 deletions
+11
View File
@@ -8,6 +8,17 @@ orchestration code; see each submodule's own `CHANGELOG.md`
[sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md)) [sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md))
for what changed inside the apps it composes. for what changed inside the apps it composes.
## [v1.46.0] - 2026-08-07
Rolls up **theta-agent v1.6.0**, **sso-manager-node v1.31.0**, **jump-host v1.19.1**.
### Added
- **On-demand CLI Secret Fetching.** `theta-agent get-secret <key>` and `theta-agent get-secrets [--env|--json]` for dynamic secret resolution without plaintext files on disk.
- **Resource Secrets Engine & Zero-View Security.** OpenBao KV-v2 encrypted secrets for directory resources with strict regex validation (`^[A-Za-z0-9_]+$`), password generator, and multi-level hierarchy secret inheritance.
- **OpenBao `sso-broker` Policy.** Granted `secret/data/resources/*` and `secret/metadata/resources/*` permissions to `sso-broker`.
- **Zero-Trust LDAP WebSocket Tunnel.** Auto-starts local `/run/theta/ldap.sock` and `127.0.0.1:3890` loopback listeners on managed nodes.
- **Agent Self-Update & Service Control.** Added `theta-agent update` and `theta-agent reinitialize` CLI commands with automated service restarts (`sssd`, `sshd`).
## [v1.45.0] - 2026-08-06 ## [v1.45.0] - 2026-08-06
Rolls up **sso-manager-node v1.30.2**, **proxy v1.35.1**, **jump-host v1.19.1**. Rolls up **sso-manager-node v1.30.2**, **proxy v1.35.1**, **jump-host v1.19.1**.
+29 -29
View File
@@ -1,8 +1,11 @@
# theta-suite # Theta Suite
The whole theta42 identity + access stack in one repo, brought up with a single
command — for home labs and small businesses.
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.
It composes four applications around a shared [OpenBao](https://openbao.org/) It composes four applications around a shared [OpenBao](https://openbao.org/)
secrets store, brought up with one command: secrets store, brought up with one command:
@@ -20,7 +23,7 @@ secrets store, brought up with one command:
All four load their secrets from OpenBao at boot; `setup.sh` automates the All four load their secrets from OpenBao at boot; `setup.sh` automates the
first-run glue so they find each other and the secrets store. first-run glue so they find each other and the secrets store.
**Documentation:** [https://theta42.github.io/theta-suite/](https://theta42.github.io/theta-suite/) **Site:** [https://theta42.github.io/theta-suite/](https://theta42.github.io/theta-suite/)
## Screenshots ## Screenshots
@@ -37,37 +40,31 @@ The SSO Manager and the proxy it fronts, both stood up by one `./setup.sh` run:
- Registers the proxy as an OIDC client of the SSO. - Registers the proxy as an OIDC client of the SSO.
- Persists submodule commit hashes in `.env` for reproducibility (e.g., `SSO_GIT_COMMIT`, `PROXY_GIT_COMMIT`). This ensures future `docker compose` runs use the same submodule versions. - Persists submodule commit hashes in `.env` for reproducibility (e.g., `SSO_GIT_COMMIT`, `PROXY_GIT_COMMIT`). This ensures future `docker compose` runs use the same submodule versions.
**Why use this instead of running the two separately?** The two only become useful once the proxy is registered as an OIDC client of the SSO and pointed at the SSO's LDAP directory — and the SSO's domain has to match across half a dozen config fields or logins silently fail with `Invalid Credentials`. Doing that by hand is fiddly and easy to get wrong. `setup.sh` handles this automatically and snapshots state before every rebuild — so you get a working SSO + proxy stack in one command and a safe way to upgrade it.
## Unified Release Status
-**Phase 1 (oidc-client)**: Complete.
-**Phases 2-5**: Pending (see [roadmap](#)).
``` ```
┌──────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────
│ browser / OIDC apps │ SSH clients │ Linux hosts │ browser / OIDC apps │ SSH clients │ Linux hosts │
│ │ │ (PAM/SSSD, sudo, keys) │ │ │ (PAM/SSSD, sudo, keys)│
└───────┬────────────┴────────────┴──────────────────────┘ └───────┬────────────┴────────────┴──────────────────────┘
https (:443) ssh (:2222) ldaps (:636) https (:443) ssh (:2222) ldaps (:636)
│ │ │ │ │ │
┌────────▼────────┐ ┌──────────▼────────┐ ┌────────▼────────┐ ┌────────▼──────────┐ │
│ proxy │ │ jump-host │ │ proxy │ │ jump-host │ │
│ OpenResty │ │ sshd :2222 │ │ OpenResty │ │ sshd :2222 │ │
│ :80/:443/:4443 │ │ web UI :3002 │ │ :80/:443/:4443 │ │ web UI :3002 │ │
│ mgmt app :3000 │ └────────┬──────────┘ │ mgmt app :3000 │ └────────┬──────────┘ │
└────────┬─────────┘ │ OIDC + LDAP └────────┬─────────┘ │ OIDC + LDAP │
│ http:3001 (internal)│ via sso-manager │ http:3001 (internal)│ via sso-manager │
▼ ▼ ▼ ▼ ▼
┌───────────────────────────────────────────────────────┐ ┌───────────────────────────────────────────────────────┐
│ sso-manager (Express + OpenLDAP + Redis) │ sso-manager (Express + OpenLDAP + Redis) │
│ OIDC provider + LDAP directory │ OIDC provider + LDAP directory │
│ web UI :3001 (internal) ldaps :636 (published) │ web UI :3001 (internal) ldaps :636 (published) │
└───────────────────────────────────────────────────────┘ └───────────────────────────────────────────────────────┘
▲ loads secrets at boot (scoped token each) ▲ loads secrets at boot (scoped token each)
┌───────────┴───────────────────┐ ┌───────────┴───────────────────┐
│ openbao (KV-v2 at secret/) │ ← central secrets store │ openbao (KV-v2 at secret/) │ ← central secrets store
│ :8200 (internal) │ per-user + per-app KV │ :8200 (internal) │ per-user + per-app KV
│ :8080 (operator UI/API) │ │ :8080 (operator UI/API)
└───────────────────────────────┘ └───────────────────────────────┘
``` ```
@@ -154,7 +151,10 @@ Optional extra ports (only if you need them):
### 4. Docker + Docker Compose ### 4. Docker + Docker Compose
You must use the modern Docker Compose v2 plugin (`docker compose`). The older v1 standalone (`docker-compose`) is not compatible with the BuildKit images generated by this suite and will fail with a `ContainerConfig` KeyError during deployment. You must use the modern Docker Compose v2 plugin (`docker compose`). The older
v1 standalone (`docker-compose`) is not compatible with the BuildKit images
generated by this suite and will fail with a `ContainerConfig` KeyError during
deployment.
--- ---
+6 -18
View File
@@ -642,24 +642,12 @@ async function seedDirectory(token, clientId, jumpClientId) {
requestable: false, requestable: false,
}); });
// OpenBao and its renewer sidecar are part of what the stack deploys, so // Remove legacy OpenBao/bao-renewer seed resources if present — OpenBao is an
// they belong in the directory like every other component. Without entries // internal stack service, not a user-facing published directory service.
// their containers had nowhere to attach and showed up as parentless const openbaoRes = resources.find((r) => r.slug === 'openbao');
// discoveries on a fresh install. const renewerRes = resources.find((r) => r.slug === 'bao-renewer');
await ensure('service', 'OpenBao', 'openbao', host.id, { if (openbaoRes) await dirDelete(token, `resources/${openbaoRes.id}`);
address: 'http://openbao:8200', if (renewerRes) await dirDelete(token, `resources/${renewerRes.id}`);
port: 8200,
subType: 'vault',
icon: 'mdi:safe',
tagline: 'Secrets store for the stack.',
requestable: false,
});
await ensure('service', 'Bao Renewer', 'bao-renewer', host.id, {
subType: 'sidecar',
icon: 'mdi:autorenew',
tagline: 'Renews the stack service tokens against OpenBao.',
requestable: false,
});
// SSH jump host service (core component — always registered). // SSH jump host service (core component — always registered).
let jumpSvc = null; let jumpSvc = null;
+1 -1
View File
@@ -1,4 +1,4 @@
title: theta-suite title: Theta Suite
description: A unified, one-command SSO Manager + OIDC proxy stack for home labs and small businesses. description: A unified, one-command SSO Manager + OIDC proxy stack for home labs and small businesses.
url: "https://theta42.github.io" url: "https://theta42.github.io"
baseurl: "/theta-suite" baseurl: "/theta-suite"
+2
View File
@@ -11,6 +11,8 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
<link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}"> <link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}">
<script defer src="https://tracking.718it.biz/script.js" data-website-id="a5df0dec-6c54-4c1a-a167-02867a56e2cc"></script>
</head> </head>
<body class="d-flex flex-column min-vh-100"> <body class="d-flex flex-column min-vh-100">
+60 -48
View File
@@ -4,24 +4,28 @@ title: Home
description: A unified, one-command SSO Manager + OIDC proxy stack for home labs and small businesses. Wires together a self-hosted identity provider and a reverse proxy with one setup.sh. description: A unified, one-command SSO Manager + OIDC proxy stack for home labs and small businesses. Wires together a self-hosted identity provider and a reverse proxy with one setup.sh.
--- ---
# theta-suite # Theta suite
The whole theta42 identity, access, and secrets stack in one repo, brought up Theta Suite is your one-line solution to replacing fragmented, hard-to-wire
with a single command — for home labs and small businesses. 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.
It composes four applications around a shared secrets store: ## Who This Is For
[SSO Manager](https://theta42.github.io/sso-manager-node/) (OIDC provider + * **Self-Hosters & Homelab Engineers:** Anyone running local bare metal,
LDAP directory), [Proxy](https://theta42.github.io/proxy/) (an OIDC-protected Proxmox, or private VPS nodes who wants enterprise-grade OIDC, multi-master
reverse proxy that can also look users up directly in LDAP), LDAP, PAM/SSSD host enrollment, and OpenBao secret management without spending
[Jump Host](https://theta42.github.io/jump-host/) (directory-driven SSH access days manually wiring glue code.
through one public entry point), and * **Small-to-Medium Businesses (SMBs):** Infrastructure teams that need a
[ldap-client](https://theta42.github.io/ldap-client/) (enrolls your Linux unified, directory-driven access plane across both web apps and Linux boxes,
hosts into the directory for PAM/SSSD, sudo, and SSH keys). All of them read but want to bypass per-user SaaS taxes (Okta, Azure AD) and cloud vendor
their secrets at boot from [OpenBao](https://openbao.org/), the central secrets lock-in.
store. `setup.sh` automates the fiddly part: registering the proxy as an OIDC * **DevOps & Systems Operators:** Engineers who value idempotent, single-command
client of the SSO, pointing every component at the right LDAP directory and deployments (`./setup.sh`) and need a production-grade baseline supporting
the OpenBao token it needs, and generating hostnames and secrets from one zero-trust proxying, SSH jump-host access control, and multi-site replication
`setup.env`. out of the box.
## Screenshots ## Screenshots
@@ -33,41 +37,49 @@ The SSO Manager and the proxy it fronts, both stood up by one `./setup.sh` run:
*(click either screenshot to view full size)* *(click either screenshot to view full size)*
## Why this over running them separately
The components are designed to integrate — they're only useful together once
the proxy is registered as an OIDC client of the SSO *and* pointed at the
SSO's LDAP directory — and the domain has to match across half a dozen config
fields, or logins silently fail. Doing that by hand is fiddly. `setup.sh`
asks for your domain once, generates both apps' config with it filled in
everywhere, registers the proxy as an OIDC client automatically, and
snapshots state before every rebuild.
## What you get ## What you get
- **SSO Manager**, fronted by the proxy under TLS — manage users, groups, - **Unified SSO Manager**: An OpenID Connect (OIDC) provider and OAuth 2.0
and OAuth clients. authorization server fronted by TLS. Includes a web dashboard for managing
- **Proxy** — add the hosts you want to protect with OIDC login. users, groups, and OAuth apps, plus automated invitation and password reset
- **LDAPS** for direct binds — Linux hosts (PAM/SSSD, sudo, SSH keys) and flows.
LDAP-native apps authenticate against the same directory. - **Identity-Aware Reverse Proxy**: Intercepts HTTP/HTTPS traffic to protect
- **Hierarchical groups & permissions** — every adopted host and app gets its own upstream applications with OIDC login and direct LDAP group authorization,
`admin`/`access`/`capability` groups, generated from the Directory; they double featuring automatic TLS certificate issuance and automated host routing.
as real POSIX groups for sudo/SSH. See - **Embedded LDAPS Directory**: A bundled OpenLDAP core acting as your single
[Group & Permission Model](GROUPS.html). source of truth for POSIX accounts, SSH public keys, and sudo roles. Native
- **ldap-client** — enroll Linux hosts into the directory (PAM/SSSD login, apps, legacy infrastructure, and Linux machines authenticate directly over
sudo, SSH keys); the host inventory shows up in the SSO UI and drives encrypted LDAPS (port 636) or StartTLS.
jump-host routing. - **Hierarchical Directory Group & Permission Model**: Every adopted application
- **SSH Jump Host** — `ssh uid_-_host@jump.<domain>` (WinSCP-friendly) and machine automatically inherits dedicated `admin`, `access`, and
or an interactive picker; access is driven by directory group membership, with `capability` groups generated directly from the LDAP directory. These map
a web UI for audit + metrics. cleanly to real POSIX groups for fine-grained sudo and SSH privilege controls.
- **Central secrets (OpenBao)** — every component loads its secrets from one See [Group & Permission Model](GROUPS.html).
[OpenBao](https://openbao.org/) instance at boot; each user gets personal - **Automated Linux Host Enrollment (ldap-client)**: A lightweight host agent
secret storage, and admins mint scoped tokens for external apps. See that enrolls Linux machines into the central directory. It configures system
PAM/SSSD for login, applies sudo policies, distributes SSH public keys, and
registers host telemetry in the primary inventory dashboard.
- **Directory-Driven SSH Jump Host**: A centralized bastion host that routes
inbound terminal traffic (`ssh uid_-_host@jump.<domain>`) using active
directory group memberships. Supports WinSCP, file transfers, interactive
host pickers, and a dedicated audit interface for tracking user sessions and
connection metrics.
- **Central Secrets Engine (OpenBao integration)**: Bootstraps every component
against an embedded [OpenBao](https://openbao.org/) instance to load tokens
and cryptographic keys at runtime. Provides per-user secret vaults and enables
administrators to mint scoped API tokens for external services. See
[Secrets](secrets.html). [Secrets](secrets.html).
- **Self-service API tokens** in both apps' UIs, for scripting/CI without a - **Self-Service & CI/CD API Tokens**: Granular, personal access token
browser session. management built directly into the web interface, allowing operators to drive
- **Multi-Site Support (Geo-Location Scaling)** — built-in support for N-Way Multi-Master LDAP replication across physical locations. system administration and automation pipelines programmatically without an
- **Multi-target load balancing** — built-in proxy support for round-robin load balancing across multiple application servers. active browser session.
- **Multi-Site Geo-Replication**: Built-in support for N-Way Multi-Master LDAP
replication, allowing directory states to sync across geographically separated
physical hardware or remote data centers for high availability and low-latency
local reads.
- **Multi-Target Load Balancing**: Native reverse-proxy load balancing that
distributes traffic across multiple application backends using customizable
health checks and round-robin strategies.
## Get it ## Get it
+41 -1
View File
@@ -78,10 +78,13 @@ die() { error "$*"; exit 1; }
# (stale policies/tokens causing vault 403s). The Redis vault-token cache is # (stale policies/tokens causing vault 403s). The Redis vault-token cache is
# flushed once sso-manager is back up (see the OpenBao bootstrap section). # flushed once sso-manager is back up (see the OpenBao bootstrap section).
RESET_OPENBAO=0 RESET_OPENBAO=0
SEED_NODE_SECRET=0
SEED_NODE_ARGS=()
for arg in "$@"; do for arg in "$@"; do
case "$arg" in case "$arg" in
--reset-openbao) RESET_OPENBAO=1 ;; --reset-openbao) RESET_OPENBAO=1 ;;
*) warn "unknown argument: $arg (ignored)" ;; --seed-node-secret) SEED_NODE_SECRET=1 ;;
*) if [[ "$SEED_NODE_SECRET" == 1 ]]; then SEED_NODE_ARGS+=("$arg"); else warn "unknown argument: $arg (ignored)"; fi ;;
esac esac
done done
@@ -878,6 +881,29 @@ seed_app_conf() {
|| warn " could not seed secret/${vault_path} (continuing — app will use its file fallback)" || warn " could not seed secret/${vault_path} (continuing — app will use its file fallback)"
} }
# Seed a node-scoped secret for a theta-agent (DESIGN.md §5). Node secrets live
# at secret/data/nodes/<agent-id>/* and are read by the agent (via the SSO's
# /api/v1/agent/secrets) on behalf of 3rd-party apps on the host. Agent ids are
# minted at enrollment, so this is a helper the operator calls per node, not a
# boot-time seed:
# ./setup.sh --seed-node-secret <agent-id> <name> <key>=<value> [<key>=<value>...]
seed_node_conf() {
local agent_id="$1" name="$2"; shift 2
[[ -n "$agent_id" && -n "$name" ]] || die "seed_node_conf: need <agent-id> <name>"
# CLI paths are mount-relative (no "data/" segment -- the CLI inserts that
# itself for KV v2, same as seed_app_conf's "secret/${vault_path}" above).
# The HTTP API path api_agent_ops.js checks against (secret/data/nodes/...)
# is what this resolves to underneath.
local path="secret/nodes/${agent_id}/${name}"
if bao_run kv get "$path" >/dev/null 2>&1; then
info " ${path} already seeded — keeping."
return 0
fi
info "Seeding ${path}..."
docker exec -e BAO_TOKEN="$VAULT_TOKEN" openbao bao kv put "$path" "$@" >/dev/null \
|| die "failed to seed ${path}"
}
info "Configuring OpenBao policies..." info "Configuring OpenBao policies..."
# sso-broker — sso's authority to read/write its own conf, mint per-user and # sso-broker — sso's authority to read/write its own conf, mint per-user and
# per-app tokens (auth/token/create/sso-broker), and create the matching # per-app tokens (auth/token/create/sso-broker), and create the matching
@@ -900,6 +926,13 @@ path "secret/metadata/plugins/*" { capabilities = ["list", "read", "delete"] }
# a key that changes on every boot makes signature verification meaningless. # a key that changes on every boot makes signature verification meaningless.
path "secret/data/agent/*" { capabilities = ["create", "read", "update", "delete", "list"] } path "secret/data/agent/*" { capabilities = ["create", "read", "update", "delete", "list"] }
path "secret/metadata/agent/*" { capabilities = ["list", "read", "delete"] } path "secret/metadata/agent/*" { capabilities = ["list", "read", "delete"] }
# Node-scoped secrets for theta-agent (DESIGN.md §5): each node reads only its
# own secret/data/nodes/<agent-id>/* subtree via the SSO's /api/v1/agent/secrets
# endpoint. The SSO (sso-broker) must be able to read them on the agent's behalf.
path "secret/data/resources/*" { capabilities = ["create", "read", "update", "delete", "list"] }
path "secret/metadata/resources/*" { capabilities = ["list", "read", "delete"] }
path "secret/data/nodes/*" { capabilities = ["create", "read", "update", "delete", "list"] }
path "secret/metadata/nodes/*" { capabilities = ["list", "read", "delete"] }
path "auth/token/create/sso-broker" { capabilities = ["update"] } path "auth/token/create/sso-broker" { capabilities = ["update"] }
path "auth/token/create/sso-app" { capabilities = ["update"] } path "auth/token/create/sso-app" { capabilities = ["update"] }
path "auth/token/renew-accessor" { capabilities = ["update"] } path "auth/token/renew-accessor" { capabilities = ["update"] }
@@ -980,6 +1013,13 @@ info " policies: sso-broker, sso-admin, proxy, jump-host (+ per-user/app cre
info " token roles: sso-broker (user-*/app-*/sso-admin, 24h period), sso-app (app-*, 768h period), theta-svc (service tokens, 768h period)" info " token roles: sso-broker (user-*/app-*/sso-admin, 24h period), sso-app (app-*, 768h period), theta-svc (service tokens, 768h period)"
info " app tokens: SSO_VAULT_TOKEN, PROXY_VAULT_TOKEN, JUMP_VAULT_TOKEN in .env (periodic; renewed by bao-renewer)" info " app tokens: SSO_VAULT_TOKEN, PROXY_VAULT_TOKEN, JUMP_VAULT_TOKEN in .env (periodic; renewed by bao-renewer)"
# --seed-node-secret <agent-id> <name> <key>=<value>... : seed a node-scoped
# secret for a theta-agent (DESIGN.md §5). Runs after OpenBao is configured so
# the sso-broker policy (which grants secret/data/nodes/*) is in place.
if [[ "$SEED_NODE_SECRET" == 1 ]]; then
seed_node_conf "${SEED_NODE_ARGS[@]}"
fi
# bao-renewer: renews the three periodic service tokens every 12h so they never # bao-renewer: renews the three periodic service tokens every 12h so they never
# hit their period boundary while the stack is running. Recreated (not just # hit their period boundary while the stack is running. Recreated (not just
# started) so it always picks up freshly re-minted tokens from .env. # started) so it always picks up freshly re-minted tokens from .env.