feat(install): --enable-oob installs felhom-sshd + static belt (H1 Part 5)
install_oob: /etc/felhom-sshd tree + dedicated host key + felhom-op user + scoped sudoers + RuntimeDirectory-guarded felhom-sshd.service (enable-not-start; agent renders config) + static felhom_oob nft table + boot loader. Uninstall removes all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -154,6 +154,7 @@ REMOVE_GOLDEN=false # --remove-golden: also delete the golden vzdump during
|
||||
ADOPT_POOL=false # --adopt-pool: retrofit an EXISTING Felhom guest into the felhom pool (non-destructive)
|
||||
RESCOPE_ACL=false # --rescope-acl: migrate an existing install from the broad-/ token to the scoped ACL
|
||||
ROTATE_RECOVERY=false # --rotate-recovery: regenerate + re-vault the break-glass root@pam password (TASK G1)
|
||||
ENABLE_OOB=false # --enable-oob: install the dedicated felhom-sshd OOB instance + belt (TASK H1)
|
||||
|
||||
# --- Gitea (artifact source) + agent install model (BUNDLE slice) ---
|
||||
GITEA_BASE="https://gitea.dooplex.hu"
|
||||
@@ -600,6 +601,27 @@ run_uninstall() {
|
||||
if [[ -e "$wda" ]]; then run rm -f "$wda"; fi
|
||||
done
|
||||
|
||||
# 4b3. OOB felhom-sshd instance + belt (TASK H1). Stop/disable felhom-sshd + the belt loader,
|
||||
# remove units + config tree + belt table + felhom-op user/sudoers. NEVER touch the stock
|
||||
# sshd/:22/etc/ssh. Tolerate-absent throughout.
|
||||
if systemctl list-unit-files felhom-sshd.service >/dev/null 2>&1; then
|
||||
systemctl is-active --quiet felhom-sshd 2>/dev/null && run systemctl stop felhom-sshd
|
||||
systemctl is-enabled --quiet felhom-sshd 2>/dev/null && run systemctl disable felhom-sshd
|
||||
fi
|
||||
if systemctl list-unit-files felhom-oob-nft.service >/dev/null 2>&1; then
|
||||
systemctl is-active --quiet felhom-oob-nft 2>/dev/null && run systemctl stop felhom-oob-nft
|
||||
systemctl is-enabled --quiet felhom-oob-nft 2>/dev/null && run systemctl disable felhom-oob-nft
|
||||
fi
|
||||
run systemctl reset-failed felhom-sshd felhom-oob-nft 2>/dev/null || true
|
||||
nft list table inet felhom_oob >/dev/null 2>&1 && run nft delete table inet felhom_oob
|
||||
local oa
|
||||
for oa in /etc/systemd/system/felhom-sshd.service /etc/systemd/system/felhom-oob-nft.service \
|
||||
/etc/felhom-oob.nft /etc/sudoers.d/felhom-op /run/felhom-sshd.pid /run/felhom-sshd.healed; do
|
||||
if [[ -e "$oa" ]]; then run rm -f "$oa"; fi
|
||||
done
|
||||
if [[ -d /etc/felhom-sshd ]]; then run rm -rf /etc/felhom-sshd; fi
|
||||
if id felhom-op >/dev/null 2>&1; then run userdel -r felhom-op 2>/dev/null || run userdel felhom-op; fi
|
||||
|
||||
# 4c. Shared-parent unit + wrapper + /mnt/felhom-drives (agent-installed at runtime; drill R2).
|
||||
# Stop/disable, remove unit + script, unbind + remove the (empty) parent dir. Tolerate-absent.
|
||||
if systemctl list-unit-files felhom-shared-parent.service 2>/dev/null | grep -q felhom-shared-parent; then
|
||||
@@ -801,6 +823,7 @@ while [[ $# -gt 0 ]]; do
|
||||
--adopt-pool) ADOPT_POOL=true; shift ;;
|
||||
--rescope-acl) RESCOPE_ACL=true; shift ;;
|
||||
--rotate-recovery) ROTATE_RECOVERY=true; shift ;;
|
||||
--enable-oob) ENABLE_OOB=true; shift ;;
|
||||
--acl-storages) read -ra PVE_STORAGES <<< "$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--resume) RESUME=true; shift ;;
|
||||
@@ -1410,6 +1433,9 @@ step_agent_install() {
|
||||
# incident G1 closes (a second sshd's `RuntimeDirectory=sshd` removed the shared /run/sshd).
|
||||
install_mgmt_watchdog
|
||||
|
||||
# H1: dedicated felhom-sshd OOB instance + static belt (gated by --enable-oob).
|
||||
install_oob
|
||||
|
||||
_state_mark agent_install
|
||||
}
|
||||
|
||||
@@ -1455,6 +1481,58 @@ install_mgmt_watchdog() {
|
||||
log_success " installed break-glass layers 1+2 (tmpfiles /run/sshd + agent-independent watchdog timer)"
|
||||
}
|
||||
|
||||
# install_oob installs the dedicated felhom-sshd OOB instance + the static nft belt (TASK H1). The
|
||||
# STATIC parts land here (unit, host key, felhom-op user + sudoers, belt table + loader); the agent
|
||||
# reconciles the DYNAMIC parts (port claim, config render, authorized_keys, belt set elements) once
|
||||
# oob.enabled=true. Gated by --enable-oob. Non-fatal if the agent repo predates the artifacts.
|
||||
# The felhom-sshd unit is RuntimeDirectory-guarded (the G1 incident cause) before install.
|
||||
install_oob() {
|
||||
$ENABLE_OOB || { log_skip " OOB (felhom-sshd) not requested (--enable-oob) — skipping"; return 0; }
|
||||
if $DRY_RUN; then
|
||||
log_dry "mkdir /etc/felhom-sshd{,/authorized_keys} ; ssh-keygen host key ; useradd felhom-op ; install felhom-op sudoers"
|
||||
log_dry "fetch felhom-sshd.service (RuntimeDirectory-guarded) + felhom-oob.nft + felhom-oob-nft.service ; enable"
|
||||
return 0
|
||||
fi
|
||||
install -d -o root -g root -m 0755 /etc/felhom-sshd /etc/felhom-sshd/authorized_keys
|
||||
# dedicated host key (stable across reloads) — generate once.
|
||||
if [[ ! -f /etc/felhom-sshd/ssh_host_ed25519_key ]]; then
|
||||
ssh-keygen -t ed25519 -N "" -f /etc/felhom-sshd/ssh_host_ed25519_key -C felhom-sshd-hostkey -q
|
||||
chmod 600 /etc/felhom-sshd/ssh_host_ed25519_key
|
||||
fi
|
||||
# operator login user (no ambient privilege; escalates only via the felhom-op sudoers verbs).
|
||||
id felhom-op >/dev/null 2>&1 || useradd --create-home --shell /bin/bash felhom-op
|
||||
# felhom-op scoped sudoers (visudo-validated before install).
|
||||
local optmp; optmp=$(mktemp -t felhom-op-sudoers.XXXXXX)
|
||||
if fetch_raw "configs/felhom-op.sudoers" "$optmp" 2>/dev/null; then
|
||||
"$VISUDO" -cf "$optmp" >/dev/null || { rm -f "$optmp"; die "fetched felhom-op sudoers failed visudo -cf"; }
|
||||
install -m 0440 -o root -g root "$optmp" /etc/sudoers.d/felhom-op
|
||||
fi
|
||||
rm -f "$optmp"
|
||||
# felhom-sshd unit — RuntimeDirectory guard (the G1 incident cause) BEFORE install.
|
||||
local sutmp; sutmp=$(mktemp -t felhom-sshd-unit.XXXXXX)
|
||||
if ! fetch_raw "configs/felhom-sshd.service" "$sutmp" 2>/dev/null; then
|
||||
log_skip " felhom-sshd.service not in the agent repo yet — OOB stays unconfigured"
|
||||
rm -f "$sutmp"; return 0
|
||||
fi
|
||||
if grep -qiE '^[[:space:]]*RuntimeDirectory[[:space:]]*=' "$sutmp"; then
|
||||
rm -f "$sutmp"; die "felhom-sshd unit declares RuntimeDirectory= — the SPIKE-felhom-sshd §8 incident cause; refusing"
|
||||
fi
|
||||
install -m 0644 -o root -g root "$sutmp" /etc/systemd/system/felhom-sshd.service
|
||||
rm -f "$sutmp"
|
||||
# static belt table + boot loader.
|
||||
local ntmp utmp; ntmp=$(mktemp -t felhom-oob-nft.XXXXXX); utmp=$(mktemp -t felhom-oob-unit.XXXXXX)
|
||||
fetch_raw "configs/felhom-oob.nft" "$ntmp"
|
||||
fetch_raw "configs/felhom-oob-nft.service" "$utmp"
|
||||
nft -c -f "$ntmp" >/dev/null 2>&1 || { rm -f "$ntmp" "$utmp"; die "felhom-oob.nft failed nft -c — refusing"; }
|
||||
install -m 0644 -o root -g root "$ntmp" /etc/felhom-oob.nft
|
||||
install -m 0644 -o root -g root "$utmp" /etc/systemd/system/felhom-oob-nft.service
|
||||
rm -f "$ntmp" "$utmp"
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now felhom-oob-nft.service >/dev/null 2>&1 || true # load the static belt now
|
||||
systemctl enable felhom-sshd >/dev/null 2>&1 || true # NOT start — the agent renders the config first
|
||||
log_success " installed OOB felhom-sshd instance + static belt (agent renders config + fills sets once oob.enabled)"
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# STEP 6 — write agent config + ensure service healthy
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user