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
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>
61 lines
2.0 KiB
Bash
Executable File
61 lines
2.0 KiB
Bash
Executable File
#!/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}"
|