ops(esh-nas): infra-ops identity bootstrapped in CT 103 via pct from esh-pve-nas

Prime's ruling 2026-10-13. esh-nas (10.0.50.50) had no infra-ops user, so key
login was refused. The same steps as bootstrap-infra-ops-user.yaml (uid/gid
850, fleet key, NOPASSWD sudoers with log_output and the BULK_DATA carve-out,
visudo-validated) ran inside the container from its host. Verified with a
direct ssh infra-ops@10.0.50.50 and sudo -n whoami = root.
This commit is contained in:
vh
2026-10-13 13:25:21 -07:00
parent b699088e2b
commit 30a7220b2c
4 changed files with 53 additions and 2 deletions
+2 -1
View File
@@ -25,7 +25,8 @@
# esh-pve-nas) DO get infra-ops — done that day. # esh-pve-nas) DO get infra-ops — done that day.
# PVE ships without sudo: `apt-get install sudo` first. # PVE ships without sudo: `apt-get install sudo` first.
# Also granted by operator request: esh-docker-vm, # Also granted by operator request: esh-docker-vm,
# esh-vm-db (2026-08-24) and vm-esh-nas (2026-09-27). # esh-vm-db (2026-08-24), vm-esh-nas (2026-09-27) and esh-nas
# (CT 103, 2026-10-13, via pct from its host: playbooks/esh-nas-infra-ops.yaml).
# - nh3-nas (Synology DSM) (no standard useradd / sudoers.d) # - nh3-nas (Synology DSM) (no standard useradd / sudoers.d)
# #
# Idempotent: re-running reconciles the key + sudoers without error. # Idempotent: re-running reconciles the key + sudoers without error.
+23
View File
@@ -0,0 +1,23 @@
# Bootstrap the infra-ops identity INSIDE esh-nas (CT 103 on esh-pve-nas, 10.0.50.50), Prime 2026-10-13 ("set it up").
# infra-ops could not log into the container (no user), so this runs on the HOST and reaches in with pct.
# scripts/elway infra-ops@10.0.50.55 --playbook playbooks/esh-nas-infra-ops.yaml
# The in-container steps are scripts/oneoff/esh-nas-infra-ops/bootstrap-in-ct.sh (= playbooks/bootstrap-infra-ops-user.yaml).
vars:
ctid: "103"
steps:
- name: Stage the bootstrap script on the host
upload:
src: scripts/oneoff/esh-nas-infra-ops/bootstrap-in-ct.sh
dest: /tmp/esh-nas-bootstrap-infra-ops.sh
mode: "0700"
- name: Push it into CT {{ ctid }} and run it as root there
sudo: true
shell: pct push {{ ctid }} /tmp/esh-nas-bootstrap-infra-ops.sh /root/bootstrap-infra-ops.sh --perms 0700 && pct exec {{ ctid }} -- bash /root/bootstrap-infra-ops.sh
- name: Remove the staged copies
sudo: true
shell: pct exec {{ ctid }} -- rm -f /root/bootstrap-infra-ops.sh && rm -f /tmp/esh-nas-bootstrap-infra-ops.sh
verify:
- name: The user and its sudoers file exist in CT {{ ctid }}
sudo: true
shell: pct exec {{ ctid }} -- sh -c 'id infra-ops && visudo -cf /etc/sudoers.d/infra-ops && grep -q NOPASSWD:ALL /etc/sudoers.d/infra-ops'
changed_when: "false"
@@ -0,0 +1,27 @@
#!/bin/bash
# Run INSIDE esh-nas (CT 103 on esh-pve-nas) as root, via `pct exec 103`. The same steps as
# playbooks/bootstrap-infra-ops-user.yaml, for a container infra-ops cannot log into yet (Prime 2026-10-13: "set it up").
set -euo pipefail
U=infra-ops; ID=850
KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN+1HBwfXrkfTYWdcnWCjLJ6VLAGC87gxH5h5vKaaA3c infra-ops@pfi-fleet'
if ! id "$U" >/dev/null 2>&1; then
if ! getent passwd "$ID" >/dev/null && ! getent group "$ID" >/dev/null; then
groupadd -g "$ID" "$U"; useradd -m -s /bin/bash -u "$ID" -g "$ID" "$U"
else
echo "uid/gid $ID taken; letting the OS allocate"; useradd -m -s /bin/bash "$U"
fi
echo "created $U"
fi
chmod 0700 /home/$U
getent group docker >/dev/null && usermod -aG docker "$U" || echo "no docker group, skipped"
install -d -m 700 -o "$U" -g "$U" /home/$U/.ssh
printf '%s\n' "$KEY" > /home/$U/.ssh/authorized_keys
chown "$U:$U" /home/$U/.ssh/authorized_keys; chmod 600 /home/$U/.ssh/authorized_keys
f=/etc/sudoers.d/$U
printf 'Defaults:%s log_output\n%s ALL=(ALL) NOPASSWD:ALL\n' "$U" "$U" > "$f.tmp"
printf '%s\n' '# Bulk data movers: keep the audit line, do not record the bytes (eshpfi playbooks/sudoers-infra-ops-bulk-no-log-output.yaml)' \
'Cmnd_Alias BULK_DATA = /usr/bin/rsync, /usr/bin/tar, /usr/bin/cat, /usr/bin/dd, /usr/bin/zstd, /usr/bin/zcat, /usr/bin/gzip, /usr/bin/pv, /usr/bin/docker save *, /usr/bin/docker export *, /usr/bin/docker cp *' \
'Defaults!BULK_DATA !log_output' >> "$f.tmp"
chmod 440 "$f.tmp"
if visudo -cf "$f.tmp"; then mv "$f.tmp" "$f"; else rm -f "$f.tmp"; echo "VISUDO VALIDATION FAILED"; exit 1; fi
id "$U"; stat -c '%a %U %n' /home/$U /home/$U/.ssh /home/$U/.ssh/authorized_keys "$f"
+1 -1
View File
@@ -60,7 +60,7 @@ Media services on this box sit at `10.0.50.56` (Plex) and `10.0.50.57` (Jellyfin
rebooted this node without accounting for it. Before any planned reboot of either rebooted this node without accounting for it. Before any planned reboot of either
node, either accept the read-only window on the survivor or set node, either accept the read-only window on the survivor or set
`pvecm expected 1` on it for the duration. Discovered 2026-08-18. `pvecm expected 1` on it for the duration. Discovered 2026-08-18.
- ⚠ **CT 103 `esh-nas` (10.0.50.50) runs on THIS host and serves `hard` NFS.** - ⚠ **CT 103 `esh-nas` (10.0.50.50) runs on THIS host and serves `hard` NFS.** Since 2026-10-13 it has the `infra-ops` identity (uid 850, NOPASSWD sudo, Prime's ruling): `ssh infra-ops@10.0.50.50` works directly. Before that, the only way in was `pct exec 103` from this host.
Never reboot this host casually — quiesce the clients first. Measured from the Never reboot this host casually — quiesce the clients first. Measured from the
server on 2026-08-18 (`ss -tn '( sport = :2049 )'` inside CT 103), there are server on 2026-08-18 (`ss -tn '( sport = :2049 )'` inside CT 103), there are
**five** clients, not the two long documented here: **five** clients, not the two long documented here: