Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d0b7f555e | |||
| 67b511f8d7 | |||
| b8a8be9697 | |||
| cd9c81cd92 | |||
| c8c04440db | |||
| d53bdefc2a | |||
| 542e5fd33f | |||
| 848f35fc5e | |||
| 1d14fcee19 | |||
| 30609de3e8 | |||
| 925ac027a6 | |||
| 3b769cf24a | |||
| 2785b861b3 | |||
| c216ddd4e8 | |||
| 9c3cbb0ec2 | |||
| f44c075ede | |||
| ac9f672bae | |||
| 43b8307e54 | |||
| 9541c47470 | |||
| a40326778e |
@@ -8,6 +8,19 @@ 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.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
|
## [v1.34.0] - 2026-08-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -1546,3 +1559,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.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.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.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`.
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ Optional extra ports (only if you need them):
|
|||||||
|
|
||||||
### 4. Docker + Docker Compose
|
### 4. Docker + Docker Compose
|
||||||
|
|
||||||
Any recent Docker with Compose — the v2 plugin (`docker compose`) or the v1
|
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.
|
||||||
standalone (`docker-compose`) both work.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Vendored
+17
-1
@@ -426,12 +426,16 @@ async function seedDirectory(token, clientId, jumpClientId) {
|
|||||||
macAddress: HOST_FACTS.mac,
|
macAddress: HOST_FACTS.mac,
|
||||||
os: HOST_FACTS.os,
|
os: HOST_FACTS.os,
|
||||||
kernel: HOST_FACTS.kernel,
|
kernel: HOST_FACTS.kernel,
|
||||||
|
sshPort: 22,
|
||||||
}, ['stack-host']);
|
}, ['stack-host']);
|
||||||
await ensure('service', 'SSO Manager', 'sso-manager', host.id, {
|
await ensure('service', 'SSO Manager', 'sso-manager', host.id, {
|
||||||
address: `https://${SSO_HOST}`,
|
address: `https://${SSO_HOST}`,
|
||||||
port: 3001,
|
port: 3001,
|
||||||
gitRepo: 'https://github.com/theta42/sso-manager-node',
|
gitRepo: 'https://github.com/theta42/sso-manager-node',
|
||||||
subType: 'web',
|
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
|
// Proxy = the node management UI; OpenResty = the data plane every hostname
|
||||||
// in the stack actually flows through (80/443). Two faces, two entries.
|
// in the stack actually flows through (80/443). Two faces, two entries.
|
||||||
@@ -440,6 +444,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
|
|||||||
port: 3000,
|
port: 3000,
|
||||||
gitRepo: 'https://github.com/theta42/proxy',
|
gitRepo: 'https://github.com/theta42/proxy',
|
||||||
subType: 'web',
|
subType: 'web',
|
||||||
|
icon: 'mdi:server-network',
|
||||||
|
tagline: 'Reverse proxy and API gateway.',
|
||||||
|
requestable: false,
|
||||||
});
|
});
|
||||||
// OpenLDAP is independently consumed — Linux hosts authenticate against it
|
// OpenLDAP is independently consumed — Linux hosts authenticate against it
|
||||||
// (PAM/SSSD, sudoRole, sshPublicKey) and LDAP-native apps bind directly
|
// (PAM/SSSD, sudoRole, sshPublicKey) and LDAP-native apps bind directly
|
||||||
@@ -451,8 +458,12 @@ async function seedDirectory(token, clientId, jumpClientId) {
|
|||||||
address: `ldaps://${LDAPS_HOST}:636`,
|
address: `ldaps://${LDAPS_HOST}:636`,
|
||||||
port: 389,
|
port: 389,
|
||||||
externalPort: 636,
|
externalPort: 636,
|
||||||
|
portMappings: [{ proto: 'tcp', external: 636, internal: 389, comment: 'LDAPS' }],
|
||||||
gitRepo: 'https://github.com/theta42/sso-manager-node',
|
gitRepo: 'https://github.com/theta42/sso-manager-node',
|
||||||
subType: 'openldap',
|
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 address: OpenResty fronts every host under the domain (same
|
||||||
// */** wildcard convention the proxy's Host records use). Its config lives
|
// */** wildcard convention the proxy's Host records use). Its config lives
|
||||||
@@ -462,6 +473,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
|
|||||||
port: 443,
|
port: 443,
|
||||||
gitRepo: 'https://github.com/theta42/proxy',
|
gitRepo: 'https://github.com/theta42/proxy',
|
||||||
subType: 'openresty',
|
subType: 'openresty',
|
||||||
|
icon: 'mdi:router-network',
|
||||||
|
tagline: 'Data plane.',
|
||||||
|
requestable: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// SSH jump host service (core component — always registered).
|
// SSH jump host service (core component — always registered).
|
||||||
@@ -473,6 +487,9 @@ async function seedDirectory(token, clientId, jumpClientId) {
|
|||||||
port: 3002,
|
port: 3002,
|
||||||
gitRepo: 'https://github.com/theta42/jump-host',
|
gitRepo: 'https://github.com/theta42/jump-host',
|
||||||
subType: 'ssh',
|
subType: 'ssh',
|
||||||
|
icon: 'mdi:ssh',
|
||||||
|
tagline: 'Secure SSH jump host.',
|
||||||
|
requestable: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +590,6 @@ function writeJumpSecrets(apiToken, oidc, localAdminPass) {
|
|||||||
// sshPublicKey attribute (key injection); for a hardened deployment use a
|
// sshPublicKey attribute (key injection); for a hardened deployment use a
|
||||||
// scoped account with an sshPublicKey write-ACL instead (see jump-host README).
|
// scoped account with an sshPublicKey write-ACL instead (see jump-host README).
|
||||||
module.exports = {
|
module.exports = {
|
||||||
\tname: ${JSON.stringify(sso.name || 'SSO Manager')},
|
|
||||||
\tldap: {
|
\tldap: {
|
||||||
\t\t// ldaps:// (636), not ldap:// (389): @simpleworkjs/ldap's client always
|
\t\t// ldaps:// (636), not ldap:// (389): @simpleworkjs/ldap's client always
|
||||||
\t\t// sets tlsOptions (see jump-host's models/user_ldap.js), and ldapts
|
\t\t// sets tlsOptions (see jump-host's models/user_ldap.js), and ldapts
|
||||||
|
|||||||
+8
-2
@@ -12,8 +12,7 @@ description: Step-by-step first run for theta-suite — prerequisites, setup.env
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- A Linux host with **Docker** + **Docker Compose** (the v2 plugin `docker
|
- A Linux host with **Docker + Docker Compose** (you must use the modern `docker compose` v2 plugin; the older `docker-compose` v1 standalone will fail on BuildKit images).
|
||||||
compose` or the v1 standalone `docker-compose` both work).
|
|
||||||
- Two hostnames that resolve to the host: one for the SSO UI (your `stack.ssoHost`),
|
- Two hostnames that resolve to the host: one for the SSO UI (your `stack.ssoHost`),
|
||||||
one for the proxy mgmt UI (your `stack.proxyHost`). On a real network add DNS
|
one for the proxy mgmt UI (your `stack.proxyHost`). On a real network add DNS
|
||||||
records; for a local try, add them to `/etc/hosts`.
|
records; for a local try, add them to `/etc/hosts`.
|
||||||
@@ -141,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`
|
passwords are reset to the config; the OAuth client is kept if `proxy-secrets.js`
|
||||||
already holds its creds).
|
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
|
## Direct LDAP for LDAP-native clients and Linux hosts
|
||||||
|
|||||||
+1
-1
Submodule jump-host updated: 4874544955...c56bfe21e5
+1
-1
Submodule ldap-client updated: ca8132f5ff...31d8fa1229
+1
-1
Submodule proxy updated: 4aa994121a...62cdaa2cdd
+21
-8
@@ -73,13 +73,6 @@ CFG_DOMAIN=example.com
|
|||||||
# 'sso-manager' so clients don't need a public 636 port forward. See docs.
|
# 'sso-manager' so clients don't need a public 636 port forward. See docs.
|
||||||
#CFG_LDAPS_HOST=
|
#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 ──────────────────────────────────────────────────
|
# ── DO NOT put secrets here ──────────────────────────────────────────────────
|
||||||
# The LDAP admin password, JWT secret, admin password, LDAP service-account
|
# The LDAP admin password, JWT secret, admin password, LDAP service-account
|
||||||
# password, and the proxy's local admin password are all GENERATED (random)
|
# 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_LDAP_ADMIN_PASS / CFG_JWT_SECRET / CFG_ADMIN_PASS / CFG_SVC_PASS /
|
||||||
# CFG_PROXY_ADMIN_PASS here.
|
# 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) ───────────────────────────
|
# ── Geo-Location Scaling (N-Way Multi-Master LDAP) ───────────────────────────
|
||||||
# If deploying this stack across multiple physical sites to provide local HA
|
# If deploying this stack across multiple physical sites to provide local HA
|
||||||
# for directory services, you can enable N-Way Multi-Master OpenLDAP replication.
|
# 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.
|
# LDAP_REPLICATION_HOSTS is a space-separated list of the other sites' LDAP URLs.
|
||||||
# Example for Site 1:
|
# Example for Site 1:
|
||||||
#LDAP_SERVER_ID=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
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
CFG_ADMIN_PASS="${CFG_ADMIN_PASS:-}"
|
||||||
CONFIG_DIR=./config
|
CONFIG_DIR=./config
|
||||||
BACKUP_DIR=./backups
|
BACKUP_DIR=./backups
|
||||||
BACKUP_KEEP="${BACKUP_KEEP:-5}"
|
BACKUP_KEEP="${BACKUP_KEEP:-5}"
|
||||||
@@ -442,6 +443,7 @@ BAOEOF
|
|||||||
CFG_ADMIN_PASS="${CFG_ADMIN_PASS:-}"
|
CFG_ADMIN_PASS="${CFG_ADMIN_PASS:-}"
|
||||||
CFG_SVC_PASS="${CFG_SVC_PASS:-}"
|
CFG_SVC_PASS="${CFG_SVC_PASS:-}"
|
||||||
CFG_PROXY_ADMIN_PASS="${CFG_PROXY_ADMIN_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) ──
|
# ── One-time migration from .env / proxy.env (existing deployments) ──
|
||||||
# Preserve the operator's existing secrets so the running deployment keeps
|
# Preserve the operator's existing secrets so the running deployment keeps
|
||||||
@@ -672,7 +674,7 @@ for i in $(seq 1 30); do
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
if ! docker exec openbao bao status -format=json 2>/dev/null | grep -q '"initialized": true' || true; then
|
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)
|
status_json=$(docker exec openbao bao status -format=json 2>/dev/null || true)
|
||||||
if ! echo "$status_json" | grep -q '"initialized": true'; then
|
if ! echo "$status_json" | grep -q '"initialized": true'; then
|
||||||
info "Initializing openbao for the first time..."
|
info "Initializing openbao for the first time..."
|
||||||
@@ -795,6 +797,7 @@ HCL
|
|||||||
ensure_policy sso-admin <<'HCL'
|
ensure_policy sso-admin <<'HCL'
|
||||||
path "secret/data/*" { capabilities = ["create", "read", "update", "delete", "list"] }
|
path "secret/data/*" { capabilities = ["create", "read", "update", "delete", "list"] }
|
||||||
path "secret/metadata" { capabilities = ["list", "read", "delete"] }
|
path "secret/metadata" { capabilities = ["list", "read", "delete"] }
|
||||||
|
path "secret/metadata/" { capabilities = ["list", "read", "delete"] }
|
||||||
path "secret/metadata/*" { capabilities = ["list", "read", "delete"] }
|
path "secret/metadata/*" { capabilities = ["list", "read", "delete"] }
|
||||||
HCL
|
HCL
|
||||||
# proxy / jump-host — read only their own boot conf.
|
# proxy / jump-host — read only their own boot conf.
|
||||||
@@ -975,7 +978,7 @@ async function ensureHost(host, ip, targetPort) {
|
|||||||
host: host,
|
host: host,
|
||||||
ip: ip,
|
ip: ip,
|
||||||
targetPort: targetPort,
|
targetPort: targetPort,
|
||||||
forcessl: true,
|
forcessl: $( [[ "$CFG_CREATE_ALL_HTTP" == "1" ]] && echo false || echo true ),
|
||||||
targetssl: false,
|
targetssl: false,
|
||||||
sso_enabled: false,
|
sso_enabled: false,
|
||||||
created_by: 'setup.sh',
|
created_by: 'setup.sh',
|
||||||
@@ -1032,7 +1035,7 @@ const {Host} = require('/app/models').models;
|
|||||||
try { await Host.get($(js_str "$JUMP_HOST")); console.log('SKIP ${JUMP_HOST} (already exists)'); }
|
try { await Host.get($(js_str "$JUMP_HOST")); console.log('SKIP ${JUMP_HOST} (already exists)'); }
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e.name !== 'EntryNotFound') throw 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" == "1" ]] && echo false || echo true ), targetssl: false, sso_enabled: false, created_by: 'setup.sh' });
|
||||||
console.log('CREATED ${JUMP_HOST} -> jump-host:3002');
|
console.log('CREATED ${JUMP_HOST} -> jump-host:3002');
|
||||||
}
|
}
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
@@ -1042,9 +1045,104 @@ NODEEOF
|
|||||||
)
|
)
|
||||||
echo "$JUMP_HOSTS_OUT" | sed 's/^/[setup] /'
|
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" == "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 ───────────────────────────────────────────────────────────────
|
# ── 8. Summary ───────────────────────────────────────────────────────────────
|
||||||
echo
|
echo
|
||||||
info "\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
|
||||||
echo " SSO Manager UI: https://${SSO_HOST} (fronted by the proxy under TLS)"
|
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}"
|
echo " first-run fallback: http://127.0.0.1:${SSO_PORT:-3001}"
|
||||||
@@ -1056,7 +1154,7 @@ echo " Jump host (web): https://${JUMP_HOST:-jump.${SSO_HOST#sso.}} (audit
|
|||||||
echo
|
echo
|
||||||
echo " First admin login credentials are in ./config/sso-secrets.js:"
|
echo " First admin login credentials are in ./config/sso-secrets.js:"
|
||||||
echo " user: ${ADMIN_UID}"
|
echo " user: ${ADMIN_UID}"
|
||||||
echo " pass: ${CFG_ADMIN_PASS}"
|
echo " pass: ${CFG_ADMIN_PASS:-<see ./config/sso-secrets.js>}"
|
||||||
echo
|
echo
|
||||||
echo " Proxy local admin (anti-lockout fallback if the SSO is unreachable):"
|
echo " Proxy local admin (anti-lockout fallback if the SSO is unreachable):"
|
||||||
echo " user: proxyadmin2"
|
echo " user: proxyadmin2"
|
||||||
|
|||||||
+1
-1
Submodule sso-manager-node updated: 522093e898...8143ef8ca8
+1
-1
Submodule theta-agent updated: 8a97bc7fbd...821ce5f991
Reference in New Issue
Block a user