Files
FabledSteward/plugins/host_agent/templates/install.sh.j2
T
bvandeusenandClaude Opus 5.5 6a68bd75d9
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 1m22s
CI / unit (push) Successful in 1m24s
CI / publish (push) Successful in 1m12s
feat(host_agent): a root helper the agent can start, for updates, reboots and drains only (#5766)
#5766 "A root helper the agent can start, for a fixed set of maintenance
actions and nothing else", milestone 514.

The agent runs unprivileged under NoNewPrivileges, so it can't update or
reboot its host. It now leaves a request in /var/lib/steward-agent/requests,
the one path its unit lets it write; steward-maint.path starts maint.py as
root, which reads it without following links, accepts only update, reboot,
drain or undrain, deletes it, and writes the outcome to
/var/lib/steward-maint/results. The agent (1.17.0) reports each new result
state once as a `maintenance` event, re-checks pending updates when an update
finishes, and says in its metadata whether the helper is installed.

The units and the helper are served from one copy at
/plugins/host_agent/files/<name> (a fixed list), and install.sh plus the
install, provision and update playbooks all fetch them, replacing three
inline copies of the unit. Update agent installs the helper on existing
hosts; the Agent panel says under Manage agent whether it is there.

Steward handing out jobs is #5767; the cadence is #5768.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:34:28 -04:00

82 lines
3.7 KiB
Django/Jinja

#!/bin/sh
# Steward host agent installer
# Generated for: {{ host_name }} ({{ host_address }})
# Steward URL: {{ url }}
set -e
STEWARD_URL="{{ url }}"
AGENT_TOKEN="{{ token }}"
AGENT_VERSION="{{ agent_version }}"
AGENT_USER="steward-agent"
AGENT_DIR="/usr/local/lib/steward-agent"
CONF_FILE="/etc/steward-agent.conf"
UNIT_DIR="/etc/systemd/system"
UNITS="steward-agent.service steward-maint.service steward-maint.path"
FILES_URL="${STEWARD_URL}/plugins/host_agent/files"
# ── preflight ────────────────────────────────────────────────────────────────
[ "$(id -u)" = "0" ] || { echo "must run as root (use sudo)"; exit 1; }
command -v systemctl >/dev/null 2>&1 || { echo "systemd not found — unsupported init system"; exit 1; }
command -v python3 >/dev/null 2>&1 || { echo "python3 not found — install python3 first"; exit 1; }
# Handle --uninstall
if [ "${1:-}" = "--uninstall" ]; then
systemctl disable --now steward-maint.path steward-agent.service 2>/dev/null || true
for u in $UNITS; do rm -f "$UNIT_DIR/$u"; done
rm -f "$CONF_FILE"
rm -rf "$AGENT_DIR" /var/lib/steward-agent /var/lib/steward-maint
systemctl daemon-reload
# keep the system user — removing it risks orphaned files elsewhere
echo "uninstalled"
exit 0
fi
# ── create system user ───────────────────────────────────────────────────────
if ! id "$AGENT_USER" >/dev/null 2>&1; then
useradd --system --no-create-home --shell /usr/sbin/nologin "$AGENT_USER"
fi
# ── drop the agent file ──────────────────────────────────────────────────────
mkdir -p "$AGENT_DIR"
curl -fsSL "${STEWARD_URL}/plugins/host_agent/agent.py" -o "$AGENT_DIR/agent.py"
chmod 0755 "$AGENT_DIR/agent.py"
chown root:root "$AGENT_DIR/agent.py"
# ── write config ─────────────────────────────────────────────────────────────
cat > "$CONF_FILE" <<EOF
url = $STEWARD_URL
token = $AGENT_TOKEN
interval_seconds = 30
# Container logs are collected by default. To opt this host out entirely:
# docker_logs_enabled = false
# To skip specific noisy containers (comma-separated names):
# docker_log_exclude = watchtower, some-chatty-service
EOF
chown "root:$AGENT_USER" "$CONF_FILE"
chmod 0640 "$CONF_FILE"
# ── the maintenance helper and the units (#5766) ─────────────────────────────
# One copy, served by Steward, the same the playbooks install. The agent may
# write only its request directory; the helper (root) and its results don't
# belong to it.
curl -fsSL "${FILES_URL}/maint.py" -o "$AGENT_DIR/maint.py"
chmod 0755 "$AGENT_DIR/maint.py"
chown root:root "$AGENT_DIR/maint.py"
install -d -o root -g root -m 0755 /var/lib/steward-agent /var/lib/steward-maint /var/lib/steward-maint/results
install -d -o "$AGENT_USER" -g "$AGENT_USER" -m 0700 /var/lib/steward-agent/requests
for u in $UNITS; do
curl -fsSL "${FILES_URL}/$u" -o "$UNIT_DIR/$u"
chmod 0644 "$UNIT_DIR/$u"
done
systemctl daemon-reload
systemctl enable --now steward-maint.path
systemctl enable steward-agent.service
systemctl restart steward-agent.service
echo
echo "Steward host agent $AGENT_VERSION installed and running."
echo "Check status: systemctl status steward-agent"
echo "Logs: journalctl -u steward-agent -f"