From 2c348d4d94fc7b61568cd5fe16e2e12dc6337bf1 Mon Sep 17 00:00:00 2001 From: CanbiZ <47820557+MickLesk@users.noreply.github.com> Date: Wed, 7 Jan 2026 17:23:36 +0100 Subject: [PATCH] Automate VM provisioning via serial console Replaces SSH-based installation with serial console automation using a new send_line_to_vm function. The script now logs in, installs Podman, downloads and installs UniFi OS Server, and retrieves the VM IP address directly via the console. This simplifies the process and removes SSH and sshpass dependencies. --- vm/unifi-os-server-vm.sh | 239 ++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 117 deletions(-) diff --git a/vm/unifi-os-server-vm.sh b/vm/unifi-os-server-vm.sh index 7ea19eb4f..134a8b9ad 100644 --- a/vm/unifi-os-server-vm.sh +++ b/vm/unifi-os-server-vm.sh @@ -107,6 +107,77 @@ function cleanup_vmid() { fi } +function send_line_to_vm() { + local line="$1" + echo -e "${DGN}Sending: ${YW}${line}${CL}" + for ((i = 0; i < ${#line}; i++)); do + character=${line:i:1} + case $character in + " ") character="spc" ;; + "-") character="minus" ;; + "=") character="equal" ;; + ",") character="comma" ;; + ".") character="dot" ;; + "/") character="slash" ;; + "'") character="apostrophe" ;; + ";") character="semicolon" ;; + '\') character="backslash" ;; + '\`') character="grave_accent" ;; + "[") character="bracket_left" ;; + "]") character="bracket_right" ;; + "_") character="shift-minus" ;; + "+") character="shift-equal" ;; + "?") character="shift-slash" ;; + "<") character="shift-comma" ;; + ">") character="shift-dot" ;; + '"') character="shift-apostrophe" ;; + ":") character="shift-semicolon" ;; + "|") character="shift-backslash" ;; + "~") character="shift-grave_accent" ;; + "{") character="shift-bracket_left" ;; + "}") character="shift-bracket_right" ;; + "A") character="shift-a" ;; + "B") character="shift-b" ;; + "C") character="shift-c" ;; + "D") character="shift-d" ;; + "E") character="shift-e" ;; + "F") character="shift-f" ;; + "G") character="shift-g" ;; + "H") character="shift-h" ;; + "I") character="shift-i" ;; + "J") character="shift-j" ;; + "K") character="shift-k" ;; + "L") character="shift-l" ;; + "M") character="shift-m" ;; + "N") character="shift-n" ;; + "O") character="shift-o" ;; + "P") character="shift-p" ;; + "Q") character="shift-q" ;; + "R") character="shift-r" ;; + "S") character="shift-s" ;; + "T") character="shift-t" ;; + "U") character="shift-u" ;; + "V") character="shift-v" ;; + "W") character="shift-w" ;; + "X") character="shift-x" ;; + "Y") character="shift-y" ;; + "Z") character="shift-z" ;; + "!") character="shift-1" ;; + "@") character="shift-2" ;; + "#") character="shift-3" ;; + '$') character="shift-4" ;; + "%") character="shift-5" ;; + "^") character="shift-6" ;; + "&") character="shift-7" ;; + "*") character="shift-8" ;; + "(") character="shift-9" ;; + ")") character="shift-0" ;; + esac + qm sendkey $VMID "$character" + done + qm sendkey $VMID ret +} + function cleanup() { popd >/dev/null post_update_to_api "done" "none" @@ -229,7 +300,7 @@ function select_os() { OS_DISPLAY="Ubuntu 24.04 LTS" ;; esac - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}" + #echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}" else exit-script fi @@ -238,14 +309,14 @@ function select_os() { function select_cloud_init() { # UniFi OS Server ALWAYS requires Cloud-Init for automated installation USE_CLOUD_INIT="yes" - echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (required for UniFi OS)${CL}" + #echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (required for UniFi OS)${CL}" } function get_image_url() { local arch=$(dpkg --print-architecture) case $OS_TYPE in debian) - # Always use generic (Cloud-Init) variant for UniFi OS + # Always use /dev/null | jq -r '.[1]["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | grep -v "127.0.0.1" | head -1 || echo "") - + VM_IP=$(qm guest cmd $VMID network-get-interfaces 2>/dev/null | jq -r '.[] | select(.name != "lo") | .["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | head -1 || echo "") if [ -n "$VM_IP" ]; then - msg_ok "VM IP Address: ${VM_IP}" break fi sleep 2 done - if [ -z "$VM_IP" ]; then - msg_error "Could not detect VM IP address" - echo -e "${TAB}${INFO}${YW}Use Proxmox Console to login with Cloud-Init credentials${CL}" - echo -e "${TAB}${INFO}${YW}User: ${BGN}${CLOUDINIT_USER:-root}${CL} / Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}" - exit 1 - fi - - # Wait for SSH to be ready - msg_info "Waiting for SSH to be ready" - SSH_READY=0 - for i in {1..30}; do - if timeout 5 sshpass -p "${CLOUDINIT_PASSWORD}" ssh -o ConnectTimeout=3 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ - "${CLOUDINIT_USER:-root}@${VM_IP}" "echo 'SSH Ready'" >/dev/null 2>&1; then - SSH_READY=1 - msg_ok "SSH connection ready" - break - fi - sleep 2 - done - - if [ $SSH_READY -eq 0 ]; then - msg_error "SSH connection failed" - echo -e "${TAB}${INFO}${YW}Manual login - User: ${BGN}${CLOUDINIT_USER:-root}${CL} / Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}" - exit 1 - fi - - # Check if sshpass is installed - if ! command -v sshpass &>/dev/null; then - msg_info "Installing sshpass for automated SSH" - apt-get update -qq >/dev/null 2>&1 - apt-get install -y sshpass -qq >/dev/null 2>&1 - fi - - # Execute UniFi OS installation directly via SSH - msg_info "Installing UniFi OS Server ${UOS_VERSION} (takes 4-6 minutes)" - - # Create installation script - INSTALL_SCRIPT=$( - cat <<'EOFINSTALL' -#!/bin/bash -set -e -export DEBIAN_FRONTEND=noninteractive - -echo "[1/5] Updating system packages..." -apt-get update -qq -apt-get install -y curl wget ca-certificates podman uidmap slirp4netns iptables -qq - -echo "[2/5] Configuring Podman..." -loginctl enable-linger root - -echo "[3/5] Downloading UniFi OS Server installer..." -cd /root -curl -fsSL "UNIFI_URL" -o unifi-installer.bin -chmod +x unifi-installer.bin - -echo "[4/5] Installing UniFi OS Server (this takes 3-5 minutes)..." -./unifi-installer.bin install - -echo "[5/5] Starting UniFi OS Server..." -sleep 15 - -if systemctl list-unit-files | grep -q unifi-os-server; then - systemctl enable unifi-os-server - systemctl start unifi-os-server - sleep 10 - - if systemctl is-active --quiet unifi-os-server; then - echo "✓ UniFi OS Server is running" + if [ -n "$VM_IP" ]; then + msg_ok "VM IP Address: ${VM_IP}" else - echo "⚠ Service status:" - systemctl status unifi-os-server --no-pager || true + msg_info "IP address will be shown in VM console" + send_line_to_vm "ip -4 addr show | grep inet | grep -v 127.0.0.1" fi -fi - -echo "Installation completed!" -EOFINSTALL - ) - - # Replace URL placeholder - INSTALL_SCRIPT="${INSTALL_SCRIPT//UNIFI_URL/$UOS_URL}" - - # Execute installation via SSH (with output streaming) - if sshpass -p "${CLOUDINIT_PASSWORD}" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ - "${CLOUDINIT_USER:-root}@${VM_IP}" "bash -s" <<<"$INSTALL_SCRIPT" 2>&1 | while IFS= read -r line; do - echo -e "${TAB}${DGN}${line}${CL}" - done; then - msg_ok "UniFi OS Server installed successfully" - else - msg_error "Installation failed" - echo -e "${TAB}${INFO}${YW}Check logs: ${BL}ssh ${CLOUDINIT_USER:-root}@${VM_IP}${CL}" - exit 1 - fi - - # Wait for UniFi OS web interface - msg_info "Waiting for UniFi OS web interface (port 11443)" - PORT_OPEN=0 - for i in {1..60}; do - if timeout 2 bash -c ">/dev/tcp/${VM_IP}/11443" 2>/dev/null; then - PORT_OPEN=1 - msg_ok "UniFi OS Server web interface is ready" - break - fi - sleep 2 - done echo "" - if [ $PORT_OPEN -eq 1 ]; then - echo -e "${TAB}${GATEWAY}${BOLD}${GN}✓ UniFi OS Server is ready!${CL}" + echo -e "${TAB}${GATEWAY}${BOLD}${GN}✓ UniFi OS Server installation complete!${CL}" + if [ -n "$VM_IP" ]; then echo -e "${TAB}${GATEWAY}${BOLD}${GN}✓ Access at: ${BGN}https://${VM_IP}:11443${CL}" else - echo -e "${TAB}${INFO}${YW}UniFi OS is installed but web interface not yet available${CL}" - echo -e "${TAB}${INFO}${YW}Access at: ${BGN}https://${VM_IP}:11443${CL} ${YW}(may take 1-2 more minutes)${CL}" + echo -e "${TAB}${INFO}${YW}Access via: ${BGN}https://:11443${CL}" fi - - echo -e "${TAB}${INFO}${DGN}SSH Access: ${BL}ssh ${CLOUDINIT_USER:-root}@${VM_IP}${CL}" - echo -e "${TAB}${INFO}${DGN}Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}" + echo -e "${TAB}${INFO}${DGN}Console login - User: ${BGN}root${CL} / Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}" + echo -e "${TAB}${INFO}${YW}Note: UniFi OS may take 1-2 more minutes to fully start${CL}" echo "" fi