Skip to content

Instantly share code, notes, and snippets.

@ivan-leschinsky
Last active January 26, 2022 19:04
Show Gist options
  • Save ivan-leschinsky/36e6c6508a042f6ae269cf6a1ee78e07 to your computer and use it in GitHub Desktop.
Save ivan-leschinsky/36e6c6508a042f6ae269cf6a1ee78e07 to your computer and use it in GitHub Desktop.
proxmox ha install

New Proxmox VM with Home Assistant

This script will create a new Proxmox VM with the latest version of Home Assistant. To create a new VM, run the following in a SSH session or the console from Proxmox interface

bash -c "$(wget -qLO - https://github.com/whiskerz007/proxmox_hassos_install/raw/master/install.sh)"

After script completes, click on the new VM (the script will tell you the ID), click on the Hardware tab for the VM and change the Memory and Processors settings to what you desire. The Hard Disk can be expanded by clicking on it, then click on the Resize disk button above (Note: additional steps must be taken for storage to take effect in the VM after the first boot). The network MAC address can be changed by selecting Network Device and clicking Edit above. Once all changes have been made, click Start above.

Root Prompt

To get to the root prompt

  • Open the console after the VM has been started
  • When the messages slow down press the Enter key a couple of times until you see the following

Welcome to Home Assistant
homeassistant login:
  • Login using root, no password is requested
  • When you see the hassio > prompt, type login
  • You should now see a # prompt.

Add a serial port

By adding a serial port, you are able to use a different interface to interact with the VM. When you click on the down arrow next to Console you will be able to use xterm.js which enables you to Right-Click and get access to Copy and Paste functions. If the serial port was already added by the install script, no further actions are required to enable the functionality.

  • Click on the VM in the list of containers at the left side panel
  • Click Hardware tab located beside the list of containers
  • Click Add located beside Summary tab, then click Serial Port
  • Serial Port should be set to 0 in the input box, then click Add
  • Start the VM, if it isn't already
  • At the root prompt type sed -i 's/$/ console=ttyS0/' /mnt/boot/cmdline.txt
  • A Shutdown and Start is required for the changes to take effect

Show Current IP Address

To get the current IP address assigned to the VM from the Proxmox interface

  • Click on the VM in the list of containers at the left side panel
  • Click Summary tab located beside the list of containers
  • Click More near IPs in the top left section
  • You can find the assigned IP addresses on the line with the name similar to enp0s18

To get the current IP address assigned to the VM from the command line

  • At the root prompt type nmcli -g ip4.address d sh $(nmcli -g device c)
  • The response will be the IP address with subnet mask or nothing

Note: If DHCP is configured and nothing is shown, check DHCP server and VM network settings

Configure Network for Static IP Address

To set a static IP address, use the following as an example

  • At the root prompt type nmcli c mod $(nmcli -g uuid c) ipv4.method manual ipv4.addresses "192.168.20.170/24" ipv4.gateway "192.168.20.1" ipv4.dns "8.8.8.8,8.8.4.4"
  • At the root prompt type nmcli c up $(nmcli -g uuid c)

Configure Network for DHCP

To remove all static IP addresses and enable DHCP

  • At the root prompt type nmcli c mod $(nmcli -g uuid c) ipv4.method auto ipv4.addresses "" ipv4.gateway "" ipv4.dns ""
  • At the root prompt type nmcli c up $(nmcli -g uuid c)

Default Interface Name

To get the default interface name

  • At the root prompt type nmcli -g device c
  • The response with be the interface name

Change Hostname

To change the HassOS VM hostname

  • At the root prompt type hostnamectl set-hostname your-new-hostname
  • You can verify the change by logging out with exit, the last line printed will be your-new-hostname login:

Resize Disk

To resize the disk after the first boot

  • At the root prompt type df -h /dev/sda8 and note the Size
  • Shutdown the VM
  • Resize the disk to the desired size
  • At the root prompt type sgdisk -e /dev/sda
  • At the root prompt type reboot
  • Verify resize was successful by typing df -h /dev/sda8 at the root prompt
#!/usr/bin/env bash
# original: bash -c "$(wget -qLO - https://github.com/whiskerz007/proxmox_hassos_install/raw/master/install.sh)"
# mine: bash -c "$(wget -qLO - https://gist.github.com/ivan-leschinsky/36e6c6508a042f6ae269cf6a1ee78e07/raw/d1dccdf358b25f77d004af258e9746e73f780f31/hainstall.sh)"
# Setup script environment
set -o errexit #Exit immediately if a pipeline returns a non-zero status
set -o errtrace #Trap ERR from shell functions, command substitutions, and commands from subshell
set -o nounset #Treat unset variables as an error
set -o pipefail #Pipe will exit with last non-zero status if applicable
shopt -s expand_aliases
alias die='EXIT=$? LINE=$LINENO error_exit'
trap die ERR
trap cleanup EXIT
function error_exit() {
trap - ERR
local DEFAULT='Unknown failure occured.'
local REASON="\e[97m${1:-$DEFAULT}\e[39m"
local FLAG="\e[91m[ERROR] \e[93m$EXIT@$LINE"
msg "$FLAG $REASON"
[ ! -z ${VMID-} ] && cleanup_vmid
exit $EXIT
}
function warn() {
local REASON="\e[97m$1\e[39m"
local FLAG="\e[93m[WARNING]\e[39m"
msg "$FLAG $REASON"
}
function info() {
local REASON="$1"
local FLAG="\e[36m[INFO]\e[39m"
msg "$FLAG $REASON"
}
function msg() {
local TEXT="$1"
echo -e "$TEXT"
}
function cleanup_vmid() {
if $(qm status $VMID &>/dev/null); then
if [ "$(qm status $VMID | awk '{print $2}')" == "running" ]; then
qm stop $VMID
fi
qm destroy $VMID
fi
}
function cleanup() {
popd >/dev/null
rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
# Select storage location
while read -r line; do
TAG=$(echo $line | awk '{print $1}')
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
fi
STORAGE_MENU+=( "$TAG" "$ITEM" "OFF" )
done < <(pvesm status -content images | awk 'NR>1')
if [ $((${#STORAGE_MENU[@]}/3)) -eq 0 ]; then
warn "'Disk image' needs to be selected for at least one storage location."
die "Unable to detect valid storage location."
elif [ $((${#STORAGE_MENU[@]}/3)) -eq 1 ]; then
STORAGE=${STORAGE_MENU[0]}
else
while [ -z "${STORAGE:+x}" ]; do
STORAGE=$(whiptail --title "Storage Pools" --radiolist \
"Which storage pool you would like to use for the container?\n\n" \
16 $(($MSG_MAX_LENGTH + 23)) 6 \
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
done
fi
info "Using '$STORAGE' for storage location."
# Get the next guest VM/LXC ID
VMID=$(pvesh get /cluster/nextid)
info "Container ID is $VMID."
# Get latest Home Assistant disk image archive URL
msg "Getting URL for latest Home Assistant disk image..."
RELEASE_TYPE=vmdk
URL=$(cat<<EOF | python3
import requests
url = "https://api.github.com/repos/home-assistant/operating-system/releases"
r = requests.get(url).json()
if "message" in r:
exit()
for release in r:
if release["prerelease"]:
continue
for asset in release["assets"]:
if asset["name"].find("$RELEASE_TYPE") != -1:
image_url = asset["browser_download_url"]
print(image_url)
exit()
EOF
)
if [ -z "$URL" ]; then
die "Github has returned an error. A rate limit may have been applied to your connection."
fi
# Download Home Assistant disk image archive
msg "Downloading disk image..."
wget -q --show-progress $URL
echo -en "\e[1A\e[0K" #Overwrite output from wget
FILE=$(basename $URL)
# Extract Home Assistant disk image
msg "Extracting disk image..."
case $FILE in
*"gz") gunzip -f $FILE;;
*"zip") unzip -o $FILE;;
*"xz") xz -d $FILE;;
*) die "Unable to handle file extension '${FILE##*.}'.";;
esac
# Create variables for container disk
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
if [ "$STORAGE_TYPE" = "dir" ]; then
DISK_EXT=".qcow2"
DISK_REF="$VMID/"
IMPORT_OPT="-format qcow2"
fi
for i in {0,1}; do
disk="DISK$i"
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
# Create VM
msg "Creating VM..."
VM_NAME=$(sed -e "s/\_//g" -e "s/.${RELEASE_TYPE}.*$//" <<< $FILE)
qm create $VMID -agent 1 -bios ovmf -name $VM_NAME -net0 virtio,bridge=vmbr0 \
-onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 128 1>&/dev/null
qm importdisk $VMID ${FILE%.*} $STORAGE ${IMPORT_OPT:-} 1>&/dev/null
qm set $VMID \
-efidisk0 ${DISK0_REF},size=128K \
-sata0 ${DISK1_REF},size=6G > /dev/null
qm set $VMID \
-boot order=sata0 > /dev/null
# Add serial port and enable console output
set +o errtrace
(
msg "Adding serial port and configuring console..."
trap '
warn "Unable to configure serial port. VM is still functional."
if [ "$(qm config $VMID | sed -n ''/serial0/p'')" != "" ]; then
qm set $VMID --delete serial0 >/dev/null
fi
exit
' ERR
if [ "$(command -v kpartx)" = "" ]; then
msg "Installing 'kpartx'..."
apt-get update >/dev/null
apt-get -qqy install kpartx &>/dev/null
fi
DISK1_PATH="$(pvesm path $DISK1_REF)"
DISK1_PART1="$(kpartx -al $DISK1_PATH | awk 'NR==1 {print $1}')"
DISK1_PART1_PATH="/dev/mapper/$DISK1_PART1"
TEMP_MOUNT="${TEMP_DIR}/mnt"
trap '
findmnt $TEMP_MOUNT >/dev/null && umount $TEMP_MOUNT
command -v kpartx >/dev/null && kpartx -d $DISK1_PATH
' EXIT
kpartx -a $DISK1_PATH
mkdir $TEMP_MOUNT
mount $DISK1_PART1_PATH $TEMP_MOUNT
sed -i 's/$/ console=ttyS0/' ${TEMP_MOUNT}/cmdline.txt
qm set $VMID -serial0 socket >/dev/null
)
info "Completed Successfully! New VM ID is \e[1m$VMID\e[0m."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment