#!/usr/bin/env bash # authorized_keys aus docu/shared/ssh deployen set -euo pipefail DOCU_ROOT="${DOCU_ROOT:-/root/docu}" SSH_DIR="$DOCU_ROOT/shared/ssh" DRY_RUN=0 TARGET="" DEST="" REMOTE="" CT_IDS=() usage() { cat <<'EOF' Usage: install-authorized-keys.sh [options] Targets: proxmox-root → /root/.ssh/authorized_keys auf Proxmox-Hosts vm101-jean → jean@192.168.10.10 ~/.ssh/authorized_keys pve2-lxc-root → root in CTs auf pve2 (101 docker, 109 media, 110 aidev) horus-root → root@10.1.1.1 (Horus VPS, nur via WireGuard — Springt über VM 101) Options: --dest PATH Lokale Zieldatei (nur proxmox-root, default: /root/.ssh/authorized_keys) --remote USER@HOST Auf Remote-Host installieren (proxmox-root / vm101-jean / horus-root) --jump USER@HOST Sprung-Host für horus-root (default: jean@192.168.10.10) --ct VMID Nur einen CT (pve2-lxc-root, mehrfach möglich) --dry-run Nur anzeigen, nicht schreiben -h Hilfe Beispiele: ./install-authorized-keys.sh proxmox-root ./install-authorized-keys.sh --remote root@192.168.10.5 proxmox-root ./install-authorized-keys.sh vm101-jean ./install-authorized-keys.sh pve2-lxc-root --ct 101 ./install-authorized-keys.sh horus-root EOF } JUMP="" log() { printf '%s\n' "$*"; } run() { if (( DRY_RUN )); then log "[dry-run] $*" else "$@" fi } install_local_file() { local src="$1" dest="$2" run mkdir -p "$(dirname "$dest")" run chmod 700 "$(dirname "$dest")" if (( DRY_RUN )); then log "[dry-run] cp $src → $dest" head -3 "$src" log "… ($(wc -l <"$src") Zeilen)" else install -m 600 -o root -g root "$src" "$dest" log "Installiert: $dest ($(wc -l <"$dest") Keys)" fi } install_remote() { local src="$1" remote="$2" dest="$3" if (( DRY_RUN )); then log "[dry-run] ssh $remote install -m 600 … ← $src" return fi ssh "$remote" "mkdir -p $(dirname "$dest") && chmod 700 $(dirname "$dest")" scp -q "$src" "$remote:/tmp/authorized_keys.new" ssh "$remote" "install -m 600 -o \$(id -un) -g \$(id -gn) /tmp/authorized_keys.new '$dest' && rm -f /tmp/authorized_keys.new" log "Installiert auf $remote:$dest" } install_remote_via_jump() { local src="$1" jump="$2" remote="$3" dest="$4" if (( DRY_RUN )); then log "[dry-run] $jump → $remote → $dest ← $src" return fi scp -q "$src" "$jump:/tmp/authorized_keys.new" ssh "$jump" "scp -q /tmp/authorized_keys.new ${remote}:/tmp/authorized_keys.new && ssh -o BatchMode=yes ${remote} 'mkdir -p /root/.ssh && chmod 700 /root/.ssh && install -m 600 /tmp/authorized_keys.new ${dest} && rm -f /tmp/authorized_keys.new' && rm -f /tmp/authorized_keys.new" log "Installiert auf $remote:$dest (via $jump)" } install_pve2_ct() { local src="$1" vmid="$2" if (( DRY_RUN )); then log "[dry-run] pct exec $vmid → /root/.ssh/authorized_keys" return fi pct exec "$vmid" -- mkdir -p /root/.ssh pct exec "$vmid" -- chmod 700 /root/.ssh pct push "$vmid" "$src" /root/.ssh/authorized_keys pct exec "$vmid" -- chmod 600 /root/.ssh/authorized_keys log "CT $vmid: /root/.ssh/authorized_keys ($(wc -l <"$src") Keys)" } while [[ $# -gt 0 ]]; do case "$1" in --dest) DEST="$2"; shift 2 ;; --remote) REMOTE="$2"; shift 2 ;; --jump) JUMP="$2"; shift 2 ;; --ct) CT_IDS+=("$2"); shift 2 ;; --dry-run) DRY_RUN=1; shift ;; -h|--help) usage; exit 0 ;; -*) echo "Unbekannte Option: $1" >&2; usage >&2; exit 1 ;; *) TARGET="$1"; shift ;; esac done [[ -n "$TARGET" ]] || { usage >&2; exit 1; } [[ -d "$SSH_DIR/assembled" ]] || { echo "Fehlt: $SSH_DIR (git pull?)" >&2; exit 1; } case "$TARGET" in proxmox-root) SRC="$SSH_DIR/assembled/proxmox-root.pub" DEST="${DEST:-/root/.ssh/authorized_keys}" if [[ -n "$REMOTE" ]]; then install_remote "$SRC" "$REMOTE" "$DEST" else install_local_file "$SRC" "$DEST" fi ;; vm101-jean) SRC="$SSH_DIR/assembled/vm101-jean.pub" DEST="${DEST:-/home/jean/.ssh/authorized_keys}" REMOTE="${REMOTE:-jean@192.168.10.10}" install_remote "$SRC" "$REMOTE" "$DEST" ;; pve2-lxc-root) SRC="$SSH_DIR/assembled/pve2-lxc-root.pub" if [[ ${#CT_IDS[@]} -eq 0 ]]; then CT_IDS=(101 109 110) fi for vmid in "${CT_IDS[@]}"; do install_pve2_ct "$SRC" "$vmid" done ;; horus-root) SRC="$SSH_DIR/assembled/horus-root.pub" DEST="${DEST:-/root/.ssh/authorized_keys}" JUMP="${JUMP:-jean@192.168.10.10}" REMOTE="${REMOTE:-root@10.1.1.1}" install_remote_via_jump "$SRC" "$JUMP" "$REMOTE" "$DEST" ;; *) echo "Unbekanntes Target: $TARGET" >&2 usage >&2 exit 1 ;; esac