diff --git a/scripts/configure_igpu_lxc.sh b/scripts/configure_igpu_lxc.sh index f7eb484..0272b3a 100644 --- a/scripts/configure_igpu_lxc.sh +++ b/scripts/configure_igpu_lxc.sh @@ -6,8 +6,8 @@ # Author : MacRimi # Copyright : (c) 2024 MacRimi # License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE) -# Version : 1.0 -# Last Updated: 28/01/2025 +# Version : 1.1 +# Last Updated: 17/08/2025 # ========================================================== # Description: # This script automates the process of enabling and configuring Intel Integrated GPU (iGPU) support in Proxmox VE LXC containers. @@ -32,7 +32,7 @@ initialize_cache -# Select LXC container + select_container() { CONTAINERS=$(pct list | awk 'NR>1 {print $1, $3}' | xargs -n2) @@ -59,14 +59,14 @@ select_container() { -# Validate that the selected container is valid + validate_container_id() { if [ -z "$CONTAINER_ID" ]; then msg_error "$(translate 'Container ID not defined. Make sure to select a container first.')" exit 1 fi - # Check if the container is running and stop it before configuration + if pct status "$CONTAINER_ID" | grep -q "running"; then msg_info "$(translate 'Stopping the container before applying configuration...')" pct stop "$CONTAINER_ID" @@ -76,103 +76,103 @@ validate_container_id() { -# Configure LXC for iGPU configure_lxc_for_igpu() { - validate_container_id - CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf" - if [ ! -f "$CONFIG_FILE" ]; then - msg_error "$(translate 'Configuration file for container') $CONTAINER_ID $(translate 'not found.')" - exit 1 + validate_container_id + + CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf" + [[ -f "$CONFIG_FILE" ]] || { msg_error "$(translate 'Configuration file for container') $CONTAINER_ID $(translate 'not found.')"; exit 1; } + + + if [[ ! -d /dev/dri ]]; then + modprobe i915 2>/dev/null || true + for _ in {1..5}; do + [[ -d /dev/dri ]] && break + sleep 1 + done + fi + + CT_TYPE=$(pct config "$CONTAINER_ID" | awk '/^unprivileged:/ {print $2}') + [[ -z "$CT_TYPE" ]] && CT_TYPE="0" + + msg_info "$(translate 'Configuring Intel iGPU passthrough for container...')" + + for rn in /dev/dri/renderD*; do + [[ -e "$rn" ]] || continue + chmod 660 "$rn" 2>/dev/null || true + chgrp render "$rn" 2>/dev/null || true + done + + mapfile -t RENDER_NODES < <(find /dev/dri -maxdepth 1 -type c -name 'renderD*' 2>/dev/null || true) + mapfile -t CARD_NODES < <(find /dev/dri -maxdepth 1 -type c -name 'card*' 2>/dev/null || true) + FB_NODE="" + [[ -e /dev/fb0 ]] && FB_NODE="/dev/fb0" + + if [[ ${#RENDER_NODES[@]} -eq 0 && ${#CARD_NODES[@]} -eq 0 && -z "$FB_NODE" ]]; then + msg_warn "$(translate 'No VA-API devices found on host (/dev/dri*, /dev/fb0). Is i915 loaded?')" + return 0 fi - if grep -q "^unprivileged: 1" "$CONFIG_FILE"; then - msg_info "$(translate 'The container is unprivileged. Changing to privileged...')" - sed -i "s/^unprivileged: 1/unprivileged: 0/" "$CONFIG_FILE" - STORAGE_TYPE=$(pct config "$CONTAINER_ID" | grep "^rootfs:" | awk -F, '{print $2}' | cut -d'=' -f2) - if [[ "$STORAGE_TYPE" == "dir" ]]; then - STORAGE_PATH=$(pct config "$CONTAINER_ID" | grep "^rootfs:" | awk '{print $2}' | cut -d',' -f1) - chown -R root:root "$STORAGE_PATH" - fi - msg_ok "$(translate 'Container changed to privileged.')" - fi - - - if grep -q "^lxc.apparmor.profile" "$CONFIG_FILE"; then - msg_info "$(translate 'Disabling AppArmor profile to avoid conflicts...')" - sed -i "/^lxc.apparmor.profile/d" "$CONFIG_FILE" - msg_ok "$(translate 'AppArmor profile removed.')" - fi - - - - # Configure iGPU - if ! grep -q "features: nesting=1" "$CONFIG_FILE"; then + if grep -q '^features:' "$CONFIG_FILE"; then + grep -Eq '^features:.*(^|,)\s*nesting=1(\s|,|$)' "$CONFIG_FILE" || sed -i 's/^features:\s*/&nesting=1, /' "$CONFIG_FILE" + else echo "features: nesting=1" >> "$CONFIG_FILE" fi - if ! grep -q "c 226:0 rwm" "$CONFIG_FILE"; then - echo "lxc.cgroup2.devices.allow: c 226:0 rwm # iGPU" >> "$CONFIG_FILE" - echo "lxc.cgroup2.devices.allow: c 226:128 rwm # iGPU" >> "$CONFIG_FILE" + + + if [[ "$CT_TYPE" == "0" ]]; then + + sed -i '/^lxc\.cgroup2\.devices\.allow:\s*c\s*226:/d' "$CONFIG_FILE" + sed -i '\|^lxc\.mount\.entry:\s*/dev/dri|d' "$CONFIG_FILE" + sed -i '\|^lxc\.mount\.entry:\s*/dev/fb0|d' "$CONFIG_FILE" + + echo "lxc.cgroup2.devices.allow: c 226:* rwm" >> "$CONFIG_FILE" echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >> "$CONFIG_FILE" - echo "lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file" >> "$CONFIG_FILE" - fi - - if ! grep -q "c 29:0 rwm # Framebuffer" "$CONFIG_FILE"; then - echo "lxc.cgroup2.devices.allow: c 29:0 rwm # Framebuffer" >> "$CONFIG_FILE" - fi - - if ! grep -q "lxc.mount.entry: /dev/fb0" "$CONFIG_FILE"; then - echo "lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file" >> "$CONFIG_FILE" - fi + [[ -n "$FB_NODE" ]] && echo "lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file" >> "$CONFIG_FILE" - msg_ok "$(translate 'iGPU configuration added to container') $CONTAINER_ID." -} + else + sed -i '/^dev[0-9]\+:/d' "$CONFIG_FILE" + idx=0 + for c in "${CARD_NODES[@]}"; do + echo "dev${idx}: $c,gid=44" >> "$CONFIG_FILE" + idx=$((idx+1)) + done + for r in "${RENDER_NODES[@]}"; do + echo "dev${idx}: $r,gid=104" >> "$CONFIG_FILE" + idx=$((idx+1)) + done - - - -configure_lxc_for_igpu_() { - validate_container_id - CONFIG_FILE="/etc/pve/lxc/${CONTAINER_ID}.conf" - [[ -f "$CONFIG_FILE" ]] || { msg_error "$(translate 'Configuration file not found.')"; exit 1; } - - - if ! grep -q "^unprivileged:" "$CONFIG_FILE"; then - echo "unprivileged: 1" >> "$CONFIG_FILE" fi - - - grep -q "^features: " "$CONFIG_FILE" || echo "features: nesting=1" >> "$CONFIG_FILE" - grep -q "^lxc.cgroup2.devices.allow: c 226:\* rwm" "$CONFIG_FILE" || \ - echo "lxc.cgroup2.devices.allow: c 226:* rwm" >> "$CONFIG_FILE" - grep -q "^lxc.mount.entry: /dev/dri " "$CONFIG_FILE" || \ - echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >> "$CONFIG_FILE" - msg_ok "$(translate 'iGPU configuration added to container') $CONTAINER_ID." + } -# Install iGPU drivers in the container install_igpu_in_container() { msg_info2 "$(translate 'Installing iGPU drivers inside the container...')" tput sc LOG_FILE=$(mktemp) - #msg_info "$(translate 'Installing iGPU drivers...')" + pct start "$CONTAINER_ID" >/dev/null 2>&1 script -q -c "pct exec \"$CONTAINER_ID\" -- bash -c ' set -e + getent group video >/dev/null || groupadd -g 44 video + getent group render >/dev/null || groupadd -g 104 render + usermod -aG video,render root || true + apt-get update >/dev/null 2>&1 apt-get install -y va-driver-all ocl-icd-libopencl1 intel-opencl-icd vainfo intel-gpu-tools - chgrp video /dev/dri && chmod 755 /dev/dri - adduser root video && adduser root render + + chgrp video /dev/dri 2>/dev/null || true + chmod 755 /dev/dri 2>/dev/null || true '" "$LOG_FILE" if [ $? -eq 0 ]; then @@ -193,6 +193,7 @@ install_igpu_in_container() { select_container show_proxmenux_logo +msg_title "$(translate "Add HW iGPU acceleration to an LXC")" configure_lxc_for_igpu install_igpu_in_container