feat: add host_agent plugin — push-model host resource monitoring
Lightweight stdlib-only Python agent runs on each monitored host, collects CPU / memory / disk / load / uptime from /proc every 30s, and POSTs signed payloads to the Roundtable ingest endpoint. One-line curl-pipe installer creates a hardened systemd unit; admin UI manages host registrations with rotate / revoke. - agent.py: 370 LoC single-file daemon, ring buffer + exponential backoff - ingest route: bearer-token auth, metric expansion into plugin_metrics - install.sh.j2: systemd unit with NoNewPrivileges / ProtectSystem / ProtectHome - settings UI: add host / rotate token / delete registration (admin-only) - dashboard widgets: fleet-glance table + per-host history chart - stale-agent scheduler: 60s log warning for agents past 180s silence Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#!/bin/sh
|
||||
# Roundtable host agent installer
|
||||
# Generated for: {{ host_name }} ({{ host_address }})
|
||||
# Roundtable URL: {{ url }}
|
||||
set -e
|
||||
|
||||
ROUNDTABLE_URL="{{ url }}"
|
||||
AGENT_TOKEN="{{ token }}"
|
||||
AGENT_VERSION="{{ agent_version }}"
|
||||
|
||||
AGENT_USER="roundtable-agent"
|
||||
AGENT_DIR="/usr/local/lib/roundtable-agent"
|
||||
CONF_FILE="/etc/roundtable-agent.conf"
|
||||
UNIT_FILE="/etc/systemd/system/roundtable-agent.service"
|
||||
|
||||
# ── 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 roundtable-agent.service 2>/dev/null || true
|
||||
rm -f "$UNIT_FILE" "$CONF_FILE"
|
||||
rm -rf "$AGENT_DIR"
|
||||
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 -sSL "${ROUNDTABLE_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 = $ROUNDTABLE_URL
|
||||
token = $AGENT_TOKEN
|
||||
interval_seconds = 30
|
||||
EOF
|
||||
chown "root:$AGENT_USER" "$CONF_FILE"
|
||||
chmod 0640 "$CONF_FILE"
|
||||
|
||||
# ── write systemd unit ───────────────────────────────────────────────────────
|
||||
cat > "$UNIT_FILE" <<EOF
|
||||
[Unit]
|
||||
Description=Roundtable host agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$AGENT_USER
|
||||
ExecStart=/usr/bin/python3 $AGENT_DIR/agent.py
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
ReadOnlyPaths=/proc /sys
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now roundtable-agent.service
|
||||
|
||||
echo
|
||||
echo "Roundtable host agent $AGENT_VERSION installed and running."
|
||||
echo "Check status: systemctl status roundtable-agent"
|
||||
echo "Logs: journalctl -u roundtable-agent -f"
|
||||
Reference in New Issue
Block a user