mirror of
https://github.com/Kron4ek/Conty
synced 2024-12-27 09:58:25 +01:00
2a40644729
Allows to mount the squahfs image via the regular mount command instead of squashfuse. In this case root rights will be requested via sudo during mounting and unmounting.
369 lines
12 KiB
Bash
Executable file
369 lines
12 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
## Dependencies: bash fuse2 tar coreutils
|
|
|
|
# Prevent launching as root
|
|
if [ -z "$ALLOW_ROOT" ]; then
|
|
if [ $EUID = 0 ]; then
|
|
echo "Do not run this script as root!"
|
|
echo
|
|
echo "If you really need to run it as root, set ALLOW_ROOT env variable."
|
|
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Full path to the script
|
|
script_literal="${BASH_SOURCE[0]}"
|
|
script_name="$(basename "${script_literal}")"
|
|
script="$(readlink -f "${script_literal}")"
|
|
|
|
# Working directory where squashfs image will be mounted
|
|
# Default path: /tmp/scriptname_username_randomnumber
|
|
working_dir=/tmp/"$(basename "${script}")"_"${USER}"_${RANDOM}
|
|
|
|
# It's important to set correct sizes below, otherwise there will be
|
|
# a problem with mounting the squashfs image due to an incorrectly calculated offset.
|
|
|
|
# The size of this script
|
|
scriptsize=12742
|
|
|
|
# The size of the utils.tar archive
|
|
# utils.tar contains bwrap and squashfuse binaries
|
|
utilssize=1259520
|
|
|
|
# Offset where the squashfs image is stored
|
|
offset=$((scriptsize+utilssize))
|
|
|
|
if [ "$1" = "--help" ] || [ "$1" = "-h" ] || ([ -z "$1" ] && [ -z "${AUTOSTART}" ] && [ ! -L "${script_literal}" ]); then
|
|
echo "Usage: ./conty.sh command command_arguments"
|
|
echo
|
|
echo "Arguments:"
|
|
echo
|
|
echo -e "-e \tExtract squashfs image"
|
|
echo -e "-o \tShow squashfs image offset"
|
|
echo
|
|
echo "Environment variables:"
|
|
echo
|
|
echo -e "AUTOSTART \tAutostarts an application specified in this variable"
|
|
echo -e "\t\tFor example, AUTOSTART=\"steam\" or AUTOSTART=\"/home/username/"
|
|
echo -e "\t\tprogram\""
|
|
echo -e "AUTOARGS \tAutomatically appends arguments from this variable to a"
|
|
echo -e "\t\tlaunched application. For example, AUTOARGS=\"--version\""
|
|
echo -e "\t\tCan be used together with AUTOSTART, but also without it."
|
|
echo -e "DISABLE_NET \tDisables network access"
|
|
echo -e "SANDBOX \tEnables filesystem sandbox"
|
|
echo -e "BIND \t\tBinds directories and files (separated by space) from host"
|
|
echo -e "\t\tsystem to the container. All specified items must exist."
|
|
echo -e "\t\tFor example, BIND=\"/home/username/.config /etc/pacman.conf\""
|
|
echo -e "HOME_DIR \tSets HOME directory to a custom location."
|
|
echo -e "\t\tCan be used only together with SANDBOX enabled."
|
|
echo -e "\t\tFor example, HOME_DIR=\"/home/username/custom_home\""
|
|
echo -e "USE_SYS_UTILS \tMakes the script to use squashfuse and bwrap"
|
|
echo -e "\t\tinstalled on the system instead of the builtin ones."
|
|
echo -e "\t\tIf you want to enable this variable, please make sure"
|
|
echo -e "\t\tthat bubblewrap and squashfuse are installed on your system"
|
|
echo -e "\t\tand that squashfuse supports the compression algo the image"
|
|
echo -e "\t\twas built with."
|
|
echo -e "NVIDIA_FIX \tAutomatically download and bind the required Nvidia"
|
|
echo -e "\t\tlibraries if the kernel module version in the system differs"
|
|
echo -e "\t\tfrom the Nvidia libraries version inside the container."
|
|
echo -e "\t\tThis should fix the graphics acceleration problems on Nvidia."
|
|
echo -e "SUDO_MOUNT \tMakes the script to mount the squashfs image by using"
|
|
echo -e "\t\tthe regular mount command instead of squashfuse. In this"
|
|
echo -e "\t\tcase root rights will be requested (via sudo) when mounting"
|
|
echo -e "\t\tand unmounting."
|
|
echo
|
|
echo "If you enable SANDBOX but don't set BIND or HOME_DIR, then"
|
|
echo "no directories will be available at all. And a fake temporary HOME"
|
|
echo "directory will be created inside the container."
|
|
echo
|
|
echo "Also, if the script is a symlink to itself but with different name,"
|
|
echo "then the symlinked script will automatically run a program according"
|
|
echo "to its name. For instance, if the script is a symlink with the name \"wine\","
|
|
echo "then it will automatically run wine during launch. This is an alternative"
|
|
echo "to the AUTOSTART variable, but the variable has a higher priority."
|
|
|
|
exit
|
|
elif [ "$1" = "-e" ]; then
|
|
if command -v unsquashfs 1>/dev/null; then
|
|
unsquashfs -o $offset -d "$(basename "${script}")"_files "${script}"
|
|
else
|
|
echo "To extract the image install squashfs-tools."
|
|
fi
|
|
|
|
exit
|
|
elif [ "$1" = "-o" ]; then
|
|
echo $offset
|
|
|
|
exit
|
|
fi
|
|
|
|
# Check if FUSE2 is installed
|
|
if command -v fusermount 1>/dev/null; then
|
|
fmount=fusermount
|
|
else
|
|
echo "Please install fuse2 and run the script again!"
|
|
exit 1
|
|
fi
|
|
|
|
# Extract utils.tar
|
|
mkdir -p "${working_dir}"
|
|
|
|
if [ -z "${USE_SYS_UTILS}" ]; then
|
|
tail -c +$((scriptsize+1)) "${script}" | head -c $utilssize > "${working_dir}"/utils.tar
|
|
tar -C "${working_dir}" -xf "${working_dir}"/utils.tar
|
|
rm "${working_dir}"/utils.tar
|
|
|
|
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${working_dir}/utils"
|
|
sfuse="${working_dir}"/utils/squashfuse
|
|
bwrap="${working_dir}"/utils/bwrap
|
|
|
|
chmod +x "${sfuse}"
|
|
chmod +x "${bwrap}"
|
|
else
|
|
if ! command -v bwrap 1>/dev/null; then
|
|
echo "USE_SYS_UTILS is enabled, but bwrap is not installed!"
|
|
echo "Please install it and run the script again."
|
|
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v squashfuse 1>/dev/null && [ -z "${SUDO_MOUNT}" ]; then
|
|
echo "USE_SYS_UTILS is enabled, but squshfuse is not installed!"
|
|
echo "Please install it and run the script again."
|
|
echo "Or enable SUDO_MOUNT to mount the image using the regular"
|
|
echo "mount command instead of squashfuse."
|
|
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using system squashfuse and bwrap"
|
|
|
|
sfuse=squashfuse
|
|
bwrap=bwrap
|
|
fi
|
|
|
|
run_bwrap () {
|
|
if [ -n "$DISABLE_NET" ]; then
|
|
echo "Network is disabled"
|
|
|
|
net="--unshare-net"
|
|
fi
|
|
|
|
if [ -n "$SANDBOX" ]; then
|
|
echo "Filesystem sandbox is enabled"
|
|
|
|
dirs="--tmpfs /home --dir ${HOME} --tmpfs /opt --tmpfs /mnt \
|
|
--tmpfs /media --tmpfs /var --tmpfs /run --symlink /run /var/run \
|
|
--bind-try /run/user /run/user --bind-try /run/dbus /run/dbus"
|
|
|
|
if [ -n "${HOME_DIR}" ]; then
|
|
echo "Set HOME to ${HOME_DIR}"
|
|
dirs="${dirs} --bind ${HOME_DIR} ${HOME}"
|
|
fi
|
|
|
|
# unshare="--unshare-user-try --unshare-pid --unshare-uts --unshare-cgroup-try \
|
|
# --hostname Conty"
|
|
else
|
|
dirs="--bind-try /home /home --bind-try /mnt /mnt --bind-try /opt /opt \
|
|
--bind-try /media /media --bind-try /run /run --bind-try /var /var"
|
|
fi
|
|
|
|
if [ -n "$BIND" ]; then
|
|
echo "Binded items: ${BIND}"
|
|
|
|
for i in ${BIND}; do
|
|
bind="${bind} --bind ${i} ${i}"
|
|
done
|
|
|
|
dirs="${dirs} ${bind}"
|
|
fi
|
|
|
|
echo
|
|
|
|
"${bwrap}" --ro-bind "${working_dir}"/mnt / \
|
|
--dev-bind /dev /dev \
|
|
--ro-bind /sys /sys \
|
|
--bind-try /tmp /tmp \
|
|
--proc /proc \
|
|
--ro-bind-try /etc/resolv.conf /etc/resolv.conf \
|
|
--ro-bind-try /etc/hosts /etc/hosts \
|
|
--ro-bind-try /etc/nsswitch.conf /etc/nsswitch.conf \
|
|
--ro-bind-try /etc/passwd /etc/passwd \
|
|
--ro-bind-try /etc/group /etc/group \
|
|
--ro-bind-try /usr/local /usr/local \
|
|
${dirs} \
|
|
${net} \
|
|
${nvidia_driver_bind} \
|
|
--setenv PATH "${PATH}:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/lib/jvm/default/bin" \
|
|
"$@"
|
|
}
|
|
|
|
# Function that checks if the Nvidia kernel module loaded in the
|
|
# system matches the version of the Nvidia libraries inside the container
|
|
# and downloads corresponding Nvidia libs from the official site if they
|
|
# are not the same. Also binds the downloaded libraries to the container.
|
|
#
|
|
# This is absolutely necessary for Nvidia GPUs, otherwise graphics
|
|
# acceleration will not work.
|
|
|
|
bind_nvidia_driver () {
|
|
# Path to store downloaded Nvidia drivers
|
|
nvidia_drivers_dir="${HOME}"/.local/share/Conty/nvidia-drivers
|
|
|
|
# Check if the Nvidia module is loaded
|
|
# If it's loaded, then likely Nvidia GPU is being used
|
|
if lsmod | grep nvidia 1>/dev/null || nvidia-smi 1>/dev/null; then
|
|
if nvidia-smi 1>/dev/null; then
|
|
nvidia_version="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader)"
|
|
elif modinfo nvidia &>/dev/null; then
|
|
nvidia_version="$(modinfo -F version nvidia 2>/dev/null)"
|
|
else
|
|
if [ -d /usr/lib/x86_64-linux-gnu ]; then
|
|
nvidia_version="$(basename /usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.*.* | tail -c +18)"
|
|
else
|
|
nvidia_version="$(basename /usr/lib/libGLX_nvidia.so.*.* | tail -c +18)"
|
|
fi
|
|
fi
|
|
|
|
# Check if the kernel module version is different from the
|
|
# libraries version inside the container
|
|
if [ -n "${nvidia_version}" ]; then
|
|
nvidia_version_inside="$(basename "${working_dir}"/mnt/usr/lib/libGLX_nvidia.so.*.* | tail -c +18)"
|
|
|
|
if [ "$(cat "${nvidia_drivers_dir}"/current_version.txt 2>/dev/null)" != "${nvidia_version}" ] \
|
|
&& [ "${nvidia_version}" != "${nvidia_version_inside}" ]; then
|
|
echo "Nvidia driver version mismatch detected, trying to fix"
|
|
|
|
mkdir -p "${nvidia_drivers_dir}"
|
|
cd "${nvidia_drivers_dir}"
|
|
|
|
rm -rf nvidia-driver
|
|
rm -f nvidia.run
|
|
|
|
echo "Downloading Nvidia ${nvidia_version}, please wait"
|
|
|
|
# Try to download from the default Nvidia url
|
|
driver_url="https://us.download.nvidia.com/XFree86/Linux-x86_64/${nvidia_version}/NVIDIA-Linux-x86_64-${nvidia_version}.run"
|
|
wget -q --show-progress "${driver_url}" -O nvidia.run
|
|
|
|
# If the previous download failed, get url from flathub
|
|
if [ ! -s nvidia.run ]; then
|
|
rm -f nvidia.run
|
|
driver_url="https:$(wget -q "https://raw.githubusercontent.com/flathub/org.freedesktop.Platform.GL.nvidia/master/data/nvidia-${nvidia_version}-i386.data" \
|
|
-O - | cut -d ':' -f 6)"
|
|
|
|
wget -q --show-progress "${driver_url}" -O nvidia.run
|
|
fi
|
|
|
|
if [ -s nvidia.run ]; then
|
|
chmod +x nvidia.run
|
|
echo "Unpacking nvidia.run..."
|
|
./nvidia.run -x &>/dev/null
|
|
rm nvidia.run
|
|
mv NVIDIA-Linux-x86_64-${nvidia_version} nvidia-driver
|
|
echo ${nvidia_version} > current_version.txt
|
|
fi
|
|
|
|
cd "${PWD}"
|
|
fi
|
|
|
|
# Bind the downloaded Nvidia libs to the container
|
|
if [ -d "${nvidia_drivers_dir}"/nvidia-driver ]; then
|
|
nvidia_libs_list="libcuda.so libEGL_nvidia.so libGLESv1_CM_nvidia.so \
|
|
libGLESv2_nvidia.so libGLX_nvidia.so libnvcuvid.so libnvidia-cbl.so \
|
|
libnvidia-cfg.so libnvidia-eglcore.so libnvidia-encode.so libnvidia-fbc.so \
|
|
libnvidia-glcore.so libnvidia-glsi.so libnvidia-glvkspirv.so libnvidia-ifr.so \
|
|
libnvidia-ml.so libnvidia-ngx.so libnvidia-opticalflow.so libnvidia-ptxjitcompiler.so \
|
|
libnvidia-rtcore.so libnvidia-tls.so libnvoptix.so"
|
|
|
|
for lib in ${nvidia_libs_list}; do
|
|
if [ -f "${working_dir}"/mnt/usr/lib/${lib}.${nvidia_version_inside} ]; then
|
|
nvidia_driver_bind="${nvidia_driver_bind} \
|
|
--ro-bind-try ${nvidia_drivers_dir}/nvidia-driver/${lib}.${nvidia_version} \
|
|
/usr/lib/${lib}.${nvidia_version_inside}"
|
|
fi
|
|
|
|
if [ -f "${working_dir}"/mnt/usr/lib32/${lib}.${nvidia_version_inside} ]; then
|
|
nvidia_driver_bind="${nvidia_driver_bind} \
|
|
--ro-bind-try ${nvidia_drivers_dir}/nvidia-driver/32/${lib}.${nvidia_version} \
|
|
/usr/lib32/${lib}.${nvidia_version_inside}"
|
|
fi
|
|
|
|
if [ -f "${working_dir}"/mnt/usr/lib/nvidia/xorg/libglxserver_nvidia.so.${nvidia_version_inside} ]; then
|
|
nvidia_driver_bind="${nvidia_driver_bind} \
|
|
--ro-bind-try ${nvidia_drivers_dir}/nvidia-driver/libglxserver_nvidia.so.${nvidia_version} \
|
|
/usr/lib/nvidia/xorg/libglxserver_nvidia.so.${nvidia_version_inside}"
|
|
fi
|
|
|
|
if [ -f "${working_dir}"/mnt/usr/lib/vdpau/libvdpau_nvidia.so.${nvidia_version_inside} ]; then
|
|
nvidia_driver_bind="${nvidia_driver_bind} \
|
|
--ro-bind-try ${nvidia_drivers_dir}/nvidia-driver/libvdpau_nvidia.so.${nvidia_version} \
|
|
/usr/lib/vdpau/libvdpau_nvidia.so.${nvidia_version_inside}"
|
|
fi
|
|
|
|
if [ -f "${working_dir}"/mnt/usr/lib32/vdpau/libvdpau_nvidia.so.${nvidia_version_inside} ]; then
|
|
nvidia_driver_bind="${nvidia_driver_bind} \
|
|
--ro-bind-try ${nvidia_drivers_dir}/nvidia-driver/32/libvdpau_nvidia.so.${nvidia_version} \
|
|
/usr/lib32/vdpau/libvdpau_nvidia.so.${nvidia_version_inside}"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
trap_exit () {
|
|
"${fmount}" -uz "${working_dir}"/mnt 2>/dev/null || \
|
|
${sudo_umount} umount --lazy "${working_dir}"/mnt 2>/dev/null
|
|
sleep 1
|
|
rm -rf "${working_dir}"
|
|
exit
|
|
}
|
|
|
|
trap 'trap_exit' EXIT
|
|
|
|
if [ -n "${SUDO_MOUNT}" ]; then
|
|
echo "Using regular mount command (sudo mount) instead of squashfuse"
|
|
|
|
sfuse=mount
|
|
sudo_mount=sudo
|
|
sudo_umount=sudo
|
|
fi
|
|
|
|
# Mount boostrap image
|
|
mkdir -p "${working_dir}"/mnt
|
|
|
|
if ${sudo_mount} "${sfuse}" -o offset="${offset}" "${script}" "${working_dir}"/mnt ; then
|
|
echo "Running Conty"
|
|
|
|
if [ -n "${NVIDIA_FIX}" ]; then
|
|
bind_nvidia_driver
|
|
fi
|
|
|
|
if [ -n "${AUTOSTART}" ]; then
|
|
autostart="${AUTOSTART}"
|
|
elif [ -L "${script_literal}" ]; then
|
|
if [ -f "${working_dir}"/mnt/usr/bin/"${script_name}" ]; then
|
|
autostart="${script_name}"
|
|
fi
|
|
fi
|
|
|
|
if [ -n "${AUTOARGS}" ]; then
|
|
echo "Automatically append arguments: ${AUTOARGS}"
|
|
fi
|
|
|
|
if [ -n "${autostart}" ]; then
|
|
echo "Autostarting ${autostart}"
|
|
run_bwrap "${autostart}" "$@" ${AUTOARGS}
|
|
else
|
|
run_bwrap "$@" ${AUTOARGS}
|
|
fi
|
|
else
|
|
echo "Mounting the squashfs image failed!"
|
|
|
|
exit 1
|
|
fi
|
|
|
|
exit
|