Skip to content

Instantly share code, notes, and snippets.

@flanter21
Created March 8, 2025 12:17
Show Gist options
  • Save flanter21/de65cb0ddcb97678e9048f6f81ada237 to your computer and use it in GitHub Desktop.
Save flanter21/de65cb0ddcb97678e9048f6f81ada237 to your computer and use it in GitHub Desktop.
Automates the process at https://docs.getutm.app/guest-support/linux/ on distros based on Fedora, Alpine, Ubuntu or Arch. Should be POSIX-compliant.
#!/bin/sh
# Load functions
#. ./functions.sh
#!/bin/sh
# Check for systemd
checkSYSTEMD ( ) {
if command -v systemctl >/dev/null 2>&1; then
echo "true"
else
echo "false"
fi
}
# Ensure folders are being specified from root directory
checkOPTARG ( ) {
case "$OPTARG" in
"/"*) echo "$OPTARG" ;;
? ) echo "Invalid path $OPTARG"; exit ;;
esac
}
# Used to find package manager (will not return actual distro; eg. it will return debian when the distro is ubuntu)
getDIST ( ) {
if grep -q ^ID_LIKE= < /etc/os-release; then
grep ^ID_LIKE= < /etc/os-release | cut -d'=' -f2 -
elif grep -q ^ID= < /etc/os-release; then
grep ^ID= < /etc/os-release | cut -d'=' -f2 -
else
echo "Invalid"
fi
}
# Get appropriate package manager and refresh index
getPACINSTALL ( ) {
if [ "$distro" = "debian" ]; then
apt update
pacinstall="apt install -y "
elif [ "$distro" = "fedora" ]; then
dnf update
pacinstall="dnf -y install "
elif [ "$distro" = "arch" ]; then
pacinstall="pacman -Sy "
elif [ "$distro" = "alpine" ]; then
apk update
pacinstall="apk add "
fi
}
reloadFOLDERS ( ) {
mount -a
if [ "$systemd" = "true" ]; then systemctl daemon-reload; fi
}
# Defaults
mntr="/mnt/utm" # Shared folder (read-only) location
mntw="/media/utm" # Shared folder (read-write) location
fstab="/etc/fstab" # fstab location
systemd=$(checkSYSTEMD)
installdeps=true
distro=$(getDIST)
# Process arguments
while getopts ":d:f:hio:r:t" opt; do
case ${opt} in
d ) distro="$OPTARG" ;;
f ) fstab=$(checkOPTARG) ;; # Set fstab
h ) echo "helo " ;; # Help
i ) installdeps=false ;;
o ) mntw=$(checkOPTARG) ;; # Where to mount bindfs filesystem
r ) mntr=$(checkOPTARG) ;; # Where to mount 9fs filesystem
t ) fstab="/dev/null" ;;
? ) echo "Invalid option -$OPTARG"; exit ;;
esac
done
# Check if distro is supported
case "$distro" in
debian|fedora|arch|alpine ) ;;
? ) echo "Your distro, $distro appears to be unsupported. If your distro shares a package manager with one of: debian, fedora, arch, alpine - specify this manually using -d."; exit ;;
esac
# Install dependencies
if [ "$installdeps" = "true" ]; then
getPACINSTALL
packages="spice-vdagent qemu-guest-agent bindfs"
if [ "$distro" = "alpine" ]; then
printf "WARNINGS: On Alpine\n1) ensure community repos are enabled.\n2)Bindfs is currently only available on edge/testing, so it might not be reliable"
$pacinstall bindfs --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing/
packages="$packages spice-vdagent-openrc qemu-guest-agent-openrc virtiofsd"
rc-update add qemu-guest-agent
rc-update add spice-vdagentd
fi
$pacinstall $packages
fi
mkdir -p $mntr $mntw # Make target directories
if [ -f $fstab ] || [ $fstab = "/dev/null" ]; then
# Check that target folders are available
if grep -q "$mntr" < $fstab || grep -q "$mntw" < $fstab; then
echo "Something is already defined to mount at $mntr or $mntw"; exit
fi
# Add shared folder to fstab
ro="\n# UTM Shared Folder\nshare $mntr 9p trans=virtio,version=9p2000.L,rw,_netdev,nofail,auto 0 0"
printf "$ro"
printf "$ro" >> $fstab
# Mount shared folder
reloadFOLDERS
# Get UID and GID of host
utmUID=$(stat -c %u $mntr)
utmGID=$(stat -c %g $mntr)
userUID=1000
userGID=1000
rw="\n# bindfs mount to remap UID/GID\n$mntr $mntw fuse.bindfs map=$utmUID/$userUID:@$utmGID/@$userGID,"
if [ "$systemd" = "true" ]; then rw="${rw}x-systemd.requires=$mntr,"; fi
rw="${rw}_netdev,nofail,auto 0 0"
printf "$rw"
printf "$rw" >> $fstab
reloadFOLDERS
else
echo "$fstab was not found or was not a file."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment