This is convenient for app launch wrappers that would want to set their own default command but still allow overriding it
211 lines
6.7 KiB
Bash
Executable file
211 lines
6.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
SCRIPT_PATH=$(dirname $(realpath -s $0))
|
|
MUVM_PATH=$(dirname $(which muvm))
|
|
PASST_PATH=$(dirname $(which passt))
|
|
HOST_OPENGL_DRIVER=/run/opengl-driver
|
|
: "${MICROVM_DEFAULT_COMMAND:=bash}"
|
|
MICROVM_CLOSURE=
|
|
MICROVM_COMMAND=()
|
|
MICROVM_UID=1337
|
|
MICROVM_GID=1337
|
|
BWRAP_ARGS=()
|
|
MUVM_ARGS=()
|
|
GPU=1
|
|
WAYLAND=1
|
|
PIPEWIRE=1
|
|
X11=0
|
|
export TMP=/tmp TMPDIR=/tmp TEMP=/tmp TEMPDIR=/tmp LC_ALL=C
|
|
|
|
if [ ! -e "$HOST_OPENGL_DRIVER" ]; then
|
|
HOST_OPENGL_DRIVER="$FALLBACK_OPENGL_DRIVER"
|
|
fi
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
-u|--uid) MICROVM_UID="$2"; shift 2;;
|
|
-g|--gid) MICROVM_GID="$2"; shift 2;;
|
|
--no-gpu) GPU=0; shift 1;;
|
|
--no-wayland) WAYLAND=0; shift 1;;
|
|
--no-pipewire) PIPEWIRE=0; shift 1;;
|
|
--x11) X11=1; shift 1;;
|
|
--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;;
|
|
--ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;;
|
|
--expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;;
|
|
--ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); shift 2;;
|
|
--host-opengl-driver) HOST_OPENGL_DRIVER="$2"; shift 2;;
|
|
--munix-bin-dir) SCRIPT_PATH="$2"; shift 2;;
|
|
--muvm-bin-dir) MUVM_PATH="$2"; shift 2;;
|
|
--passt-bin-dir) PASST_PATH="$2"; shift 2;;
|
|
--) shift 1; MICROVM_COMMAND+=("$@"); break;;
|
|
-*) echo "munix: unknown option: $1" >&2; exit 1;;
|
|
*)
|
|
if [ "$MICROVM_CLOSURE" = "" ]; then
|
|
MICROVM_CLOSURE="$1"
|
|
else
|
|
MICROVM_COMMAND+=("$1")
|
|
fi
|
|
shift 1;;
|
|
esac
|
|
done
|
|
|
|
if [ "$MICROVM_CLOSURE" = "" ]; then
|
|
echo "munix: provide a system closure path as a positional argument" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$MUVM_PATH" = "" ]; then
|
|
echo "munix: muvm not found, provide a --muvm-bin-dir or fix \$PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$PASST_PATH" = "" ]; then
|
|
echo "munix: passt not found, provide a --passt-bin-dir or fix \$PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -e "$HOST_OPENGL_DRIVER" ]; then
|
|
echo "munix: host graphics driver not found, provide a --host-opengl-driver" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Resolve symlinks automatically
|
|
MICROVM_CLOSURE=$(realpath "$MICROVM_CLOSURE")
|
|
|
|
if [ ${#MICROVM_COMMAND[@]} -eq 0 ]; then
|
|
MICROVM_COMMAND=("$MICROVM_DEFAULT_COMMAND")
|
|
fi
|
|
|
|
if [ "$GPU" -eq 1 ]; then
|
|
BWRAP_ARGS+=(
|
|
"--dev-bind" "/dev/dri" "/dev/dri"
|
|
"--ro-bind" "$HOST_OPENGL_DRIVER" "/run/opengl-driver"
|
|
)
|
|
GPU_MODE=venus
|
|
kernel_ver="$(uname -r)"
|
|
kernel_ver_arr=(${kernel_ver//./ })
|
|
kernel_major="${kernel_ver_arr:-0}"
|
|
kernel_ver_arr=("${kernel_ver_arr[@]:1}")
|
|
kernel_minor="${kernel_ver_arr:-0}"
|
|
if [[ "$kernel_major" -gt 6 || ("$kernel_major" -eq 6 && "$kernel_minor" -gt 12) ]]; then
|
|
for card in /dev/dri/card*; do
|
|
driver_link="/sys/class/drm/${card##*/}/device/driver"
|
|
if [ -L "$driver_link" ]; then
|
|
driver_mod="$(readlink "$driver_link")"
|
|
driver_name="${driver_mod##*/}"
|
|
case "$driver_name" in
|
|
amdgpu|msm_dpu) # TODO: i915
|
|
echo "munix: ${card##*/} gpu driver is '$driver_name', using vdrm" >&2;
|
|
GPU_MODE=drm
|
|
break;;
|
|
*) echo "munix: ${card##*/} gpu driver is '$driver_name', using venus unless more gpus are found" >&2;;
|
|
esac
|
|
else
|
|
echo "munix: ${card##*/} has no gpu driver" >&2;
|
|
fi
|
|
done
|
|
else
|
|
echo "munix: kernel version '$kernel_ver' is older than 6.13, not using gpu due to missing support" >&2;
|
|
GPU_MODE=software
|
|
fi
|
|
MUVM_ARGS+=("--gpu-mode=$GPU_MODE")
|
|
else
|
|
BWRAP_ARGS+=("--dir" "/dev/dri")
|
|
MUVM_ARGS+=("--gpu-mode=software")
|
|
fi
|
|
|
|
if [ "$WAYLAND" -eq 1 ]; then
|
|
if [ "$XDG_RUNTIME_DIR" = "" ]; then
|
|
echo "munix: wayland requested, but no XDG_RUNTIME_DIR set" >&2
|
|
exit 1
|
|
fi
|
|
BWRAP_ARGS+=(
|
|
"--bind" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
|
|
"--setenv" "WAYLAND_DISPLAY" "$WAYLAND_DISPLAY"
|
|
)
|
|
MUVM_ARGS+=("-e" "WAYLAND_DISPLAY=wayland-1") # the proxy is managed by us, not muvm
|
|
fi
|
|
|
|
if [ "$PIPEWIRE" -eq 1 ]; then
|
|
if [ "$PIPEWIRE_RUNTIME_DIR" = "" ]; then
|
|
PIPEWIRE_RUNTIME_DIR="$XDG_RUNTIME_DIR"
|
|
fi
|
|
if [ "$PIPEWIRE_RUNTIME_DIR" = "" ]; then
|
|
PIPEWIRE_RUNTIME_DIR="$USERPROFILE"
|
|
fi
|
|
if [ "$PIPEWIRE_RUNTIME_DIR" = "" ]; then
|
|
echo "munix: pipewire requested, but no PIPEWIRE_RUNTIME_DIR/XDG_RUNTIME_DIR/USERPROFILE set" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$PIPEWIRE_REMOTE" = "" ]; then
|
|
PIPEWIRE_REMOTE=pipewire-0
|
|
fi
|
|
BWRAP_ARGS+=("--bind" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE")
|
|
fi
|
|
|
|
if [ "$X11" -eq 1 ]; then
|
|
BWRAP_ARGS+=(
|
|
"--bind" "/tmp/.X11-unix" "/tmp/.X11-unix"
|
|
"--ro-bind" "$XAUTHORITY" "$XAUTHORITY"
|
|
)
|
|
else
|
|
unset DISPLAY XAUTHORITY
|
|
fi
|
|
|
|
declare -a BG_PIDS
|
|
|
|
cleanup() {
|
|
for pid in "${BG_PIDS[@]}"; do
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
echo "Killing process $pid"
|
|
kill -INT "$pid"
|
|
wait "$pid" 2>/dev/null
|
|
fi
|
|
done
|
|
exit
|
|
}
|
|
|
|
trap cleanup EXIT INT TERM
|
|
|
|
HOST_RUNTIME_DIR="$XDG_RUNTIME_DIR/munix.$$"
|
|
mkdir -p $HOST_RUNTIME_DIR
|
|
rm $HOST_RUNTIME_DIR/*
|
|
sidebus-broker --guest-mountpoint /mnt/munix-doc-portal/doc --runtime-dir "$HOST_RUNTIME_DIR" --unix-path "$HOST_RUNTIME_DIR/port.sock" >/dev/null 2>&1 &
|
|
BG_PIDS+=("$!")
|
|
while [ ! -S "$HOST_RUNTIME_DIR/port.sock" ]; do sleep 0.1; done
|
|
BWRAP_ARGS+=(
|
|
--bind "$HOST_RUNTIME_DIR" /mnt/munix-doc-portal
|
|
--bind "$HOST_RUNTIME_DIR/port.sock" "$XDG_RUNTIME_DIR/krun/socket/port-50000"
|
|
)
|
|
|
|
# do not 'exec' because of cleanup :)
|
|
bwrap --unshare-all --share-net \
|
|
--uid $MICROVM_UID --gid $MICROVM_GID \
|
|
--tmpfs / \
|
|
--dir /run --dir /var --symlink /run /var/run --dir /tmp --dir /mnt --dir /bin --dir /usr/bin \
|
|
--proc /proc --ro-bind /sys /sys \
|
|
--dev /dev --dir /dev/input --dev-bind /dev/kvm /dev/kvm \
|
|
--ro-bind "$MUVM_PATH" /run/munix/muvm \
|
|
--ro-bind "$PASST_PATH" /run/munix/passt \
|
|
--ro-bind "$SCRIPT_PATH/micro-activate" /opt/bin/micro-activate \
|
|
--ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-remote \
|
|
--ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-configure-network \
|
|
--ro-bind "$MUVM_PATH/muvm-guest" /opt/bin/muvm-pwbridge \
|
|
--symlink "$MICROVM_CLOSURE/etc" /etc \
|
|
--symlink "$MICROVM_CLOSURE/sw/bin/sh" /bin/sh \
|
|
--symlink "$MICROVM_CLOSURE/sw/bin/env" /usr/bin/env \
|
|
--symlink "$MICROVM_CLOSURE" /run/current-system \
|
|
--ro-bind /nix/store /nix/store \
|
|
--file 12 /run/machine-id \
|
|
--file 13 /run/resolv.conf \
|
|
--dir "$XDG_RUNTIME_DIR" \
|
|
--setenv PATH "/run/munix/muvm:/run/munix/passt:$MICROVM_CLOSURE/sw/bin" \
|
|
"${BWRAP_ARGS[@]}" \
|
|
muvm \
|
|
--custom-init-cmdline "/opt/bin/micro-activate $MICROVM_CLOSURE/sw/sbin/init --log-target=console systemd.set_credential=sidebus.port:50000" \
|
|
"${MUVM_ARGS[@]}" \
|
|
-e container=munix \
|
|
-e MICROVM_CLOSURE="$MICROVM_CLOSURE" \
|
|
-e MICROVM_UID="$MICROVM_UID" -e MICROVM_GID="$MICROVM_GID" \
|
|
-i -t "${MICROVM_COMMAND[@]}" \
|
|
12< /etc/machine-id \
|
|
13< /etc/resolv.conf
|