#!/usr/bin/env bash # DECNET bootstrap installer for agent {{ agent_name }} -> master {{ master_host }}. # Fetches the code+certs payload, installs, and starts the agent daemon. # Generated by the master at {{ generated_at }}. Expires {{ expires_at }}. set -euo pipefail [[ $EUID -eq 0 ]] || { echo "decnet-install: must run as root (use sudo)"; exit 1; } for bin in python3 curl tar systemctl; do command -v "$bin" >/dev/null || { echo "decnet-install: $bin required"; exit 1; } done WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT echo "[DECNET] fetching payload..." curl -fsSL "{{ tarball_url }}" | tar -xz -C "$WORK" INSTALL_DIR=/opt/decnet RELEASE_DIR="$INSTALL_DIR/releases/active" VENV_DIR="$INSTALL_DIR/venv" # Mirror the updater's layout from day one so `decnet updater` can rotate # releases/active in-place and the shared venv is the thing on PATH. mkdir -p "$RELEASE_DIR" cp -a "$WORK/." "$RELEASE_DIR/" ln -sfn "$RELEASE_DIR" "$INSTALL_DIR/current" cd "$RELEASE_DIR" echo "[DECNET] building shared venv at $VENV_DIR..." python3 -m venv "$VENV_DIR" "$VENV_DIR/bin/pip" install -q --upgrade pip "$VENV_DIR/bin/pip" install -q "$RELEASE_DIR" install -Dm0644 etc/decnet/decnet.ini /etc/decnet/decnet.ini [[ -f services.ini ]] && install -Dm0644 services.ini /etc/decnet/services.ini # Log directory the baked-in INI points at — must exist before `decnet` imports config. install -d -m0755 /var/log/decnet # Certs live under /etc/decnet/ (root-owned, 0600 keys) — this is a root # daemon's data, not a user's. The baked INI's `agent-dir`/`updater-dir` # point at these paths. for f in ca.crt worker.crt worker.key; do install -Dm0600 -o root -g root \ "home/.decnet/agent/$f" "/etc/decnet/agent/$f" done chmod 0755 /etc/decnet/agent WITH_UPDATER="{{ with_updater }}" if [[ "$WITH_UPDATER" == "true" && -d home/.decnet/updater ]]; then for f in ca.crt updater.crt updater.key; do install -Dm0600 -o root -g root \ "home/.decnet/updater/$f" "/etc/decnet/updater/$f" done chmod 0755 /etc/decnet/updater fi # Guarantee the pip-installed entrypoint is executable (some setuptools+editable # combos drop it with mode 0644) and expose it on PATH. chmod 0755 "$VENV_DIR/bin/decnet" ln -sf "$VENV_DIR/bin/decnet" /usr/local/bin/decnet echo "[DECNET] installing systemd units..." for unit in \ decnet-agent decnet-forwarder decnet-engine \ decnet-collector decnet-prober decnet-sniffer; do install -Dm0644 "etc/systemd/system/${unit}.service" "/etc/systemd/system/${unit}.service" done if [[ "$WITH_UPDATER" == "true" ]]; then install -Dm0644 etc/systemd/system/decnet-updater.service /etc/systemd/system/decnet-updater.service fi systemctl daemon-reload # Agent + forwarder are the control plane; collector/prober/profiler/sniffer # are the per-host microservices that used to require `decnet deploy` to # auto-spawn. With systemd units they come up at boot and auto-restart. ACTIVE_UNITS=( decnet-agent.service decnet-forwarder.service decnet-collector.service decnet-prober.service decnet-sniffer.service ) if [[ "$WITH_UPDATER" == "true" ]]; then ACTIVE_UNITS+=(decnet-updater.service) fi systemctl enable --now "${ACTIVE_UNITS[@]}" echo "[DECNET] agent {{ agent_name }} enrolled -> {{ master_host }}. Units: ${ACTIVE_UNITS[*]} active."