From a467da324dd0ee9ac16d7b2d5a235db03f90d20c Mon Sep 17 00:00:00 2001 From: Kron4ek Date: Sun, 21 May 2023 22:01:03 +0500 Subject: [PATCH] Add a function to fix issues with Nvidia GPUs The function is called NVIDIA_HANDLER and is disabled by default. When enabled, it will automatically download the same Nvidia driver version as installed on the host system and pass it into the container. This is implemented via fuse-overlayfs, fuse3 is required for this to work. --- conty-start.sh | 130 ++++++++++++++++++++++++++++++++++++++++++-- create-utils.sh | 12 +++- utils.tar.gz | 4 +- utils_dwarfs.tar.gz | 4 +- 4 files changed, 140 insertions(+), 10 deletions(-) diff --git a/conty-start.sh b/conty-start.sh index 8ad1b51..523876f 100755 --- a/conty-start.sh +++ b/conty-start.sh @@ -19,8 +19,8 @@ script_version="1.23" # Important variables to manually adjust after modification! # Needed to avoid problems with mounting due to an incorrect offset. -script_size=29108 -utils_size=2520686 +script_size=33659 +utils_size=2564623 # Full path to the script script_literal="${BASH_SOURCE[0]}" @@ -114,6 +114,12 @@ Environment variables: isolates X11 server with Xephyr. The default is 1. + NVIDIA_HANDLER Fixes issues with graphical applications on Nvidia + GPUs with the proprietary driver. Enable this only + if you are using an Nvidia GPU, the proprietary + driver and encountering issues running graphical + applications. Fuse3 is required for this to work. + USE_SYS_UTILS Tells the script to use squashfuse/dwarfs and bwrap installed on the system instead of the builtin ones. @@ -166,6 +172,9 @@ fi mount_point="${working_dir}"/mnt +export overlayfs_dir="${HOME}"/.local/share/Conty/overlayfs +export nvidia_drivers_dir="${HOME}"/.local/share/Conty/nvidia + # Offset where the image is stored offset=$((script_size+utils_size)) @@ -284,6 +293,90 @@ gui () { fi } +mount_overlayfs () { + if [ "${script_md5}" != "$(cat "${overlayfs_dir}"/current-image-version 2>/dev/null)" ]; then + rm -rf "${overlayfs_dir}"/up "${overlayfs_dir}"/work \ + "${nvidia_drivers_dir}"/current-nvidia-version + fi + + mkdir -p "${overlayfs_dir}"/up + mkdir -p "${overlayfs_dir}"/work + mkdir -p "${overlayfs_dir}"/merged + + echo "${script_md5}" > "${overlayfs_dir}"/current-image-version + + if [ ! "$(ls "${overlayfs_dir}"/merged 2>/dev/null)" ]; then + if command -v "${fuse_overlayfs}" 1>/dev/null; then + if command -v fusermount3 1>/dev/null; then + "${fuse_overlayfs}" -o squash_to_uid="$(id -u)" -o squash_to_gid="$(id -g)" -o lowerdir="${mount_point}",upperdir="${overlayfs_dir}"/up,workdir="${overlayfs_dir}"/work "${overlayfs_dir}"/merged + else + echo "Fuse3 is required for fuse-overlayfs" + fi + else + echo "fuse-overlayfs not found" + fi + fi +} + +nvidia_driver_handler () { + if lsmod | grep nvidia 1>/dev/null || nvidia-smi 1>/dev/null; then + if [ "$(ls /tmp/hostlibs/x86_64-linux-gnu/libGLX_nvidia.so.* 2>/dev/null)" ]; then + nvidia_driver_version="$(basename /tmp/hostlibs/x86_64-linux-gnu/libGLX_nvidia.so.*.* | tail -c +18)" + elif [ "$(ls /tmp/hostlibs/libGLX_nvidia.so.* 2>/dev/null)" ]; then + nvidia_driver_version="$(basename /tmp/hostlibs/libGLX_nvidia.so.*.* | tail -c +18)" + elif nvidia-smi 1>/dev/null; then + nvidia_driver_version="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader)" + elif modinfo nvidia &>/dev/null; then + nvidia_driver_version="$(modinfo -F version nvidia 2>/dev/null)" + fi + else + echo "Seems like your system has no Nvidia driver loaded" + exit 1 + fi + + if [ "$(cat "${nvidia_drivers_dir}"/current-nvidia-version 2>/dev/null)" = "${nvidia_driver_version}" ]; then + exit + fi + + if [ -z "${nvidia_driver_version}" ]; then + echo "Unable to determine the Nvidia driver version" + exit 1 + fi + + OLD_PWD="${PWD}" + + mkdir -p "${nvidia_drivers_dir}" + cd "${nvidia_drivers_dir}" + + echo "Found Nvidia driver ${nvidia_driver_version}" + echo "Downloading the Nvidia driver ${nvidia_driver_version}, please wait..." + + # Try to download the driver from the default Nvidia URL + driver_url="https://us.download.nvidia.com/XFree86/Linux-x86_64/${nvidia_driver_version}/NVIDIA-Linux-x86_64-${nvidia_driver_version}.run" + curl -#Lo nvidia.run "${driver_url}" + + # If the previous download failed, get the URL from FlatHub repo + if [ ! -s nvidia.run ]; then + rm -f nvidia.run + driver_url="https:$(curl -#Lo - "https://raw.githubusercontent.com/flathub/org.freedesktop.Platform.GL.nvidia/master/data/nvidia-${nvidia_driver_version}-i386.data" | cut -d ':' -f 6)" + curl -#Lo nvidia.run "${driver_url}" + fi + + if [ -s nvidia.run ]; then + echo "Installing the Nvidia driver, please wait..." + chmod +x nvidia.run + ./nvidia.run --target nvidia-driver -x &>/dev/null + cd nvidia-driver || exit 1 + fakeroot ./nvidia-installer --silent --no-x-check --no-kernel-module &>/dev/null + cd "${nvidia_drivers_dir}" + echo "${nvidia_driver_version}" > current-nvidia-version + rm -rf nvidia.run nvidia-driver + echo "The driver has been installed" + fi + + cd "${OLD_PWD}" +} + # Check if FUSE is installed if ! command -v fusermount3 1>/dev/null && ! command -v fusermount 1>/dev/null; then echo "Please install fuse2 or fuse3 and run the script again." @@ -357,6 +450,7 @@ if [ "${USE_SYS_UTILS}" != 1 ]; then fi bwrap="${working_dir}"/utils/bwrap + fuse_overlayfs="${working_dir}"/utils/fuse-overlayfs if [ ! -f "${mount_tool}" ] || [ ! -f "${bwrap}" ]; then tail -c +$((script_size+1)) "${script}" | head -c "${utils_size}" | tar -C "${working_dir}" -zxf - @@ -369,9 +463,10 @@ if [ "${USE_SYS_UTILS}" != 1 ]; then exit 1 fi - chmod +x "${mount_tool}" - chmod +x "${bwrap}" + chmod +x "${mount_tool}" 2>/dev/null + chmod +x "${bwrap}" 2>/dev/null chmod +x "${extraction_tool}" 2>/dev/null + chmod +x "${fuse_overlayfs}" 2>/dev/null fi else if ! command -v bwrap 1>/dev/null; then @@ -382,6 +477,7 @@ else fi bwrap=bwrap + fuse_overlayfs=fuse-overlayfs if [ "${dwarfs_image}" = 1 ]; then if ! command -v dwarfs 1>/dev/null && ! command -v dwarfs2 1>/dev/null; then @@ -774,10 +870,16 @@ run_bwrap () { mount_opt=(--bind-try /opt /opt) fi + if [ "${NVIDIA_HANDLER}" = 1 ] && [ "$(ls "${overlayfs_dir}"/merged 2>/dev/null)" ]; then + newroot_path="${overlayfs_dir}"/merged + else + newroot_path="${mount_point}" + fi + show_msg launch_wrapper "${bwrap}" \ - --ro-bind "${mount_point}" / \ + --bind "${newroot_path}" / \ --dev-bind /dev /dev \ --ro-bind /sys /sys \ --bind-try /tmp /tmp \ @@ -809,6 +911,11 @@ run_bwrap () { trap_exit () { rm -f "${working_dir}"/running_"${script_id}" + if [ -d "${overlayfs_dir}"/merged ]; then + fusermount"${fuse_version}" -uz "${overlayfs_dir}"/merged 2>/dev/null || \ + umount --lazy "${overlayfs_dir}"/merged 2>/dev/null + fi + if [ ! "$(ls "${working_dir}"/running_* 2>/dev/null)" ]; then fusermount"${fuse_version}" -uz "${mount_point}" 2>/dev/null || \ umount --lazy "${mount_point}" 2>/dev/null @@ -926,6 +1033,19 @@ if [ "$(ls "${mount_point}" 2>/dev/null)" ] || \ exit fi + if [ "${NVIDIA_HANDLER}" = 1 ]; then + show_msg "Nvidia driver handler is enabled" + + mount_overlayfs + mkdir -p "${nvidia_drivers_dir}" + export -f nvidia_driver_handler + run_bwrap --tmpfs /tmp --tmpfs /var --tmpfs /run \ + --bind-try /usr/lib /tmp/hostlibs \ + --bind-try /usr/lib64 /tmp/hostlibs \ + --bind-try "${nvidia_drivers_dir}" "${nvidia_drivers_dir}" \ + bash -c nvidia_driver_handler + fi + # If SANDBOX_LEVEL is 3, run Xephyr and openbox before running applications if [ "${SANDBOX}" = 1 ] && [ -n "${SANDBOX_LEVEL}" ] && [ "${SANDBOX_LEVEL}" -ge 3 ]; then if [ -f "${mount_point}"/usr/bin/Xephyr ]; then diff --git a/create-utils.sh b/create-utils.sh index a89e9e3..f29aa49 100755 --- a/create-utils.sh +++ b/create-utils.sh @@ -12,13 +12,14 @@ script_dir="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" # Set to true to compile dwarfs instead of squashfuse -build_dwarfs="true" +build_dwarfs="false" squashfuse_version="0.1.105" bwrap_version="0.8.0" lz4_version="1.9.4" zstd_version="1.5.5" squashfs_tools_version="4.6.1" +fuse_overlayfs_version="1.12" export CC=gcc export CXX=g++ @@ -33,10 +34,12 @@ cd "${script_dir}"/build-utils || exit 1 curl -#Lo lz4.tar.gz https://github.com/lz4/lz4/archive/refs/tags/v${lz4_version}.tar.gz curl -#Lo zstd.tar.gz https://github.com/facebook/zstd/archive/refs/tags/v${zstd_version}.tar.gz curl -#Lo bwrap.tar.gz https://github.com/containers/bubblewrap/archive/refs/tags/v${bwrap_version}.tar.gz +curl -#Lo fuse-overlayfs.tar.gz https://github.com/containers/fuse-overlayfs/archive/refs/tags/v${fuse_overlayfs_version}.tar.gz tar xf lz4.tar.gz tar xf zstd.tar.gz tar xf bwrap.tar.gz +tar xf fuse-overlayfs.tar.gz if [ "${build_dwarfs}" != "true" ]; then curl -#Lo squashfuse.tar.gz https://github.com/vasi/squashfuse/archive/refs/tags/${squashfuse_version}.tar.gz @@ -51,6 +54,11 @@ cd bubblewrap-"${bwrap_version}" || exit 1 ./configure --disable-selinux --disable-man make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install +cd ../fuse-overlayfs-"${fuse_overlayfs_version}" || exit 1 +./autogen.sh +./configure +make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install + cd ../lz4-"${lz4_version}" || exit 1 make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install @@ -76,6 +84,7 @@ mv bin/usr/local/bin/squashfuse utils mv bin/usr/local/bin/squashfuse_ll utils mv bin/usr/local/bin/mksquashfs utils mv bin/usr/local/bin/unsquashfs utils +mv bin/usr/local/bin/fuse-overlayfs utils mv bin/usr/local/lib/liblz4.so."${lz4_version}" utils/liblz4.so.1 mv bin/usr/local/lib/libzstd.so."${zstd_version}" utils/libzstd.so.1 mv bin/usr/local/lib/libfuseprivate.so.0.0.0 utils/libfuseprivate.so.0 @@ -130,6 +139,7 @@ find utils -type f -exec strip --strip-unneeded {} \; 2>/dev/null cat < utils/info bubblewrap ${bwrap_version} +fuse-overlayfs ${fuse_overlayfs_version} lz4 ${lz4_version} zstd ${zstd_version} EOF diff --git a/utils.tar.gz b/utils.tar.gz index f2b018e..d268e33 100644 --- a/utils.tar.gz +++ b/utils.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6637ac7ef4a0e36e90349b5ce701c334abe284f4425024ea67cbf55761f617f3 -size 2520686 +oid sha256:20b855587b07fa71c8be8e73220495fcee7c9ec290914e982b76fd184fa67094 +size 2564623 diff --git a/utils_dwarfs.tar.gz b/utils_dwarfs.tar.gz index 4de9e8c..3c35cef 100644 --- a/utils_dwarfs.tar.gz +++ b/utils_dwarfs.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b160ecd08ffb0b4c6340799c882fb3f017524383b323582e6e8bd7e76fbf9cc -size 9387864 +oid sha256:ef56bd72810c1c05a6f4cd77e816b2741ab014b421c00eb0337602c5a11d0959 +size 9431944