Compare commits

..

29 Commits

Author SHA1 Message Date
wmantly f9af81983b Merge pull request #154 from theta42/fix/unseal-key-unbound-v1.35.11
CI/CD / build-theta-agent (push) Successful in 45s
CI/CD / docker-push (push) Failing after 16s
fix: UNSEAL_KEY unbound variable in setup.sh (v1.35.11)
2026-08-03 22:45:27 -04:00
wmantly 5ef2493e17 chore: changelog for v1.35.11 2026-08-03 22:44:03 -04:00
wmantly 8535372123 fix: guard UNSEAL_KEY with ${UNSEAL_KEY:-} in setup.sh (v1.35.11)
On a re-run where OpenBao is already unsealed, the unseal block is skipped and
UNSEAL_KEY is never set; line 778 then referenced it under set -u and aborted
with 'UNSEAL_KEY: unbound variable'. Guard with ${UNSEAL_KEY:-} so the
VAULT_UNSEAL_KEY upsert is simply skipped when there's no key this run.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-03 22:43:51 -04:00
wmantly ade9a41aed Merge pull request #153 from theta42/release/v1.35.10-reset-openbao-theta-agent
CI/CD / build-theta-agent (push) Successful in 47s
CI/CD / docker-push (push) Failing after 16s
feat: --reset-openbao + fix theta-agent install; bump sso to v1.21.0 (v1.35.10)
2026-08-03 22:26:35 -04:00
wmantly ce664f5cb9 feat: --reset-openbao + fix theta-agent install; bump sso to v1.21.0 (v1.35.10)
- Add --reset-openbao: full clean OpenBao reset (re-init store, flush the
  Redis vault-token cache) to clear stale policies/tokens causing recurring
  vault 403s.
- Fix theta-agent install: copy the prebuilt theta-agent-linux-amd64 from the
  submodule instead of a broken go build; write config to /etc/theta42/agent.yml
  (the path the agent reads), not /etc/theta/agent.yml.
- Bump sso-manager-node gitlink to v1.21.0 (shared secrets + durable vault 403 fix).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-03 22:24:48 -04:00
wmantly 647f5b846c Merge pull request #152 from theta42/fix/submodule-version-sync-v1.35.9
CI/CD / build-theta-agent (push) Successful in 42s
CI/CD / docker-push (push) Failing after 17s
fix: bump sso & proxy submodules to corrected version tags (v1.35.9)
2026-08-03 21:37:39 -04:00
wmantly fe08c2f8c7 fix: bump sso & proxy submodules to corrected version tags (v1.35.9)
The v1.20.2 / v1.32.0 release tags were created but their package.json
versions lagged (1.20.1 / 1.14.3), so the deployed apps' update-check
banner falsely reported a newer version. Repoint the sso-manager-node and
proxy gitlinks to the corrected commits and release v1.35.9.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-03 21:36:24 -04:00
wmantly 43c58e7ed5 Merge pull request #151 from theta42/fix/auto-reset-unseal-key-loss-v1.35.8
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 17s
fix(setup): auto-reset OpenBao volume and re-initialize if unseal key is lost v1.35.8
2026-08-03 15:44:22 -04:00
wmantly 13d8a979c7 fix(setup): auto-reset OpenBao volume and re-initialize if unseal key is lost v1.35.8
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 13s
2026-08-03 15:43:35 -04:00
wmantly 16cbe46793 Merge pull request #150 from theta42/fix/restore-bao-init-from-backup-v1.35.7
CI/CD / build-theta-agent (push) Successful in 41s
CI/CD / docker-push (push) Failing after 17s
fix(setup): auto-restore bao-init.json from backups if missing from config/ v1.35.7
2026-08-03 15:42:35 -04:00
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
7 changed files with 166 additions and 45 deletions
+30
View File
@@ -8,6 +8,36 @@ 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.11] - 2026-08-04
### Fixed
- **`setup.sh` aborted with `UNSEAL_KEY: unbound variable` on re-runs** — when OpenBao was already unsealed, the unseal block was skipped and `UNSEAL_KEY` was never set, so the later `if [[ -n "$UNSEAL_KEY" ]]` crashed under `set -u`. Guarded with `${UNSEAL_KEY:-}`.
## [v1.35.10] - 2026-08-04
### Added
- **`--reset-openbao`** — full clean OpenBao reset for clearing stale policies/tokens (re-inits the store, flushes the Redis vault-token cache). Use when the vault UI shows a recurring `403 permission denied` on the secrets list.
- **sso v1.21.0** — shared secrets: users publish secrets to `secret/shared/<owner>/<slug>` and grant read access to other users and apps; plus a durable fix for the recurring vault 403 (broker now always reconciles policy content before serving a cached token). Bumped the sso-manager-node submodule gitlink to v1.21.0.
### Fixed
- **theta-agent was never installed** — `setup.sh` tried to `go build` from an incomplete source-file list (omitting `executor.go`/`telemetry.go`), which failed silently and skipped install. It now installs the prebuilt `theta-agent-linux-amd64` binary from the submodule and writes config to `/etc/theta42/agent.yml` (the path the agent actually reads).
## [v1.35.9] - 2026-08-03
### Fixed
- **sso & proxy version strings now match their release tags** — The v1.20.2 / v1.32.0 release tags were created but their `nodejs/package.json` version fields were left behind (1.20.1 / 1.14.3), so the deployed apps' update-check banner falsely reported a newer version. Bumped submodules to the corrected commits so `buildVersion` matches the deployed tag.
## [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
+2
View File
@@ -423,10 +423,12 @@ 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}`,
+1 -1
Submodule proxy updated: 25419382bd...8107755307
+130 -41
View File
@@ -72,6 +72,19 @@ warn() { printf '\033[1;33m[setup]\033[0m %s\n' "$*" >&2; }
error() { printf '\033[1;31m[setup]\033[0m %s\n' "$*" >&2; }
die() { error "$*"; exit 1; }
# ── Flags ──────────────────────────────────────────────────────────────────────
# --reset-openbao: wipe the OpenBao volume + bao-init.json and re-initialize a
# fresh store (no prod data to preserve). Use when OpenBao state is suspect
# (stale policies/tokens causing vault 403s). The Redis vault-token cache is
# flushed once sso-manager is back up (see the OpenBao bootstrap section).
RESET_OPENBAO=0
for arg in "$@"; do
case "$arg" in
--reset-openbao) RESET_OPENBAO=1 ;;
*) warn "unknown argument: $arg (ignored)" ;;
esac
done
# Escape a value for a single-quoted JS string: \ -> \\, ' -> \', then wrap in '...'.
js_str() {
local s="$1"
@@ -106,6 +119,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)
@@ -178,6 +198,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
@@ -662,6 +684,20 @@ backup_before_rebuild() {
backup_before_rebuild
# ── 3b. Setup OpenBao (Vault) ────────────────────────────────────────────────
# Full reset (--reset-openbao): stop/remove openbao, drop the data volume, and
# delete the init/keys file (incl. any backup copy that setup.sh would otherwise
# restore). The normal bootstrap below then initializes a brand-new store, so no
# stale policy content or token survives.
if [[ "$RESET_OPENBAO" == "1" ]]; then
info "── Full OpenBao reset requested (--reset-openbao) ──"
"${COMPOSE[@]}" stop openbao >/dev/null 2>&1 || true
"${COMPOSE[@]}" rm -f openbao >/dev/null 2>&1 || true
docker volume ls -q 2>/dev/null | grep '^openbao' | xargs -r docker volume rm >/dev/null 2>&1 || true
rm -f "$CONFIG_DIR/bao-init.json"
rm -f ./backups/bao-init.json ./backups/*/bao-init.json 2>/dev/null || true
info " openbao volume + bao-init.json cleared; will re-initialize fresh."
fi
info "Starting openbao..."
"${COMPOSE[@]}" run --rm --user root openbao chown -R 100:1000 /vault/data
"${COMPOSE[@]}" up -d openbao
@@ -674,7 +710,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..."
@@ -686,13 +732,54 @@ 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
warn "OpenBao is sealed with an unrecoverable key. Resetting OpenBao volume and re-initializing..."
"${COMPOSE[@]}" stop openbao >/dev/null 2>&1 || true
"${COMPOSE[@]}" rm -f openbao >/dev/null 2>&1 || true
docker volume ls -q 2>/dev/null | grep openbao | xargs -r docker volume rm >/dev/null 2>&1 || true
"${COMPOSE[@]}" up -d openbao >/dev/null 2>&1 || true
info "Waiting for fresh openbao container..."
for i in $(seq 1 30); do
if docker exec openbao bao status >/dev/null 2>&1 || [[ $? -eq 2 ]]; then break; fi
sleep 2
done
info "Initializing fresh openbao..."
docker exec openbao bao operator init -key-shares=1 -key-threshold=1 -format=json > "$CONFIG_DIR/bao-init.json"
chmod 600 "$CONFIG_DIR/bao-init.json"
UNSEAL_KEY=$(grep -A1 '"unseal_keys_b64":' "$CONFIG_DIR/bao-init.json" | tail -n1 | cut -d'"' -f2)
info "Unsealing fresh openbao..."
docker exec openbao bao operator unseal "$UNSEAL_KEY" >/dev/null
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
# UNSEAL_KEY is only set when OpenBao needed unsealing this run; on a re-run of
# an already-unsealed store it is unset, so guard with ${UNSEAL_KEY:-} (set -u).
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
@@ -722,21 +809,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).
@@ -858,6 +930,18 @@ for i in $(seq 1 60); do
sleep 2
done
# After a full OpenBao reset, the Redis-cached per-user/admin vault tokens (in
# the persisted sso-data volume) reference the old, now-wiped store — drop them
# so the broker re-mints fresh tokens against the new instance. Belt-and-
# suspenders: the broker also always reconciles policy content before serving a
# token, but a token minted by the previous OpenBao instance is simply invalid
# there, so a cache flush is required after a reset.
if [[ "$RESET_OPENBAO" == "1" ]]; then
info " clearing cached vault tokens (old OpenBao instance)..."
docker exec sso-manager sh -c "redis-cli EVAL \"for _,k in ipairs(redis.call('keys','vault_token:*')) do redis.call('del',k) end\" 0" \
>/dev/null 2>&1 || warn " could not flush Redis vault-token cache (will re-mint on next access)"
fi
info "Seeding app configs into OpenBao (idempotent)..."
# sso-manager/conf holds the operator-set LDAP/SMTP/jwtSecret values — sso has
# no bootstrap-generated creds, so the file is the complete source of truth.
@@ -978,7 +1062,7 @@ async function ensureHost(host, ip, targetPort) {
host: host,
ip: ip,
targetPort: targetPort,
forcessl: $( [[ "$CFG_CREATE_ALL_HTTP" == "1" ]] && echo false || echo true ),
forcessl: $( [[ "${CFG_CREATE_ALL_HTTP:-0}" == "1" ]] && echo false || echo true ),
targetssl: false,
sso_enabled: false,
created_by: 'setup.sh',
@@ -1035,7 +1119,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: $( [[ "$CFG_CREATE_ALL_HTTP" == "1" ]] && echo false || echo 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);
@@ -1052,25 +1136,30 @@ 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."
# Install the prebuilt binary that ships in the theta-agent submodule (the
# repo's own install.sh uses the same release binary). We do NOT build from
# source here: a previous `go build -o theta-agent main.go websocket.go
# config.go` omitted executor.go/telemetry.go, failed to compile, and was
# silently skipped, so the agent was never installed.
if [[ ! -f "theta-agent-linux-amd64" ]]; then
warn "Prebuilt theta-agent-linux-amd64 missing from the theta-agent submodule. 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
info " Installing prebuilt theta-agent binary..."
if [[ -x "theta-agent-linux-amd64" ]]; then
# The agent binary reads /etc/theta42/agent.yml (theta-agent/main.go).
sudo mkdir -p /etc/theta42
if [[ ! -f /etc/theta42/agent.yml ]]; then
sudo cp agent.yml.example /etc/theta42/agent.yml
AGENT_TOKEN="$(rand_hex 16)"
sudo sed -i "s/REPLACE_WITH_AGENT_TOKEN/$AGENT_TOKEN/" /etc/theta/agent.yml
sudo sed -i "s/REPLACE_WITH_AGENT_TOKEN/$AGENT_TOKEN/" /etc/theta42/agent.yml
# We want to connect to either https or http depending on CFG_CREATE_ALL_HTTP
if [[ "$CFG_CREATE_ALL_HTTP" == "1" ]]; then
sudo sed -i "s|https://sso.example.com|http://${SSO_HOST}|" /etc/theta/agent.yml
if [[ "${CFG_CREATE_ALL_HTTP:-0}" == "1" ]]; then
sudo sed -i "s|https://sso.example.com|http://${SSO_HOST}|" /etc/theta42/agent.yml
else
sudo sed -i "s|https://sso.example.com|https://${SSO_HOST}|" /etc/theta/agent.yml
sudo sed -i "s|https://sso.example.com|https://${SSO_HOST}|" /etc/theta42/agent.yml
fi
fi
sudo cp theta-agent /usr/local/bin/theta-agent
sudo cp theta-agent-linux-amd64 /usr/local/bin/theta-agent
sudo chmod +x /usr/local/bin/theta-agent
sudo bash -c "cat <<'EOF' > /etc/systemd/system/theta-agent.service
@@ -1123,15 +1212,15 @@ if [[ "$CFG_THETA_AGENT_ENABLE" == "1" ]] && [[ -x /usr/local/bin/theta-agent ]]
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: false/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
if [[ -f /etc/theta42/agent.yml ]]; then
sudo sed -i 's/arbitrary_bash: false/arbitrary_bash: true/' /etc/theta42/agent.yml
sudo sed -i 's/service_control: .*/service_control: true/' /etc/theta42/agent.yml
sudo sed -i 's/reboot: false/reboot: true/' /etc/theta42/agent.yml
sudo sed -i 's/configure_ldap: false/configure_ldap: true/' /etc/theta42/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."
warn " /etc/theta42/agent.yml not found. Full control not configured."
fi
else
info " theta-agent running with limited capabilities (CFG_THETA_AGENT_FULL_CONTROL=0)."