Skip to content

Instantly share code, notes, and snippets.

@pbootly
Created January 30, 2026 00:05
Show Gist options
  • Select an option

  • Save pbootly/7e4360a403d5ec6d057e5e3a11bdccc2 to your computer and use it in GitHub Desktop.

Select an option

Save pbootly/7e4360a403d5ec6d057e5e3a11bdccc2 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Simple helper script to automatically start and ssh
# to a UTM VM. Requires ssh setup on machine prior
# requires:
# - utmctl in path or passed with -b
# - fzf binary in path for selection
UTMCTL="utmctl"
SSH_USER="root"
usage() {
cat <<EOF
Usage: $0 [-b utmctl_binary] [-u ssh_user]
-b Path to utmctl binary (default: utmctl)
-u SSH username (default: root)
-h Show this help message
EOF
exit 1
}
while getopts ":b:u:h" opt; do
case $opt in
b) UTMCTL="$OPTARG" ;;
u) SSH_USER="$OPTARG" ;;
h) usage ;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
command -v "$UTMCTL" >/dev/null 2>&1 || {
echo "Error: $UTMCTL not found in PATH"
exit 1
}
VM_NAME=$("$UTMCTL" list 2>/dev/null |
tail -n +2 |
awk '{print $3}' |
fzf --prompt="Select a VM: ")
[ -z "$VM_NAME" ] && {
echo "You chose nothing"
exit 1
}
"$UTMCTL" start "$VM_NAME" >/dev/null 2>&1 || echo "VM already running or failed to start"
for i in {1..20}; do
IP=$("$UTMCTL" ip-address "$VM_NAME" 2>/dev/null | head -n1)
[ -n "$IP" ] && break || echo "No IP found for machine, retry $i..." && sleep 1
done
[ -z "$IP" ] && {
echo "Unable to get VM IP, check network settings"
exit 1
}
echo "Found IP: $IP, connecting..." && ssh "$SSH_USER@$IP"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment