Files
DECNET/decnet/web/templates/enroll_bootstrap.sh.j2
anti dad29249de fix(updater): align bootstrap layout with updater; log update phases
The bootstrap was installing into /opt/decnet/.venv with an editable
`pip install -e .`, and /usr/local/bin/decnet pointed there. The updater
writes releases to /opt/decnet/releases/active/ with a shared venv at
/opt/decnet/venv — a parallel tree nothing on the box actually runs.
Result: updates appeared to succeed (release dir rotated, SHA changed)
but systemd kept executing the untouched bootstrap code.

Changes:
  - Bootstrap now installs directly into /opt/decnet/releases/active
    with the shared venv at /opt/decnet/venv and /opt/decnet/current
    symlinked. Same layout the updater rotates in and out of.
  - /usr/local/bin/decnet -> /opt/decnet/venv/bin/decnet.
  - run_update / run_update_self heal /usr/local/bin/decnet on every
    push so already-enrolled hosts recover on the next update instead
    of needing a re-enroll.
  - run_update / run_update_self now log each phase (receive, extract,
    pip install, rotate, restart, probe) so the updater log actually
    shows what happened.
2026-04-19 18:39:11 -04:00

78 lines
3.0 KiB
Django/Jinja

#!/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..."
install -Dm0644 etc/systemd/system/decnet-agent.service /etc/systemd/system/decnet-agent.service
install -Dm0644 etc/systemd/system/decnet-forwarder.service /etc/systemd/system/decnet-forwarder.service
install -Dm0644 etc/systemd/system/decnet-engine.service /etc/systemd/system/decnet-engine.service
if [[ "$WITH_UPDATER" == "true" ]]; then
install -Dm0644 etc/systemd/system/decnet-updater.service /etc/systemd/system/decnet-updater.service
fi
systemctl daemon-reload
ACTIVE_UNITS=(decnet-agent.service decnet-forwarder.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."