- Add .gitignore: exclude compiled binaries, build artifacts, and Helm values files containing real secrets (authentik, prometheus) - Add all Kubernetes deployment manifests (deployment/) - Add services source code: ha-sync, device-inventory, games-console, paperclip, parts-inventory - Add Ansible orchestration: playbooks, roles, inventory, cloud-init - Add hardware specs, execution plans, scripts, HOMELAB.md - Add skills/homelab/SKILL.md + skills/install.sh to preserve Copilot skill - Remove previously-tracked inventory-cli binary from git index Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
97 lines
2.8 KiB
Bash
Executable file
97 lines
2.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
PROXMOX_HOST="${PROXMOX_HOST:-root@192.168.2.193}"
|
|
PROXMOX_SNIPPET_STORAGE="${PROXMOX_SNIPPET_STORAGE:-local}"
|
|
PROXMOX_CLOUDINIT_STORAGE="${PROXMOX_CLOUDINIT_STORAGE:-local-lvm}"
|
|
CI_USER="${CI_USER:-dan}"
|
|
KEYS_FILE="${KEYS_FILE:-./cloud-init/authorized_keys}"
|
|
VMIDS="${VMIDS:-100 102 103 104 105}"
|
|
|
|
if [[ ! -f "${KEYS_FILE}" ]]; then
|
|
echo "Keys file not found: ${KEYS_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
TMP_USER_DATA="$(mktemp)"
|
|
TMP_KEYS="$(mktemp)"
|
|
cleanup() {
|
|
rm -f "${TMP_USER_DATA}"
|
|
rm -f "${TMP_KEYS}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
ssh -o StrictHostKeyChecking=no "${PROXMOX_HOST}" 'mkdir -p /var/lib/vz/snippets'
|
|
|
|
tr -d '\r' < "${KEYS_FILE}" | awk '
|
|
/^[[:space:]]*#/ {next}
|
|
/^[[:space:]]*$/ {next}
|
|
{
|
|
keytype=$1
|
|
keydata=$2
|
|
if (keytype ~ /^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|sk-ssh-ed25519@openssh.com|sk-ecdsa-sha2-nistp256@openssh.com)$/ && keydata != "") {
|
|
print $0
|
|
}
|
|
}
|
|
' > "${TMP_KEYS}"
|
|
|
|
if [[ ! -s "${TMP_KEYS}" ]]; then
|
|
echo "No valid SSH public keys found in ${KEYS_FILE}."
|
|
exit 1
|
|
fi
|
|
|
|
VALID_KEYS="$(cat "${TMP_KEYS}")"
|
|
|
|
{
|
|
echo "#cloud-config"
|
|
echo "users:"
|
|
echo " - default"
|
|
echo " - name: ${CI_USER}"
|
|
echo " groups: sudo"
|
|
echo " shell: /bin/bash"
|
|
echo " sudo: ALL=(ALL) NOPASSWD:ALL"
|
|
echo " lock_passwd: true"
|
|
echo " ssh_authorized_keys:"
|
|
while IFS= read -r key; do
|
|
[[ -z "${key}" ]] && continue
|
|
echo " - ${key}"
|
|
done <<< "${VALID_KEYS}"
|
|
echo "ssh_pwauth: false"
|
|
echo "disable_root: false"
|
|
echo "package_update: true"
|
|
} > "${TMP_USER_DATA}"
|
|
|
|
scp -q -o StrictHostKeyChecking=no "${TMP_KEYS}" "${PROXMOX_HOST}:/var/lib/vz/snippets/homelab-authorized_keys"
|
|
scp -q -o StrictHostKeyChecking=no "${TMP_USER_DATA}" "${PROXMOX_HOST}:/var/lib/vz/snippets/homelab-user-data.yaml"
|
|
|
|
ssh -o StrictHostKeyChecking=no "${PROXMOX_HOST}" bash <<EOF
|
|
set -euo pipefail
|
|
|
|
for vmid in ${VMIDS}; do
|
|
if ! qm status "\${vmid}" >/dev/null 2>&1; then
|
|
echo "[skip] VMID \${vmid} does not exist"
|
|
continue
|
|
fi
|
|
|
|
ostype="\$(qm config "\${vmid}" | awk -F': ' '/^ostype:/ {print \$2}')"
|
|
if [[ "\${ostype}" == win* ]]; then
|
|
echo "[skip] VMID \${vmid} is Windows (ostype=\${ostype})"
|
|
continue
|
|
fi
|
|
|
|
if ! qm config "\${vmid}" | grep -q 'cloudinit'; then
|
|
qm set "\${vmid}" --ide2 "${PROXMOX_CLOUDINIT_STORAGE}:cloudinit" >/dev/null
|
|
fi
|
|
|
|
qm set "\${vmid}" \
|
|
--ciuser "${CI_USER}" \
|
|
--sshkeys /var/lib/vz/snippets/homelab-authorized_keys \
|
|
--cicustom "user=${PROXMOX_SNIPPET_STORAGE}:snippets/homelab-user-data.yaml" >/dev/null
|
|
|
|
qm cloudinit update "\${vmid}" >/dev/null || true
|
|
echo "[ok] Applied cloud-init key baseline to VMID \${vmid}"
|
|
done
|
|
EOF
|
|
|
|
echo "Done. Cloud-init baseline applied to VMIDs: ${VMIDS}"
|
|
echo "Note: Existing guests usually need a reboot to consume updated cloud-init metadata."
|