Compare commits

...

25 Commits

Author SHA1 Message Date
wmantly 40a1e7f64e fix(setup): auto-restore bao-init.json from backups if missing from config/ v1.35.7
Lint / Shellcheck setup.sh (push) Failing after 10s
Lint / Syntax check bootstrap.js (push) Successful in 14s
2026-08-03 15:42:01 -04:00
wmantly 45715b61ea Merge pull request #149 from theta42/fix/env-get-function-order-v1.35.6
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 17s
fix(setup): move env_get helper function definition to top of setup.sh v1.35.6
2026-08-03 15:39:39 -04:00
wmantly 54ebb83bb1 fix(setup): move env_get helper function definition to top of setup.sh v1.35.6
Lint / Shellcheck setup.sh (push) Failing after 10s
Lint / Syntax check bootstrap.js (push) Successful in 14s
2026-08-03 15:39:05 -04:00
wmantly a67d972217 Merge pull request #148 from theta42/fix/setup-openbao-unseal-fallback-v1.35.5
CI/CD / build-theta-agent (push) Successful in 42s
CI/CD / docker-push (push) Failing after 18s
fix(setup): fallback to .env VAULT_UNSEAL_KEY and VAULT_TOKEN if bao-init.json is missing v1.35.5
2026-08-03 15:36:46 -04:00
wmantly 875ea874b4 fix(setup): fallback to .env VAULT_UNSEAL_KEY and VAULT_TOKEN if bao-init.json is missing v1.35.5
Lint / Shellcheck setup.sh (push) Failing after 8s
Lint / Syntax check bootstrap.js (push) Successful in 12s
2026-08-03 15:36:22 -04:00
wmantly 119f21b821 Merge pull request #147 from theta42/bump/sso-v1.20.2-proxy-v1.32.0
CI/CD / build-theta-agent (push) Successful in 42s
CI/CD / docker-push (push) Failing after 18s
bump(deps): update sso-manager-node to v1.20.2 and proxy to v1.32.0
2026-08-03 15:31:29 -04:00
wmantly 80275c42e4 bump(deps): update sso-manager-node to v1.20.2 and proxy to v1.32.0
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 13s
2026-08-03 15:30:56 -04:00
wmantly a30deae866 Merge pull request #146 from theta42/bump/theta-agent-v1.2.1
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 17s
bump(theta-agent): update to v1.2.1 for automatic SSSD installation
2026-08-03 15:02:56 -04:00
wmantly dc9a7ff9c4 bump(theta-agent): update to v1.2.1 for automatic SSSD installation
Lint / Shellcheck setup.sh (push) Failing after 8s
Lint / Syntax check bootstrap.js (push) Successful in 13s
2026-08-03 15:02:14 -04:00
wmantly 7937d6cf92 Merge pull request #145 from theta42/fix/setup-unbound-var-v1.35.2
CI/CD / build-theta-agent (push) Successful in 45s
CI/CD / docker-push (push) Failing after 18s
fix(setup): export CFG_CREATE_ALL_HTTP default and add fail-safe parameter expansion v1.35.2
2026-08-03 14:59:07 -04:00
wmantly 21333de814 fix(setup): export CFG_CREATE_ALL_HTTP default and add fail-safe parameter expansion v1.35.2
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 12s
2026-08-03 14:58:39 -04:00
wmantly b3bdebe1c9 Merge pull request #144 from theta42/release/v1.35.1
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 16s
release(theta-suite): v1.35.1
2026-08-03 14:02:55 -04:00
wmantly e6b318e28e release(theta-suite): v1.35.1 - Submodule updates, Directory, Conf layout & Jump host target filter
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 14s
2026-08-03 14:02:13 -04:00
wmantly 4d0b7f555e Merge pull request #143 from theta42/feature/v1.35.0-final-roll-up
CI/CD / build-theta-agent (push) Successful in 45s
CI/CD / docker-push (push) Failing after 18s
release: v1.35.0 final roll-up
2026-08-03 02:42:24 -04:00
wmantly 67b511f8d7 release: v1.35.0 - final roll up (sso v1.20.0, proxy v1.14.3, jump-host v1.17.1, theta-agent v1.2.0) 2026-08-03 02:41:57 -04:00
wmantly b8a8be9697 Merge pull request #142 from theta42/feature/v1.35.0-theta-suite-stack-update
release: v1.35.0 theta-suite stack roll-up
2026-08-03 02:22:39 -04:00
wmantly cd9c81cd92 release: v1.35.0 - roll up submodules (sso v1.20.0, proxy v1.14.3, jump-host v1.17.1, theta-agent v1.2.0) and setup fixes 2026-08-03 02:22:10 -04:00
wmantly c8c04440db Merge pull request #141 from theta42/release/v1.35.0-update
Release v1.35.0 - Bump sso-manager-node to v1.19.6
2026-08-02 23:03:49 -04:00
wmantly d53bdefc2a chore: Bump sso-manager-node to v1.19.6
Lint / Shellcheck setup.sh (push) Failing after 7s
Lint / Syntax check bootstrap.js (push) Successful in 14s
### Changed
- sso-manager-node: v1.18.0-26-gef2207e → v1.19.6 (4945dec)

### sso-manager-node v1.19.6 highlights
- Fixed navbar auth (Catalog/Vault now require login)
- Added docs/directory.md
- SMTP moved to UI-only configuration
- Added test email/SMS API endpoints
- Added non-interactive theta-agent config variables

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-02 22:55:30 -04:00
wmantly 542e5fd33f chore: Release v1.35.0 - Non-interactive theta-agent config
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 12s
### Added
- Non-interactive theta-agent configuration via setup.env variables

### Changed
- setup.sh: Made theta-agent setup fully non-interactive

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-02 22:34:45 -04:00
wmantly 848f35fc5e chore: Add theta-agent configuration variables to setup.env
### Changed
- **setup.sh**: Made theta-agent installation and configuration non-interactive,
  controlled by CFG_THETA_AGENT_* environment variables.
- **setup.env.example**: Added documentation for:
  - CFG_THETA_AGENT_ENABLE (default: 1)
  - CFG_THETA_AGENT_LDAP_AUTH (default: 1)
  - CFG_THETA_AGENT_FULL_CONTROL (default: 1)

All options default to enabled for backwards compatibility.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-02 22:23:29 -04:00
wmantly 1d14fcee19 feat: install theta-agent on host and add CFG_CREATE_ALL_HTTP option (#139)
CI/CD / build-theta-agent (push) Successful in 39s
CI/CD / docker-push (push) Failing after 15s
* feat: install theta-agent on host and add CFG_CREATE_ALL_HTTP option

* docs: update changelog for 1.34.5
2026-08-02 20:04:44 -04:00
wmantly 30609de3e8 chore: release v1.34.4 (update sso-manager-node submodule for vault fix) (#138)
CI/CD / build-theta-agent (push) Successful in 41s
CI/CD / docker-push (push) Failing after 16s
2026-08-02 19:48:54 -04:00
wmantly 925ac027a6 Merge pull request #137 from theta42/release-v1.34.3
CI/CD / build-theta-agent (push) Successful in 41s
CI/CD / docker-push (push) Failing after 16s
chore: release v1.34.3
2026-08-02 19:09:51 -04:00
wmantly 3b769cf24a chore: release v1.34.3 (updates submodules, docs, bootstrap)
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 13s
2026-08-02 19:08:14 -04:00
10 changed files with 233 additions and 36 deletions
+33
View File
@@ -8,6 +8,30 @@ orchestration code; see each submodule's own `CHANGELOG.md`
[sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md))
for what changed inside the apps it composes.
## [v1.35.2] - 2026-08-03
### Fixed
- **Unbound `CFG_CREATE_ALL_HTTP` variable in `setup.sh`** — Fixed unbound variable error during host registration in `setup.sh` when `ensure_secrets_files()` is skipped on pre-configured installations.
## [v1.35.1] - 2026-08-03
### Fixed
- **Directory & Configuration UI enhancements** — Live Cytoscape graph update on parent/child edge modifications, improved discovery reconciler host matching, updated configuration sidebar layout, relocated discovery and messaging plugins to Directory and Configuration pages.
- **Managed Host Target Filter** — Filter SSH connection targets in Jump Host to managed hosts only.
## [v1.35.0] - 2026-08-02
### Added
- **Non-interactive theta-agent configuration** — Added three `setup.env` variables
to control theta-agent installation and configuration without interactive prompts:
- `CFG_THETA_AGENT_ENABLE` (default: 1) — Enable theta-agent installation
- `CFG_THETA_AGENT_LDAP_AUTH` (default: 1) — Configure LDAP authentication via ldap-client
- `CFG_THETA_AGENT_FULL_CONTROL` (default: 1) — Enable all agent capabilities
### Changed
- **`setup.sh`**: Made theta-agent setup fully non-interactive, driven by `setup.env`
variables. Defaults preserve existing behavior (all features enabled).
## [v1.34.0] - 2026-08-02
### Added
@@ -1546,3 +1570,12 @@ First tagged release. Establishes the `vX.Y.Z` tag convention going forward.
[1.1.2]: https://github.com/theta42/theta-suite/compare/v1.1.1...v1.1.2
[1.1.1]: https://github.com/theta42/theta-suite/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/theta42/theta-suite/releases/tag/v1.1.0
## [1.34.4] - 2026-08-02
### Changed
- Updated `sso-manager-node` submodule to `v1.19.6` to pull in a fix for the Vault API 403 error on the Secrets List.
## [1.34.5] - 2026-08-02
### Added
- Automatically build and install `theta-agent` on the host system as a systemd service during `setup.sh`.
- Added `CFG_CREATE_ALL_HTTP` option to `setup.env` to create all default proxy host entries with `forcessl=false`.
+19
View File
@@ -423,15 +423,21 @@ async function seedDirectory(token, clientId, jumpClientId) {
const host = await ensure('host', HOST_FACTS.name || 'Stack host', hostSlug, site.id, {
subType: 'linux',
ip: HOST_FACTS.ip,
address: HOST_FACTS.ip,
macAddress: HOST_FACTS.mac,
os: HOST_FACTS.os,
kernel: HOST_FACTS.kernel,
sshPort: 22,
managed: true,
}, ['stack-host']);
await ensure('service', 'SSO Manager', 'sso-manager', host.id, {
address: `https://${SSO_HOST}`,
port: 3001,
gitRepo: 'https://github.com/theta42/sso-manager-node',
subType: 'web',
icon: 'mdi:shield-account',
tagline: 'Home-lab identity and access management.',
requestable: false,
});
// Proxy = the node management UI; OpenResty = the data plane every hostname
// in the stack actually flows through (80/443). Two faces, two entries.
@@ -440,6 +446,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
port: 3000,
gitRepo: 'https://github.com/theta42/proxy',
subType: 'web',
icon: 'mdi:server-network',
tagline: 'Reverse proxy and API gateway.',
requestable: false,
});
// OpenLDAP is independently consumed — Linux hosts authenticate against it
// (PAM/SSSD, sudoRole, sshPublicKey) and LDAP-native apps bind directly
@@ -451,8 +460,12 @@ async function seedDirectory(token, clientId, jumpClientId) {
address: `ldaps://${LDAPS_HOST}:636`,
port: 389,
externalPort: 636,
portMappings: [{ proto: 'tcp', external: 636, internal: 389, comment: 'LDAPS' }],
gitRepo: 'https://github.com/theta42/sso-manager-node',
subType: 'openldap',
icon: 'mdi:book-open-outline',
tagline: 'LDAP directory for identity.',
requestable: false,
});
// Wildcard address: OpenResty fronts every host under the domain (same
// */** wildcard convention the proxy's Host records use). Its config lives
@@ -462,6 +475,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
port: 443,
gitRepo: 'https://github.com/theta42/proxy',
subType: 'openresty',
icon: 'mdi:router-network',
tagline: 'Data plane.',
requestable: false,
});
// SSH jump host service (core component — always registered).
@@ -473,6 +489,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
port: 3002,
gitRepo: 'https://github.com/theta42/jump-host',
subType: 'ssh',
icon: 'mdi:ssh',
tagline: 'Secure SSH jump host.',
requestable: false,
});
}
+7
View File
@@ -140,6 +140,13 @@ then converges the stack to your `./config/` values (LDAP service account + admi
passwords are reset to the config; the OAuth client is kept if `proxy-secrets.js`
already holds its creds).
> **Troubleshooting: "A newer version is available" after running setup.sh?**
> If the UI shows this warning immediately after you ran `./setup.sh`, the latest
> GitHub release tag might not yet be merged into the default tracking branch for
> the submodules, or Docker may have cached the `COPY` step if the `package.json`
> didn't change. You can force a clean rebuild by running
> `docker compose build --no-cache` and then re-running `./setup.sh`.
---
## Direct LDAP for LDAP-native clients and Linux hosts
+1 -1
Submodule proxy updated: 25419382bd...eb08b6b5b9
+21 -8
View File
@@ -73,13 +73,6 @@ CFG_DOMAIN=example.com
# 'sso-manager' so clients don't need a public 636 port forward. See docs.
#CFG_LDAPS_HOST=
# Optional SMTP (outbound email from the SSO app). Leave blank to disable:
#CFG_SMTP_HOST=smtp.example.com
#CFG_SMTP_PORT=587
#CFG_SMTP_USER=noreply@example.com
#CFG_SMTP_PASS=your-smtp-password
#CFG_SMTP_FROM=SSO Manager <noreply@example.com>
# ── DO NOT put secrets here ──────────────────────────────────────────────────
# The LDAP admin password, JWT secret, admin password, LDAP service-account
# password, and the proxy's local admin password are all GENERATED (random)
@@ -90,6 +83,20 @@ CFG_DOMAIN=example.com
# CFG_LDAP_ADMIN_PASS / CFG_JWT_SECRET / CFG_ADMIN_PASS / CFG_SVC_PASS /
# CFG_PROXY_ADMIN_PASS here.
# ── theta-agent Host Integration ─────────────────────────────────────────────
# Configure theta-agent integration with the local host. All options default to
# enabled (1). Set to 0 to disable.
#
# Enable theta-agent installation and configuration on this host.
#CFG_THETA_AGENT_ENABLE=1
#
# Configure LDAP authentication for this host via ldap-client (SSSD/PAM).
#CFG_THETA_AGENT_LDAP_AUTH=1
#
# Allow theta-agent full control of this host (arbitrary_bash, service_control,
# reboot, configure_ldap capabilities).
#CFG_THETA_AGENT_FULL_CONTROL=1
# ── Geo-Location Scaling (N-Way Multi-Master LDAP) ───────────────────────────
# If deploying this stack across multiple physical sites to provide local HA
# for directory services, you can enable N-Way Multi-Master OpenLDAP replication.
@@ -100,4 +107,10 @@ CFG_DOMAIN=example.com
# LDAP_REPLICATION_HOSTS is a space-separated list of the other sites' LDAP URLs.
# Example for Site 1:
#LDAP_SERVER_ID=1
#LDAP_REPLICATION_HOSTS="ldaps://sso.site2.com:636 ldaps://sso.site3.com:636"
#LDAP_REPLICATION_HOSTS="ldaps://sso.site2.com:636 ldaps://sso.site3.com:636"
# ── Proxy HTTP/HTTPS Defaults ────────────────────────────────────────────────
# If you are running the stack behind an external reverse proxy (like Cloudflare
# or another ingress) that handles TLS termination, you may want the internal
# proxy to serve everything over plain HTTP without forcing redirects to HTTPS.
# Set this to 1 to create all default proxy host entries with forcessl=false.
#CFG_CREATE_ALL_HTTP=1
+148 -23
View File
@@ -61,6 +61,7 @@ set -euo pipefail
cd "$(dirname "$0")"
CFG_ADMIN_PASS="${CFG_ADMIN_PASS:-}"
CONFIG_DIR=./config
BACKUP_DIR=./backups
BACKUP_KEEP="${BACKUP_KEEP:-5}"
@@ -105,6 +106,13 @@ env_upsert() {
fi
}
# Read KEY= from ./.env (empty if absent)
env_get() {
local key="$1" file=./.env
[[ -f "$file" ]] || return 0
grep -m1 "^${key}=" "$file" 2>/dev/null | cut -d= -f2- || true
}
# Detect docker compose (v2 plugin `docker compose` or v1 standalone `docker-compose`).
if docker compose version >/dev/null 2>&1; then
COMPOSE=(docker compose)
@@ -177,6 +185,8 @@ fi
# resolved in ensure_config; this is only the hostname override.
[[ -f ./setup.env ]] && parse_kv_file ./setup.env
export CFG_JUMP_HOST
CFG_CREATE_ALL_HTTP="${CFG_CREATE_ALL_HTTP:-0}"
export CFG_CREATE_ALL_HTTP
# ── Optional outbound HTTP(S) proxy for docker build + the running containers ─
# CFG_HTTP_PROXY / CFG_HTTPS_PROXY / CFG_NO_PROXY (from ./setup.env or the
@@ -442,6 +452,7 @@ BAOEOF
CFG_ADMIN_PASS="${CFG_ADMIN_PASS:-}"
CFG_SVC_PASS="${CFG_SVC_PASS:-}"
CFG_PROXY_ADMIN_PASS="${CFG_PROXY_ADMIN_PASS:-}"
CFG_CREATE_ALL_HTTP="${CFG_CREATE_ALL_HTTP:-0}"
# ── One-time migration from .env / proxy.env (existing deployments) ──
# Preserve the operator's existing secrets so the running deployment keeps
@@ -672,7 +683,17 @@ for i in $(seq 1 30); do
sleep 2
done
if ! docker exec openbao bao status -format=json 2>/dev/null | grep -q '"initialized": true' || true; then
# If config/bao-init.json is missing, search backups for a saved copy
if [[ ! -f "$CONFIG_DIR/bao-init.json" ]]; then
latest_backup_init=$(find ./backups -name "bao-init.json" 2>/dev/null | sort -r | head -n1 || true)
if [[ -n "$latest_backup_init" && -f "$latest_backup_init" ]]; then
info "Restoring $CONFIG_DIR/bao-init.json from backup ($latest_backup_init)..."
cp "$latest_backup_init" "$CONFIG_DIR/bao-init.json"
chmod 600 "$CONFIG_DIR/bao-init.json"
fi
fi
if ! docker exec openbao bao status -format=json 2>/dev/null | grep -q '"initialized": true'; then
status_json=$(docker exec openbao bao status -format=json 2>/dev/null || true)
if ! echo "$status_json" | grep -q '"initialized": true'; then
info "Initializing openbao for the first time..."
@@ -684,13 +705,37 @@ fi
status_json=$(docker exec openbao bao status -format=json 2>/dev/null || true)
if echo "$status_json" | grep -q '"sealed": true'; then
info "Unsealing openbao..."
UNSEAL_KEY=$(grep -A1 '"unseal_keys_b64":' "$CONFIG_DIR/bao-init.json" | tail -n1 | cut -d'"' -f2)
docker exec openbao bao operator unseal "$UNSEAL_KEY" >/dev/null
UNSEAL_KEY=""
if [[ -f "$CONFIG_DIR/bao-init.json" ]]; then
UNSEAL_KEY=$(grep -A1 '"unseal_keys_b64":' "$CONFIG_DIR/bao-init.json" 2>/dev/null | tail -n1 | cut -d'"' -f2 || true)
fi
if [[ -z "$UNSEAL_KEY" ]]; then
UNSEAL_KEY="$(env_get VAULT_UNSEAL_KEY)"
fi
if [[ -n "$UNSEAL_KEY" ]]; then
info "Unsealing openbao..."
docker exec openbao bao operator unseal "$UNSEAL_KEY" >/dev/null
else
die "OpenBao is sealed, but no unseal key was found in $CONFIG_DIR/bao-init.json or .env (VAULT_UNSEAL_KEY)."
fi
fi
export VAULT_TOKEN
VAULT_TOKEN=$(grep '"root_token":' "$CONFIG_DIR/bao-init.json" | cut -d'"' -f4)
if [[ -f "$CONFIG_DIR/bao-init.json" ]]; then
VAULT_TOKEN=$(grep '"root_token":' "$CONFIG_DIR/bao-init.json" 2>/dev/null | cut -d'"' -f4 || true)
fi
if [[ -z "$VAULT_TOKEN" ]]; then
VAULT_TOKEN="$(env_get VAULT_TOKEN)"
fi
if [[ -z "$VAULT_TOKEN" ]]; then
die "Could not determine OpenBao VAULT_TOKEN from $CONFIG_DIR/bao-init.json or .env."
fi
if [[ -n "$UNSEAL_KEY" ]]; then
env_upsert VAULT_UNSEAL_KEY "$UNSEAL_KEY"
fi
env_upsert VAULT_TOKEN "$VAULT_TOKEN"
if ! docker exec -e BAO_TOKEN="$VAULT_TOKEN" openbao bao secrets list -format=json 2>/dev/null | grep -q '"secret/":'; then
@@ -720,21 +765,6 @@ ensure_policy() {
docker exec -i -e BAO_TOKEN="$VAULT_TOKEN" openbao bao policy write "$name" - >/dev/null
}
# Read KEY= from ./.env (empty if absent) — reuse a previously minted token
# instead of minting a fresh one on every setup.sh run.
env_get() {
local key="$1" file=./.env
[[ -f "$file" ]] || return 0
# `|| true` is load-bearing: under `set -euo pipefail`, a no-match `grep`
# exits 1 and (pipefail) makes the whole pipeline return 1. Callers do
# `existing="$(env_get ...)"` as a bare assignment — a non-zero return there
# trips `set -e` and silently kills the whole script (this is exactly what
# aborted a fresh install right after "Minting per-app OpenBao tokens": the
# root VAULT_TOKEN env_upsert had already created .env, but the app-token
# keys were absent, so the first env_get returned 1). "Key absent" is the
# normal path here, so always return 0 with empty output.
grep -m1 "^${key}=" "$file" 2>/dev/null | cut -d= -f2- || true
}
# Mint an orphan, renewable token for `policy` and persist it to .env as `key`,
# OR reuse the token already in .env if it is still valid (re-mint on expiry).
@@ -976,7 +1006,7 @@ async function ensureHost(host, ip, targetPort) {
host: host,
ip: ip,
targetPort: targetPort,
forcessl: true,
forcessl: $( [[ "${CFG_CREATE_ALL_HTTP:-0}" == "1" ]] && echo false || echo true ),
targetssl: false,
sso_enabled: false,
created_by: 'setup.sh',
@@ -1033,7 +1063,7 @@ const {Host} = require('/app/models').models;
try { await Host.get($(js_str "$JUMP_HOST")); console.log('SKIP ${JUMP_HOST} (already exists)'); }
catch (e) {
if (e.name !== 'EntryNotFound') throw e;
await Host.create({ host: $(js_str "$JUMP_HOST"), ip: 'jump-host', targetPort: 3002, forcessl: true, targetssl: false, sso_enabled: false, created_by: 'setup.sh' });
await Host.create({ host: $(js_str "$JUMP_HOST"), ip: 'jump-host', targetPort: 3002, forcessl: $( [[ "${CFG_CREATE_ALL_HTTP:-0}" == "1" ]] && echo false || echo true ), targetssl: false, sso_enabled: false, created_by: 'setup.sh' });
console.log('CREATED ${JUMP_HOST} -> jump-host:3002');
}
process.exit(0);
@@ -1043,9 +1073,104 @@ NODEEOF
)
echo "$JUMP_HOSTS_OUT" | sed 's/^/[setup] /'
# ── 7c. Install theta-agent on the host ──────────────────────────────────────
# Controlled by CFG_THETA_AGENT_ENABLE (default: 1 = enabled)
CFG_THETA_AGENT_ENABLE="${CFG_THETA_AGENT_ENABLE:-1}"
if [[ "$CFG_THETA_AGENT_ENABLE" == "1" ]]; then
info "Setting up theta-agent on the host..."
(
cd theta-agent || exit 0
if ! command -v go >/dev/null 2>&1; then
warn "Go is not installed. Skipping theta-agent installation."
else
info " Building theta-agent..."
go build -o theta-agent main.go websocket.go config.go || warn " Failed to build theta-agent."
if [[ -x "theta-agent" ]]; then
sudo mkdir -p /etc/theta
if [[ ! -f /etc/theta/agent.yml ]]; then
sudo cp agent.yml.example /etc/theta/agent.yml
AGENT_TOKEN="$(rand_hex 16)"
sudo sed -i "s/REPLACE_WITH_AGENT_TOKEN/$AGENT_TOKEN/" /etc/theta/agent.yml
# We want to connect to either https or http depending on CFG_CREATE_ALL_HTTP
if [[ "${CFG_CREATE_ALL_HTTP:-0}" == "1" ]]; then
sudo sed -i "s|https://sso.example.com|http://${SSO_HOST}|" /etc/theta/agent.yml
else
sudo sed -i "s|https://sso.example.com|https://${SSO_HOST}|" /etc/theta/agent.yml
fi
fi
sudo cp theta-agent /usr/local/bin/theta-agent
sudo chmod +x /usr/local/bin/theta-agent
sudo bash -c "cat <<'EOF' > /etc/systemd/system/theta-agent.service
[Unit]
Description=Theta Agent
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/theta-agent
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF"
sudo systemctl daemon-reload
sudo systemctl enable --now theta-agent.service
info " theta-agent installed and started."
fi
fi
)
else
info "theta-agent installation skipped (CFG_THETA_AGENT_ENABLE=0)."
fi
# ── 7d. Configure theta-agent integration with this host ─────────────────────
# Non-interactive configuration driven by setup.env variables:
# CFG_THETA_AGENT_ENABLE (default: 1) - Install/configure theta-agent
# CFG_THETA_AGENT_LDAP_AUTH (default: 1) - Configure LDAP authentication via ldap-client
# CFG_THETA_AGENT_FULL_CONTROL (default: 1) - Enable all agent capabilities
# Only runs if theta-agent was installed (section 7c) or already exists.
if [[ "$CFG_THETA_AGENT_ENABLE" == "1" ]] && [[ -x /usr/local/bin/theta-agent ]]; then
info "Configuring theta-agent integration with this host..."
# Default to enabled unless explicitly disabled
CFG_THETA_AGENT_LDAP_AUTH="${CFG_THETA_AGENT_LDAP_AUTH:-1}"
CFG_THETA_AGENT_FULL_CONTROL="${CFG_THETA_AGENT_FULL_CONTROL:-1}"
if [[ "$CFG_THETA_AGENT_LDAP_AUTH" == "1" ]]; then
info " Configuring LDAP authentication for this host..."
(
cd ldap-client || exit 0
if [[ -x "index.sh" ]]; then
bash index.sh --non-interactive 2>/dev/null || warn " ldap-client enrollment failed (continuing)..."
fi
)
else
info " LDAP authentication configuration skipped (CFG_THETA_AGENT_LDAP_AUTH=0)."
fi
if [[ "$CFG_THETA_AGENT_FULL_CONTROL" == "1" ]]; then
info " Configuring theta-agent with full host control capabilities..."
if [[ -f /etc/theta/agent.yml ]]; then
sudo sed -i 's/arbitrary_bash: false/arbitrary_bash: true/' /etc/theta/agent.yml
sudo sed -i 's/service_control: .*/service_control: true/' /etc/theta/agent.yml
sudo sed -i 's/reboot: false/reboot: true/' /etc/theta/agent.yml
sudo sed -i 's/configure_ldap: false/configure_ldap: true/' /etc/theta/agent.yml
info " theta-agent full control enabled. Restarting service..."
sudo systemctl restart theta-agent.service
else
warn " /etc/theta/agent.yml not found. Full control not configured."
fi
else
info " theta-agent running with limited capabilities (CFG_THETA_AGENT_FULL_CONTROL=0)."
fi
else
info " theta-agent configuration skipped (agent not installed or CFG_THETA_AGENT_ENABLE=0)."
fi
# ── 8. Summary ───────────────────────────────────────────────────────────────
echo
echo -e "\033[1;34m[setup]\033[0m \033[1;32mDone. Your SSO + proxy stack is up.\033[0m"
printf '\033[1;34m[setup]\033[0m \033[1;32mDone. Your SSO + proxy stack is up.\033[0m\n'
echo
echo " SSO Manager UI: https://${SSO_HOST} (fronted by the proxy under TLS)"
echo " first-run fallback: http://127.0.0.1:${SSO_PORT:-3001}"