ansible/scripts/bootstrap-root-ssh-su-password.sh
ilia de49b34cdc
Some checks failed
CI / skip-ci-check (pull_request) Successful in 6s
CI / lint-and-test (pull_request) Failing after 9s
CI / ansible-validation (pull_request) Failing after 6s
CI / secret-scanning (pull_request) Successful in 5s
CI / dependency-scan (pull_request) Successful in 8s
CI / sast-scan (pull_request) Failing after 5s
CI / license-check (pull_request) Successful in 11s
CI / vault-check (pull_request) Failing after 6s
CI / playbook-test (pull_request) Failing after 6s
CI / container-scan (pull_request) Failing after 6s
CI / sonar-analysis (pull_request) Failing after 2s
CI / workflow-summary (pull_request) Successful in 4s
Add homelab monitoring, portfolio site, and vault tooling.
Document pve10 static IPs, monitoring stack, and site LXCs; add portfolio
to inventory; Mailcow mailbox automation; vault import/export scripts;
security audit guides and UniFi DHCP reference.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 16:25:07 -04:00

61 lines
2.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Bootstrap root SSH when `su` needs a password (no sudo on host).
# Usage: BOOTSTRAP_SU_PASSWORD='...' ./scripts/bootstrap-root-ssh-su-password.sh HOST
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
HOST="${1:-}"
BOOTSTRAP_USER="${BOOTSTRAP_USER:-ladmin}"
PUBKEY_FILE="${SSH_PUBLIC_KEY:-${HOME}/.ssh/id_ed25519.pub}"
SU_PASSWORD="${BOOTSTRAP_SU_PASSWORD:-}"
[[ -n "${HOST}" ]] || { echo "Usage: $0 HOST" >&2; exit 1; }
[[ -n "${SU_PASSWORD}" ]] || { echo "Set BOOTSTRAP_SU_PASSWORD" >&2; exit 1; }
[[ -f "${PUBKEY_FILE}" ]] || { echo "Missing ${PUBKEY_FILE}" >&2; exit 1; }
IP="$(awk -v h="${HOST}" '$1==h {for(i=2;i<=NF;i++) if($i~/^ansible_host=/) {sub(/ansible_host=/,"",$i); print $i; exit}}' \
"${REPO_ROOT}/inventories/production/hosts")"
[[ -n "${IP}" ]] || { echo "No ansible_host for ${HOST}" >&2; exit 1; }
PUBKEY="$(cat "${PUBKEY_FILE}")"
export IP BOOTSTRAP_USER SU_PASSWORD PUBKEY
/usr/bin/expect <<'EXPECT'
set timeout 60
spawn ssh -o StrictHostKeyChecking=accept-new $env(BOOTSTRAP_USER)@$env(IP)
expect {
-re {[$#] $} { }
timeout { exit 1 }
}
send "su -\r"
expect {
"Password:" {
send "$env(SU_PASSWORD)\r"
}
timeout { exit 1 }
}
expect {
-re {root@caddy|#||[$#] $} { }
timeout { exit 1 }
}
send "bash --noprofile --norc\r"
expect {
-re {# $} { }
timeout { exit 1 }
}
send "mkdir -p /root/.ssh && chmod 700 /root/.ssh && touch /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys\r"
expect -re {# $}
send "grep -qF '$env(PUBKEY)' /root/.ssh/authorized_keys || echo '$env(PUBKEY)' >> /root/.ssh/authorized_keys\r"
expect -re {# $}
send "sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config 2>/dev/null || echo PermitRootLogin prohibit-password >> /etc/ssh/sshd_config\r"
expect -re {# $}
send "systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null || true\r"
expect -re {# $}
send "exit\r"
expect eof
EXPECT
ssh -o BatchMode=yes -i "${PUBKEY_FILE}" -o ConnectTimeout=10 \
"root@${IP}" "echo OK: root@${IP}"
echo "Done: root key on ${HOST}"