diff --git a/README.md b/README.md index cbfb513..bcbf651 100644 --- a/README.md +++ b/README.md @@ -4,31 +4,39 @@ Production installer for the Triton Manage Server. Container-based (Docker or Po ## Install -```bash -curl -fsSL https://raw.githubusercontent.com/primatekuntech/triton-install/main/get.sh | sudo bash +Your vendor provides a licence bundle — a folder containing two files: + +``` +triton-bundle/ +├── license.lic # signed offline licence token +└── pubkey # vendor's Ed25519 public key ``` -That's it. The setup wizard walks you through the rest. +Point the installer at the bundle: + +```bash +curl -fsSL https://raw.githubusercontent.com/primatekuntech/triton-install/main/get.sh | sudo bash -s -- --license-file /path/to/triton-bundle/license.lic +``` ## Setup wizard After install, open `http://localhost:8082` and complete the wizard: 1. Set your manage server name -2. Enter your Triton licence server URL and licence ID — or upload an air-gap licence file -3. Create the admin account +2. Create the admin account ## Optional flags Pass flags after `--`: ```bash -curl -fsSL https://raw.githubusercontent.com/primatekuntech/triton-install/main/get.sh | sudo bash -s -- [flags] +curl -fsSL https://raw.githubusercontent.com/primatekuntech/triton-install/main/get.sh | sudo bash -s -- --license-file /path/to/license.lic [flags] ``` | Flag | Description | |------|-------------| -| `--license-server-url URL` | Vendor's License Server URL. Public key is fetched automatically. | +| `--license-file PATH` | Path to `license.lic` from your vendor bundle. **Required.** | +| `--license-server-url URL` | License Server URL for ongoing heartbeats (optional, omit for air-gap). | | `--gateway-hostname HOST` | Agent mTLS hostname (defaults to current FQDN). | | `--manage-host-ip IP` | Host LAN IP for "+ This machine" auto-registration. | | `--port PORT` | Host port for the web UI (default: `8082`). | diff --git a/manage-server/env.template b/manage-server/env.template index 534dc09..4b35b04 100644 --- a/manage-server/env.template +++ b/manage-server/env.template @@ -54,12 +54,17 @@ TLS_CERT_HOST_DIR=/etc/triton/tls # ─── Sessions ──────────────────────────────────────────────────────────── TRITON_MANAGE_SESSION_TTL=24h -# ─── License server ────────────────────────────────────────────────────── -# Vendor's Ed25519 public key (64 hex chars). Required — get this from -# your Triton vendor. The manage server refuses to start without it. +# ─── Licence ───────────────────────────────────────────────────────────── +# Offline licence token from your vendor bundle (license.lic). Set by +# install.sh automatically — do not edit manually. +TRITON_LICENSE_KEY= + +# Vendor's Ed25519 public key (64 hex chars). Set by install.sh from the +# pubkey file in your vendor bundle — do not edit manually. TRITON_MANAGE_LICENSE_SERVER_PUBKEY= -# Vendor's License Server URL. Required for activation and heartbeat. +# Vendor's License Server URL. Optional — enables ongoing heartbeats and +# binary sync. Leave empty for fully air-gapped deployments. TRITON_LICENSE_SERVER_URL= # ─── Image ─────────────────────────────────────────────────────────────── diff --git a/manage-server/install.sh b/manage-server/install.sh index 1fbcc96..77660a0 100755 --- a/manage-server/install.sh +++ b/manage-server/install.sh @@ -5,11 +5,16 @@ # Container-based via Podman or Docker (auto-detected). # # Usage: -# sudo bash install.sh +# sudo bash install.sh --license-file /path/to/bundle/license.lic # -# Flags (all optional): -# --license-server-url URL Vendor's License Server URL. The public key is -# fetched automatically from the license server. +# The license bundle (provided by your vendor) contains two files: +# license.lic — signed offline licence token +# pubkey — vendor's Ed25519 public key (64 hex chars) +# Both files must be in the same directory. +# +# Flags: +# --license-file PATH Path to license.lic from your vendor bundle. Required. +# --license-server-url URL License Server URL for ongoing heartbeats (optional). # --gateway-hostname HOST Agent mTLS hostname (defaults to current FQDN). # --manage-host-ip IP Host LAN IP — used for "+ This machine". # --port PORT Host port for the web UI (default: 8082). @@ -24,6 +29,7 @@ info() { printf '[manage-server] %s\n' "$*"; } die() { printf '[manage-server] error: %s\n' "$*" >&2; exit 1; } # ── arg parsing ────────────────────────────────────────────────────────── +LICENSE_FILE="" LICENSE_SERVER_URL="" GATEWAY_HOST="" HOST_IP="" @@ -32,6 +38,7 @@ IMAGE="" NO_TLS=0 while [[ $# -gt 0 ]]; do case "$1" in + --license-file) LICENSE_FILE="$2"; shift 2 ;; --license-server-url) LICENSE_SERVER_URL="$2"; shift 2 ;; --gateway-hostname) GATEWAY_HOST="$2"; shift 2 ;; --manage-host-ip) HOST_IP="$2"; shift 2 ;; @@ -45,6 +52,18 @@ done [[ $EUID -eq 0 ]] || die "must run as root" +# ── validate license bundle ────────────────────────────────────────────── +[[ -n "$LICENSE_FILE" ]] || die "--license-file is required (path to license.lic from your vendor bundle)" +[[ -f "$LICENSE_FILE" ]] || die "license file not found: $LICENSE_FILE" + +BUNDLE_DIR="$(cd -- "$(dirname -- "$LICENSE_FILE")" && pwd)" +PUBKEY_FILE="$BUNDLE_DIR/pubkey" +[[ -f "$PUBKEY_FILE" ]] || die "pubkey file not found: $PUBKEY_FILE (must be in the same directory as license.lic)" + +LICENSE_TOKEN="$(cat "$LICENSE_FILE")" +LICENSE_PUBKEY="$(cat "$PUBKEY_FILE" | tr -d '[:space:]')" +[[ ${#LICENSE_PUBKEY} -eq 64 ]] || die "pubkey file must contain a 64 hex-char Ed25519 public key" + # ── runtime detection ──────────────────────────────────────────────────── if command -v podman-compose >/dev/null 2>&1; then COMPOSE=(podman-compose) @@ -78,23 +97,19 @@ if [[ ! -f "$ENV_FILE" ]]; then -e "s|^TRITON_MANAGE_WORKER_KEY=.*|TRITON_MANAGE_WORKER_KEY=$WORKER_KEY|" \ -e "s|^TRITON_VAULT_KEY=.*|TRITON_VAULT_KEY=$VAULT_KEY|" \ "$ENV_FILE" - info "vault key generated (PostgreSQL AES-256-GCM)" + info "secrets generated" - if [[ -n "$LICENSE_SERVER_URL" ]]; then - sed -i "s|^TRITON_LICENSE_SERVER_URL=.*|TRITON_LICENSE_SERVER_URL=$LICENSE_SERVER_URL|" "$ENV_FILE" - info "fetching public key from license server..." - LICENSE_PUBKEY=$(curl -fsSL "${LICENSE_SERVER_URL}/api/v1/license/pubkey" \ - | grep -o '"pubkey":"[^"]*"' | cut -d'"' -f4) \ - || die "failed to fetch public key from ${LICENSE_SERVER_URL}" - [[ ${#LICENSE_PUBKEY} -eq 64 ]] \ - || die "license server returned an invalid public key (expected 64 hex chars)" - sed -i "s|^TRITON_MANAGE_LICENSE_SERVER_PUBKEY=.*|TRITON_MANAGE_LICENSE_SERVER_PUBKEY=$LICENSE_PUBKEY|" "$ENV_FILE" - info "public key configured" - fi - [[ -n "$GATEWAY_HOST" ]] && sed -i "s|^TRITON_MANAGE_GATEWAY_HOSTNAME=.*|TRITON_MANAGE_GATEWAY_HOSTNAME=$GATEWAY_HOST|" "$ENV_FILE" - [[ -n "$HOST_IP" ]] && sed -i "s|^TRITON_MANAGE_HOST_IP=.*|TRITON_MANAGE_HOST_IP=$HOST_IP|" "$ENV_FILE" - [[ -n "$PORT" ]] && sed -i "s|^TRITON_MANAGE_HOST_PORT=.*|TRITON_MANAGE_HOST_PORT=$PORT|" "$ENV_FILE" - [[ -n "$IMAGE" ]] && sed -i "s|^TRITON_MANAGE_IMAGE=.*|TRITON_MANAGE_IMAGE=$IMAGE|" "$ENV_FILE" + sed -i \ + -e "s|^TRITON_MANAGE_LICENSE_SERVER_PUBKEY=.*|TRITON_MANAGE_LICENSE_SERVER_PUBKEY=$LICENSE_PUBKEY|" \ + -e "s|^TRITON_LICENSE_KEY=.*|TRITON_LICENSE_KEY=$LICENSE_TOKEN|" \ + "$ENV_FILE" + info "licence configured" + + [[ -n "$LICENSE_SERVER_URL" ]] && sed -i "s|^TRITON_LICENSE_SERVER_URL=.*|TRITON_LICENSE_SERVER_URL=$LICENSE_SERVER_URL|" "$ENV_FILE" + [[ -n "$GATEWAY_HOST" ]] && sed -i "s|^TRITON_MANAGE_GATEWAY_HOSTNAME=.*|TRITON_MANAGE_GATEWAY_HOSTNAME=$GATEWAY_HOST|" "$ENV_FILE" + [[ -n "$HOST_IP" ]] && sed -i "s|^TRITON_MANAGE_HOST_IP=.*|TRITON_MANAGE_HOST_IP=$HOST_IP|" "$ENV_FILE" + [[ -n "$PORT" ]] && sed -i "s|^TRITON_MANAGE_HOST_PORT=.*|TRITON_MANAGE_HOST_PORT=$PORT|" "$ENV_FILE" + [[ -n "$IMAGE" ]] && sed -i "s|^TRITON_MANAGE_IMAGE=.*|TRITON_MANAGE_IMAGE=$IMAGE|" "$ENV_FILE" info ".env created at $ENV_FILE" info " back this up — it contains the JWT signing key, worker key, and vault key" @@ -117,7 +132,6 @@ HOST_PORT=${HOST_PORT:-8082} info "waiting for manage server to become healthy on :${HOST_PORT}..." for i in $(seq 1 30); do CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${HOST_PORT}/" || echo "000") - # 302 (redirect to setup or login) means the server is up. if [[ "$CODE" == "302" || "$CODE" == "200" ]]; then info "manage server is up" break @@ -128,9 +142,6 @@ done info "" info "Installation complete. Next steps:" info " 1. Open http://localhost:${HOST_PORT} (or your public URL)" -info " 2. Complete the setup wizard:" -info " - Set your manage server name" -info " - Enter your Triton licence server URL and licence ID" -info " - Or upload an air-gap licence file" +info " 2. Complete the setup wizard" info " 3. Configure TLS via reverse proxy (see docs)" info ""