From f8a940fb959deaaab851cf6a4058d0d63050d4e9 Mon Sep 17 00:00:00 2001 From: Tatsuya Ishikawa <34103899+tatsuyai713@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:59:45 +0900 Subject: [PATCH] Update print statement from 'Hello' to 'Goodbye' --- files/linuxserver-kde.base.dockerfile | 848 +++++++------------------- 1 file changed, 224 insertions(+), 624 deletions(-) diff --git a/files/linuxserver-kde.base.dockerfile b/files/linuxserver-kde.base.dockerfile index 8413372f..a664d10a 100644 --- a/files/linuxserver-kde.base.dockerfile +++ b/files/linuxserver-kde.base.dockerfile @@ -1,642 +1,242 @@ -# syntax=docker/dockerfile:1 +#!/usr/bin/with-contenv bash -########################################### -# Stage 1: Alpine rootfs builder -########################################### -FROM alpine:3.21 AS alpine-rootfs-stage +TARGET_USER="${CUSTOM_USER:-${USER_NAME:-root}}" +PORT="${SELKIES_PORT:-8082}" -ARG S6_OVERLAY_VERSION="3.2.1.0" -ARG ROOTFS=/root-out -ARG REL=v3.21 -ARG ALPINE_ARCH=x86_64 -ARG S6_OVERLAY_ARCH=x86_64 -ARG MIRROR=http://dl-cdn.alpinelinux.org/alpine -ARG PACKAGES=alpine-baselayout,alpine-keys,apk-tools,busybox,libc-utils +# Use selkies-gstreamer when GPU is available (nvidia/intel/amd), fallback to legacy selkies +# GPU_VENDOR is passed from start-container.sh: none|nvidia|intel|amd +GPU_VENDOR="${GPU_VENDOR:-none}" -# install packages -RUN \ - apk add --no-cache bash xz +# Check if running in WSL environment +WSL_ENVIRONMENT="${WSL_ENVIRONMENT:-false}" -# build rootfs -RUN \ - mkdir -p "${ROOTFS}/etc/apk" && \ - { \ - echo "${MIRROR}/${REL}/main"; \ - echo "${MIRROR}/${REL}/community"; \ - } > "${ROOTFS}/etc/apk/repositories" && \ - apk --root "${ROOTFS}" --no-cache --keys-dir /etc/apk/keys add --arch ${ALPINE_ARCH} --initdb ${PACKAGES//,/ } && \ - sed -i -e 's/^root::/root:!:/' /root-out/etc/shadow +# Use SELKIES_ENCODER from environment (set by start-container.sh based on GPU_VENDOR) +# This is more reliable than --encoder command line argument +export SELKIES_ENCODER="${SELKIES_ENCODER:-x264enc}" -# add s6 overlay -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-noarch.tar.xz -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz +# Export GStreamer debug level +export GST_DEBUG="${GST_DEBUG:-*:2}" -# add s6 optional symlinks -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-noarch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-noarch.tar.xz && unlink /root-out/usr/bin/with-contenv -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-arch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-arch.tar.xz +# Export LIBVA_DRIVER_NAME for Intel/AMD VA-API (set by start-container.sh) +if [ -n "${LIBVA_DRIVER_NAME}" ]; then + export LIBVA_DRIVER_NAME + echo "[svc-selkies] Using VA-API driver: ${LIBVA_DRIVER_NAME}" +fi +# Load GStreamer env if present (for selkies-gstreamer) and export all variables +if [ -f /opt/gstreamer/gst-env ]; then + # shellcheck source=/opt/gstreamer/gst-env + . /opt/gstreamer/gst-env + export PATH LD_LIBRARY_PATH GST_PLUGIN_PATH GST_PLUGIN_SYSTEM_PATH GI_TYPELIB_PATH PYTHONPATH GSTREAMER_PATH +fi -########################################### -# Stage 2: Ubuntu rootfs builder -########################################### -FROM alpine:3 AS ubuntu-rootfs-stage +# WSL2 specific setup for NVIDIA - add WSL libs to paths AFTER gst-env +# Must be after gst-env because it prepends /opt/gstreamer to LD_LIBRARY_PATH +# We need /usr/lib/wsl/lib at the FRONT for CUDA runtime libraries +if [ "${WSL_ENVIRONMENT}" = "true" ]; then + echo "[svc-selkies] Running in WSL2 environment" + if [ -d "/usr/lib/wsl/lib" ]; then + # Remove /usr/lib/wsl/lib if already present, then add to front + LD_LIBRARY_PATH="${LD_LIBRARY_PATH//\/usr\/lib\/wsl\/lib:/}" + LD_LIBRARY_PATH="${LD_LIBRARY_PATH//\/usr\/lib\/wsl\/lib/}" + export LD_LIBRARY_PATH="/usr/lib/wsl/lib:${LD_LIBRARY_PATH}" + export PATH="/usr/lib/wsl/lib:${PATH}" + echo "[svc-selkies] Added WSL library path at front: /usr/lib/wsl/lib" + echo "[svc-selkies] Final LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}" + fi +fi -ARG UBUNTU_ARCH=amd64 -ARG UBUNTU_REL -ARG UBUNTU_TAG -ENV REL=${UBUNTU_REL} -ENV ARCH=${UBUNTU_ARCH} -ENV TAG=${UBUNTU_TAG} +# Clear GStreamer cache to ensure encoder changes take effect +rm -rf "${HOME}/.cache/gstreamer-1.0" 2>/dev/null || true -# install packages -RUN \ - apk add --no-cache bash curl git jq tzdata xz +# Function to find nvidia-smi (handles WSL2 where it's in /usr/lib/wsl/lib) +find_nvidia_smi() { + if command -v nvidia-smi &> /dev/null; then + echo "nvidia-smi" + elif [ -x "/usr/lib/wsl/lib/nvidia-smi" ]; then + echo "/usr/lib/wsl/lib/nvidia-smi" + else + return 1 + fi +} -# grab base tarball -RUN \ - git clone --depth=1 https://git.launchpad.net/cloud-images/+oci/ubuntu-base -b ${TAG} /build && \ - cd /build/oci && \ - DIGEST=$(jq -r '.manifests[0].digest[7:]' < index.json) && \ - cd /build/oci/blobs/sha256 && \ - if jq -e '.layers // empty' < "${DIGEST}" >/dev/null 2>&1; then \ - TARBALL=$(jq -r '.layers[0].digest[7:]' < ${DIGEST}); \ - else \ - MULTIDIGEST=$(jq -r ".manifests[] | select(.platform.architecture == \"${ARCH}\") | .digest[7:]" < ${DIGEST}) && \ - TARBALL=$(jq -r '.layers[0].digest[7:]' < ${MULTIDIGEST}); \ - fi && \ - mkdir /root-out && \ - tar xf ${TARBALL} -C /root-out && \ - rm -rf \ - /root-out/var/log/* \ - /root-out/home/ubuntu \ - /root-out/root/{.ssh,.bashrc,.profile} \ - /build +# Check if NVIDIA GPU is available (works on both native Linux and WSL2) +nvidia_available() { + local nvidia_smi_cmd + nvidia_smi_cmd=$(find_nvidia_smi) || return 1 + "${nvidia_smi_cmd}" >/dev/null 2>&1 +} -# set version for s6 overlay -ARG S6_OVERLAY_VERSION="3.2.1.0" -ARG S6_OVERLAY_ARCH="x86_64" - -# add s6 overlay -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-noarch.tar.xz -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz - -# add s6 optional symlinks -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-noarch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-noarch.tar.xz && unlink /root-out/usr/bin/with-contenv -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-arch.tar.xz /tmp -RUN tar -C /root-out -Jxpf /tmp/s6-overlay-symlinks-arch.tar.xz - - -########################################### -# Stage 3: Ubuntu base temp -########################################### -FROM scratch AS ubuntu-base-temp - -COPY --from=ubuntu-rootfs-stage /root-out/ / - -ARG VERSION -ARG MODS_VERSION="v3" -ARG PKG_INST_VERSION="v1" -ARG LSIOWN_VERSION="v1" -ARG WITHCONTENV_VERSION="v1" - -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/docker-mods.${MODS_VERSION}" "/docker-mods" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/package-install.${PKG_INST_VERSION}" "/etc/s6-overlay/s6-rc.d/init-mods-package-install/run" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/lsiown.${LSIOWN_VERSION}" "/usr/bin/lsiown" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/with-contenv.${WITHCONTENV_VERSION}" "/usr/bin/with-contenv" - -ARG DEBIAN_FRONTEND="noninteractive" -ENV HOME="/root" \ - LANGUAGE="en_US.UTF-8" \ - LANG="en_US.UTF-8" \ - TERM="xterm" \ - S6_CMD_WAIT_FOR_SERVICES_MAXTIME="0" \ - S6_VERBOSITY=1 \ - S6_STAGE2_HOOK=/docker-mods \ - VIRTUAL_ENV=/lsiopy \ - PATH="/lsiopy/bin:$PATH" - -# Generate sources.list dynamically based on UBUNTU_REL and arch -ARG UBUNTU_REL -ARG UBUNTU_ARCH -RUN \ - echo "**** Generating sources.list for ${UBUNTU_REL} (${UBUNTU_ARCH}) ****" && \ - if [ "${UBUNTU_ARCH}" = "amd64" ]; then \ - MIRROR="http://archive.ubuntu.com/ubuntu"; \ - else \ - MIRROR="http://ports.ubuntu.com/ubuntu-ports"; \ - fi && \ - echo "deb ${MIRROR} ${UBUNTU_REL} main restricted" > /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL} main restricted" >> /etc/apt/sources.list && \ - echo "deb ${MIRROR} ${UBUNTU_REL}-updates main restricted" >> /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL}-updates main restricted" >> /etc/apt/sources.list && \ - echo "deb ${MIRROR} ${UBUNTU_REL} universe multiverse" >> /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL} universe multiverse" >> /etc/apt/sources.list && \ - echo "deb ${MIRROR} ${UBUNTU_REL}-updates universe multiverse" >> /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL}-updates universe multiverse" >> /etc/apt/sources.list && \ - echo "deb ${MIRROR} ${UBUNTU_REL}-security main restricted" >> /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL}-security main restricted" >> /etc/apt/sources.list && \ - echo "deb ${MIRROR} ${UBUNTU_REL}-security universe multiverse" >> /etc/apt/sources.list && \ - echo "deb-src ${MIRROR} ${UBUNTU_REL}-security universe multiverse" >> /etc/apt/sources.list - -RUN \ - echo "**** Ripped from Ubuntu Docker Logic ****" && \ - rm -f /etc/apt/sources.list.d/ubuntu.sources && \ - set -xe && \ - echo '#!/bin/sh' > /usr/sbin/policy-rc.d && \ - echo 'exit 101' >> /usr/sbin/policy-rc.d && \ - chmod +x /usr/sbin/policy-rc.d && \ - dpkg-divert --local --rename --add /sbin/initctl && \ - cp -a /usr/sbin/policy-rc.d /sbin/initctl && \ - sed -i 's/^exit.*/exit 0/' /sbin/initctl && \ - echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup && \ - echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean && \ - echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean && \ - echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean && \ - echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages && \ - echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes && \ - echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests && \ - mkdir -p /run/systemd && \ - echo 'docker' > /run/systemd/container && \ - echo "**** install apt-utils and locales ****" && \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y apt-utils locales && \ - echo "**** install packages ****" && \ - apt-get install -y \ - bc catatonit cron curl gnupg jq netcat-openbsd systemd-standalone-sysusers tzdata && \ - echo "**** generate locale ****" && \ - locale-gen en_US.UTF-8 && \ - echo "**** prepare shared folders ****" && \ - mkdir -p /app /config /defaults /lsiopy && \ - echo "**** create video and render groups with standard GIDs ****" && \ - groupadd -g 44 video 2>/dev/null || groupmod -g 44 video 2>/dev/null || true && \ - groupadd -g 106 render 2>/dev/null || groupmod -g 106 render 2>/dev/null || true && \ - echo "**** cleanup ****" && \ - id ubuntu >/dev/null 2>&1 && userdel ubuntu || echo "ubuntu user does not exist, skipping" && \ - apt-get autoremove && \ - apt-get clean && \ - rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/* /var/log/* - -# add local files for ubuntu base -COPY ubuntu-root/ / - - -########################################### -# Stage 4: Xvfb builder -########################################### -FROM ubuntu-base-temp AS xvfb-builder - -COPY /patches /patches -ENV PATCH_VERSION=21 \ - HOME=/config - -RUN \ - echo "**** build deps ****" && \ - apt-get update && \ - apt-get install -y devscripts dpkg-dev && \ - apt-get build-dep -y xorg-server - -RUN \ - echo "**** get and build xvfb ****" && \ - apt-get source xorg-server && \ - cd xorg-server-* && \ - cp /patches/${PATCH_VERSION}-xvfb-dri3.patch patch.patch && \ - patch -p0 < patch.patch && \ - awk ' \ - { print } \ - /include \/usr\/share\/dpkg\/architecture.mk/ { \ - print ""; \ - print "GLAMOR_DEP_LIBS := $(shell pkg-config --libs gbm epoxy libdrm)"; \ - print "GLAMOR_DEP_CFLAGS := $(shell pkg-config --cflags gbm epoxy libdrm)"; \ - print "export DEB_LDFLAGS_PREPEND ?= $(GLAMOR_DEP_LIBS)"; \ - print "export DEB_CFLAGS_PREPEND ?= $(GLAMOR_DEP_CFLAGS)"; \ - } \ - ' debian/rules > debian/rules.tmp && mv debian/rules.tmp debian/rules && \ - debuild -us -uc -b && \ - mkdir -p /build-out/usr/bin && \ - mv debian/xvfb/usr/bin/Xvfb /build-out/usr/bin/ - - -########################################### -# Stage 5: Alpine base temp -########################################### -FROM alpine-rootfs-stage AS alpine-base-temp - -COPY --from=alpine-rootfs-stage /root-out/ / - -ARG BUILD_DATE -ARG VERSION -ARG MODS_VERSION="v3" -ARG PKG_INST_VERSION="v1" -ARG LSIOWN_VERSION="v1" -ARG WITHCONTENV_VERSION="v1" - -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/docker-mods.${MODS_VERSION}" "/docker-mods" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/package-install.${PKG_INST_VERSION}" "/etc/s6-overlay/s6-rc.d/init-mods-package-install/run" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/lsiown.${LSIOWN_VERSION}" "/usr/bin/lsiown" -ADD --chmod=755 "https://raw.githubusercontent.com/linuxserver/docker-mods/mod-scripts/with-contenv.${WITHCONTENV_VERSION}" "/usr/bin/with-contenv" - -ENV PS1="$(whoami)@$(hostname):$(pwd)\\$ " \ - HOME="/root" \ - TERM="xterm" \ - S6_CMD_WAIT_FOR_SERVICES_MAXTIME="0" \ - S6_VERBOSITY=1 \ - S6_STAGE2_HOOK=/docker-mods \ - VIRTUAL_ENV=/lsiopy \ - PATH="/lsiopy/bin:$PATH" - -RUN \ - echo "**** install runtime packages ****" && \ - apk add --no-cache \ - alpine-release bash ca-certificates catatonit coreutils curl findutils jq \ - netcat-openbsd procps-ng shadow tzdata && \ - echo "**** prepare shared folders ****" && \ - mkdir -p /app /config /defaults /lsiopy && \ - echo "**** cleanup ****" && \ - rm -rf /tmp/* - -# add local files for alpine base -COPY alpine-root/ / - - -########################################### -# Stage 6: Selkies frontend builder -########################################### -FROM alpine-base-temp AS frontend - -RUN \ - echo "**** install build packages ****" && \ - apk add cmake git nodejs npm - -RUN \ - echo "**** ingest code ****" && \ - git clone https://github.com/selkies-project/selkies.git /src && \ - cd /src && \ - git checkout -f f1ade4dd700bf0157bb78a8a58eab42fbb8f02ee - -RUN \ - echo "**** build shared core library ****" && \ - cd /src/addons/gst-web-core && \ - npm install && \ - npm run build && \ - echo "**** build multiple dashboards ****" && \ - DASHBOARDS="selkies-dashboard selkies-dashboard-zinc selkies-dashboard-wish" && \ - mkdir /buildout && \ - for DASH in $DASHBOARDS; do \ - cd /src/addons/$DASH && \ - cp ../gst-web-core/dist/selkies-core.js src/ && \ - npm install && \ - npm run build && \ - mkdir -p dist/src dist/nginx && \ - cp ../gst-web-core/dist/selkies-core.js dist/src/ && \ - cp ../universal-touch-gamepad/universalTouchGamepad.js dist/src/ && \ - cp ../gst-web-core/nginx/* dist/nginx/ && \ - cp -r ../gst-web-core/dist/jsdb dist/ && \ - mkdir -p /buildout/$DASH && \ - cp -ar dist/* /buildout/$DASH/; \ - done - - -########################################### -# Stage 7: Selkies base image -########################################### -FROM ubuntu-base-temp AS selkies-base - -# set version label -ARG VERSION -LABEL build_version="Linuxserver.io version:- ${VERSION}" -LABEL maintainer="thelamer" - -# env -ENV DISPLAY=:1 \ - PERL5LIB=/usr/local/bin \ - HOME=/config \ - START_DOCKER=true \ - PULSE_RUNTIME_PATH=/defaults \ - SELKIES_INTERPOSER=/usr/lib/selkies_joystick_interposer.so \ - NVIDIA_DRIVER_CAPABILITIES=all \ - DISABLE_ZINK=false \ - DISABLE_DRI3=false \ - DPI=96 \ - TITLE=Selkies - -ARG APT_EXTRA_PACKAGES="" -ARG LIBVA_DEB_URL="https://launchpad.net/ubuntu/+source/libva/2.22.0-3ubuntu2/+build/30591127/+files/libva2_2.22.0-3ubuntu2_amd64.deb" -# Optional: jammy-friendly libva deb (built against glibc 2.35). Leave empty to skip on 22.04. -ARG LIBVA_DEB_URL_JAMMY="http://launchpadlibrarian.net/587480468/libva2_2.14.0-1_amd64.deb" -ARG LIBVA_LIBDIR="/usr/lib/x86_64-linux-gnu" -ARG PROOT_ARCH="x86_64" -ARG SELKIES_VERSION="1.6.2" -ARG VIRTUALGL_VERSION="3.1.4" - -RUN \ - echo "**** dev deps ****" && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3-dev && \ - echo "**** enable locales ****" && \ - sed -i '/locale/d' /etc/dpkg/dpkg.cfg.d/excludes && \ - echo "**** install docker ****" && \ - unset VERSION && \ - curl https://get.docker.com | sh && \ - echo "**** install deps ****" && \ - curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get update && \ - echo "**** determine Ubuntu version-specific packages ****" && \ - UBUNTU_VERSION=$(lsb_release -rs 2>/dev/null || grep VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"') && \ - LABWC_PKG="" && \ - MESA_GALLIUM_PKG="" && \ - if [ "$(echo "${UBUNTU_VERSION}" | cut -d. -f1)" -ge 24 ]; then \ - LABWC_PKG="labwc" && \ - MESA_GALLIUM_PKG="mesa-libgallium"; \ - fi && \ - echo "**** Installing packages (Ubuntu ${UBUNTU_VERSION}) ****" && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ - breeze-cursor-theme ca-certificates cmake console-data dbus-x11 \ - dunst file \ - fonts-noto-cjk fonts-noto-color-emoji fonts-noto-core foot fuse-overlayfs \ - g++ gcc git ${APT_EXTRA_PACKAGES} kbd ${LABWC_PKG} libatk1.0-0 libatk-bridge2.0-0 \ - libev4 libfontenc1 libfreetype6 libgbm1 libgcrypt20 libgirepository-1.0-1 \ - libgl1-mesa-dri libglu1-mesa libgnutls30 libgtk-3.0 libjpeg-turbo8 \ - libnginx-mod-http-fancyindex libnotify-bin libnss3 libnvidia-egl-wayland1 \ - libopus0 libp11-kit0 libpam0g libtasn1-6 libvulkan1 libwayland-client0 \ - libwayland-cursor0 libwayland-egl1 libwayland-server0 libx11-6 \ - libxau6 libxcb1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 \ - libxcursor1 libxdmcp6 libxext6 libxfconf-0-3 libxfixes3 libxfont2 libxinerama1 \ - libxkbcommon-dev libxkbcommon-x11-0 libxshmfence1 libxtst6 locales-all make \ - ${MESA_GALLIUM_PKG} mesa-va-drivers mesa-vulkan-drivers mesa-utils vainfo vdpauinfo \ - libvulkan-dev ocl-icd-libopencl1 clinfo libdrm2 libegl1 libgl1 libopengl0 libgles1 libgles2 \ - libglvnd0 libglx0 libglu1 libglvnd-dev \ - nginx openbox openssh-client \ - openssl pciutils procps psmisc pulseaudio pulseaudio-utils python3 python3-venv \ - gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav \ - gstreamer1.0-vaapi \ - bash-completion software-properties-common ssl-cert stterm sudo tar util-linux vulkan-tools \ - wl-clipboard wtype x11-apps x11-common x11-utils x11-xkb-utils x11-xserver-utils \ - xauth xclip xcvt xdg-utils xdotool xfconf xfonts-base xkb-data xsel \ - xserver-common xserver-xorg-core xserver-xorg-video-amdgpu xserver-xorg-video-ati \ - xserver-xorg-video-nouveau xserver-xorg-video-qxl xserver-xorg-video-dummy \ - xsettingsd xterm xutils xvfb zlib1g zstd && \ - echo "**** install coturn (AMD64 only) ****" && \ - ARCH_CUR=$(dpkg --print-architecture) && \ - if [ "${ARCH_CUR}" = "amd64" ]; then \ - apt-get install -y --no-install-recommends coturn; \ - fi && \ - echo "**** install Intel VA drivers (AMD64 only) ****" && \ - ARCH_CUR=$(dpkg --print-architecture) && \ - if [ "${ARCH_CUR}" = "amd64" ]; then \ - apt-get install -y --no-install-recommends i965-va-driver-shaders intel-media-va-driver-; \ - apt-get install -y --no-install-recommends intel-media-va-driver-non-free; \ - fi && \ - echo "**** install selkies ****" && \ - SELKIES_RELEASE=$(curl -sX GET "https://api.github.com/repos/selkies-project/selkies/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]') && \ - curl -o /tmp/selkies.tar.gz -L \ - "https://github.com/selkies-project/selkies/archive/f1ade4dd700bf0157bb78a8a58eab42fbb8f02ee.tar.gz" && \ - cd /tmp && \ - tar xf selkies.tar.gz && \ - cd selkies-* && \ - sed -i '/cryptography/d' pyproject.toml && \ - UBUNTU_VERSION="$(. /etc/os-release && echo ${VERSION_ID})" && \ - if [ "$(echo "${UBUNTU_VERSION}" | cut -d. -f1)" -lt 24 ]; then \ - echo "**** Ubuntu ${UBUNTU_VERSION}: removing xkbcommon dependency (not compatible) ****" && \ - sed -i '/xkbcommon/d' pyproject.toml; \ - fi && \ - python3 -m venv --system-site-packages /lsiopy && \ - pip install . && \ - pip install setuptools && \ - if [ "${UBUNTU_VERSION}" = "22.04" ]; then \ - echo "Installing pixelflux 1.4.7 for Ubuntu 22.04 (GLIBC 2.35)" && \ - pip install pixelflux==1.4.7; \ - elif [ "${UBUNTU_VERSION}" = "24.04" ]; then \ - echo "Installing pixelflux from selkies dependencies for Ubuntu 24.04" && \ - echo "pixelflux already installed"; \ - else \ - echo "Warning: Unknown Ubuntu version ${UBUNTU_VERSION}, using default pixelflux"; \ - fi && \ - echo "**** install selkies interposer ****" && \ - cd addons/js-interposer && \ - gcc -shared -fPIC -ldl -o selkies_joystick_interposer.so joystick_interposer.c && \ - mv selkies_joystick_interposer.so /usr/lib/selkies_joystick_interposer.so && \ - echo "**** install selkies fake udev ****" && \ - cd ../fake-udev && \ - make && \ - mkdir /opt/lib && \ - mv libudev.so.1.0.0-fake /opt/lib/ && \ - echo "**** add icon ****" && \ - mkdir -p /usr/share/selkies/www && \ - curl -o /usr/share/selkies/www/icon.png \ - https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/selkies-logo.png && \ - curl -o /usr/share/selkies/www/favicon.ico \ - https://raw.githubusercontent.com/linuxserver/docker-templates/refs/heads/master/linuxserver.io/img/selkies-icon.ico && \ - echo "**** openbox tweaks ****" && \ - sed -i \ - -e 's/NLIMC/NLMC/g' \ - -e '/debian-menu/d' \ - -e 's|| yes\n|' \ - -e 's|| \n|' \ - -e 's|4|1|' \ - /etc/xdg/openbox/rc.xml && \ - sed -i 's/--startup/--replace --startup/g' /usr/bin/openbox-session && \ - echo "**** user perms ****" && \ - sed -e 's/%sudo ALL=(ALL:ALL) ALL/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' -i /etc/sudoers && \ - echo "**** proot-apps ****" && \ - mkdir /proot-apps/ && \ - PAPPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/linuxserver/proot-apps/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]') && \ - curl -L https://github.com/linuxserver/proot-apps/releases/download/${PAPPS_RELEASE}/proot-apps-${PROOT_ARCH}.tar.gz \ - | tar -xzf - -C /proot-apps/ && \ - echo "${PAPPS_RELEASE}" > /proot-apps/pversion && \ - echo "**** dind support ****" && \ - useradd -U dockremap && \ - usermod -G dockremap dockremap && \ - echo 'dockremap:165536:65536' >> /etc/subuid && \ - echo 'dockremap:165536:65536' >> /etc/subgid && \ - curl -o /usr/local/bin/dind -L \ - https://raw.githubusercontent.com/moby/moby/master/hack/dind && \ - chmod +x /usr/local/bin/dind && \ - echo 'hosts: files dns' > /etc/nsswitch.conf && \ - groupadd -f docker && \ -echo "**** install VirtualGL ****" && \ - cd /tmp && VIRTUALGL_VERSION="$(echo ${VIRTUALGL_VERSION} | sed 's/[^0-9\.\-]*//g')" && \ - if [ "$(dpkg --print-architecture)" = "amd64" ]; then \ - dpkg --add-architecture i386 && \ - apt-get update && \ - curl -fsSL -O "https://github.com/VirtualGL/virtualgl/releases/download/${VIRTUALGL_VERSION}/virtualgl_${VIRTUALGL_VERSION}_amd64.deb" && \ - curl -fsSL -O "https://github.com/VirtualGL/virtualgl/releases/download/${VIRTUALGL_VERSION}/virtualgl32_${VIRTUALGL_VERSION}_amd64.deb" && \ - apt-get install -y --no-install-recommends "./virtualgl_${VIRTUALGL_VERSION}_amd64.deb" "./virtualgl32_${VIRTUALGL_VERSION}_amd64.deb" && \ - rm -f "virtualgl_${VIRTUALGL_VERSION}_amd64.deb" "virtualgl32_${VIRTUALGL_VERSION}_amd64.deb" && \ - chmod -f u+s /usr/lib/libvglfaker.so /usr/lib/libvglfaker-nodl.so /usr/lib/libvglfaker-opencl.so /usr/lib/libdlfaker.so /usr/lib/libgefaker.so 2>/dev/null || true && \ - chmod -f u+s /usr/lib32/libvglfaker.so /usr/lib32/libvglfaker-nodl.so /usr/lib32/libvglfaker-opencl.so /usr/lib32/libdlfaker.so /usr/lib32/libgefaker.so 2>/dev/null || true && \ - chmod -f u+s /usr/lib/i386-linux-gnu/libvglfaker.so /usr/lib/i386-linux-gnu/libvglfaker-nodl.so /usr/lib/i386-linux-gnu/libvglfaker-opencl.so /usr/lib/i386-linux-gnu/libdlfaker.so /usr/lib/i386-linux-gnu/libgefaker.so 2>/dev/null || true; \ - elif [ "$(dpkg --print-architecture)" = "arm64" ]; then \ - curl -fsSL -O "https://github.com/VirtualGL/virtualgl/releases/download/${VIRTUALGL_VERSION}/virtualgl_${VIRTUALGL_VERSION}_arm64.deb" && \ - apt-get update && apt-get install -y --no-install-recommends ./virtualgl_${VIRTUALGL_VERSION}_arm64.deb && \ - rm -f "virtualgl_${VIRTUALGL_VERSION}_arm64.deb" && \ - chmod -f u+s /usr/lib/libvglfaker.so /usr/lib/libvglfaker-nodl.so /usr/lib/libdlfaker.so /usr/lib/libgefaker.so 2>/dev/null || true; \ - fi && \ - echo "**** configure OpenCL and EGL for NVIDIA ****" && \ - mkdir -pm755 /etc/OpenCL/vendors && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd && \ - mkdir -pm755 /usr/share/glvnd/egl_vendor.d/ && echo '{\n\ - "file_format_version" : "1.0.0",\n\ - "ICD": {\n\ - "library_path": "libEGL_nvidia.so.0"\n\ - }\n\ -}' > /usr/share/glvnd/egl_vendor.d/10_nvidia.json && \ - echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \ - echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf && \ - UBUNTU_VERSION="$(. /etc/os-release && echo ${VERSION_ID})" && \ - UBUNTU_MAJOR="$(echo "${UBUNTU_VERSION}" | cut -d. -f1)" && \ - if [ "${UBUNTU_MAJOR}" -ge 24 ]; then \ - echo "**** libva hack (Ubuntu ${UBUNTU_VERSION}) ****" && \ - mkdir /tmp/libva && \ - curl -o /tmp/libva/libva.deb -L "${LIBVA_DEB_URL}" && \ - cd /tmp/libva && \ - ar x libva.deb && \ - tar xf data.tar.zst && \ - rm -f ${LIBVA_LIBDIR}/libva.so.2* && \ - cp -a usr/lib/${LIBVA_LIBDIR#/usr/lib/}/libva.so.2* ${LIBVA_LIBDIR}/; \ - elif [ -n "${LIBVA_DEB_URL_JAMMY}" ]; then \ - echo "**** libva hack (Ubuntu ${UBUNTU_VERSION}, jammy-compatible override) ****" && \ - mkdir /tmp/libva && \ - curl -o /tmp/libva/libva.deb -L "${LIBVA_DEB_URL_JAMMY}" && \ - cd /tmp/libva && \ - ar x libva.deb && \ - tar xf data.tar.zst && \ - rm -f ${LIBVA_LIBDIR}/libva.so.2* && \ - cp -a usr/lib/${LIBVA_LIBDIR#/usr/lib/}/libva.so.2* ${LIBVA_LIBDIR}/; \ - else \ - echo "**** skip libva hack on Ubuntu ${UBUNTU_VERSION} (use distro libva) ****"; \ - fi && \ - echo "**** locales ****" && \ - for LOCALE in $(curl -sL https://raw.githubusercontent.com/thelamer/lang-stash/master/langs); do \ - localedef -i $LOCALE -f UTF-8 $LOCALE.UTF-8; \ - done && \ - echo "**** theme ****" && \ - curl -s https://raw.githubusercontent.com/thelamer/lang-stash/master/theme.tar.gz \ - | tar xzvf - -C /usr/share/themes/Clearlooks/openbox-3/ && \ - echo "**** enable hardware encoders in selkies settings (arm64 only) ****" && \ - ARCH_CUR=$(dpkg --print-architecture) && \ - if [ "${ARCH_CUR}" != "amd64" ]; then \ - python3 -c "import selkies, pathlib; p = pathlib.Path(selkies.__file__).with_name('settings.py'); t = p.read_text(); old = \"['x264enc', 'x264enc-striped', 'jpeg']\"; new = \"['x264enc', 'x264enc-striped', 'jpeg', 'nvh264enc', 'vah264enc', 'vaapih264enc']\"; \ -assert old in t, f'Expected encoder list not found in {p}'; p.write_text(t.replace(old, new, 1)); print('Updated selkies encoder allowlist:', p)"; \ - fi && \ - echo "**** selkies-gstreamer (amd64 only) ****" && \ - ARCH_CUR=$(dpkg --print-architecture) && \ - if [ "${ARCH_CUR}" = "amd64" ]; then \ - UBUNTU_VERSION="$(. /etc/os-release && echo ${VERSION_ID})"; \ - BASE_URL="https://github.com/selkies-project/selkies/releases/download/v${SELKIES_VERSION}"; \ - mkdir -p /opt/gstreamer && \ - curl -fsSL "${BASE_URL}/gstreamer-selkies_gpl_v${SELKIES_VERSION}_ubuntu${UBUNTU_VERSION}_amd64.tar.gz" | tar -xzf - -C /opt && \ - cd /tmp && curl -O -fsSL "${BASE_URL}/selkies_gstreamer-${SELKIES_VERSION}-py3-none-any.whl" && \ - pip install --no-cache-dir "selkies_gstreamer-${SELKIES_VERSION}-py3-none-any.whl" && \ - rm -f "selkies_gstreamer-${SELKIES_VERSION}-py3-none-any.whl" && \ - curl -fsSL "${BASE_URL}/selkies-gstreamer-web_v${SELKIES_VERSION}.tar.gz" | tar -xzf - -C /opt && \ - echo "**** upgrade websockets to 15.x for selkies compatibility ****" && \ - pip install --force-reinstall 'websockets>=15.0'; \ - else \ - echo "Skipping selkies-gstreamer install on arch ${ARCH_CUR}"; \ - fi && \ - echo "**** cleanup ****" && \ - apt-get purge -y --autoremove python3-dev && \ - apt-get autoclean && \ - rm -rf /config/.cache /config/.npm /var/lib/apt/lists/* /var/tmp/* /tmp/* - -# add local files - this will overwrite ubuntu-root files if conflicts exist -COPY ubuntu-root/ / - -# Apply websockets 15.x compatibility patch for selkies-gstreamer (amd64 only) -RUN if [ "$(dpkg --print-architecture)" = "amd64" ] && [ -f /usr/local/bin/patch-selkies-websockets15.py ]; then \ - chmod +x /usr/local/bin/patch-selkies-websockets15.py && \ - python3 /usr/local/bin/patch-selkies-websockets15.py; \ +# Extract NVRTC dependency for NVIDIA (required for nvh264enc) +# https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvrtc/LICENSE.txt +if [ "${GPU_VENDOR}" = "nvidia" ] && nvidia_available; then + NVIDIA_SMI_CMD=$(find_nvidia_smi) + echo "[svc-selkies] NVIDIA GPU detected via: ${NVIDIA_SMI_CMD}" + + NVRTC_DEST_PREFIX="${NVRTC_DEST_PREFIX:-/opt/gstreamer}" + # Check if we can write to destination, otherwise use user home + if [ ! -w "${NVRTC_DEST_PREFIX}/lib" ]; then + NVRTC_DEST_PREFIX="${HOME}/.local/gstreamer" + mkdir -p "${NVRTC_DEST_PREFIX}/lib" 2>/dev/null + export LD_LIBRARY_PATH="${NVRTC_DEST_PREFIX}/lib:${LD_LIBRARY_PATH}" + echo "[svc-selkies] Using user-local NVRTC location: ${NVRTC_DEST_PREFIX}" + fi + + CUDA_DRIVER_SYSTEM="$("${NVIDIA_SMI_CMD}" --version | grep 'CUDA Version' | cut -d: -f2 | tr -d ' ')" + NVRTC_ARCH="${NVRTC_ARCH:-$(dpkg --print-architecture | sed -e 's/arm64/sbsa/' -e 's/ppc64el/ppc64le/' -e 's/i.*86/x86/' -e 's/amd64/x86_64/' -e 's/unknown/x86_64/')}" + # TEMPORARY: Cap CUDA version to 12.9 if the detected version is 13.0 or higher for NVRTC compatibility + # https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4655 + if [ -n "${CUDA_DRIVER_SYSTEM}" ]; then + CUDA_MAJOR_VERSION=$(echo "${CUDA_DRIVER_SYSTEM}" | cut -d. -f1) + if [ "${CUDA_MAJOR_VERSION}" -ge 13 ]; then + CUDA_DRIVER_SYSTEM="12.9" fi -COPY --from=frontend /buildout /usr/share/selkies -COPY --from=xvfb-builder /build-out/ / + fi + + # Download NVRTC if not already present + NVRTC_LIB_ARCH="$(dpkg --print-architecture | sed -e 's/arm64/aarch64-linux-gnu/' -e 's/armhf/arm-linux-gnueabihf/' -e 's/riscv64/riscv64-linux-gnu/' -e 's/ppc64el/powerpc64le-linux-gnu/' -e 's/s390x/s390x-linux-gnu/' -e 's/i.*86/i386-linux-gnu/' -e 's/amd64/x86_64-linux-gnu/' -e 's/unknown/x86_64-linux-gnu/')" + NVRTC_LIB_DIR="${NVRTC_DEST_PREFIX}/lib/${NVRTC_LIB_ARCH}" + + if [ ! -f "${NVRTC_LIB_DIR}/libnvrtc.so" ]; then + echo "[svc-selkies] Downloading NVRTC for CUDA ${CUDA_DRIVER_SYSTEM}..." + NVRTC_URL="https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvrtc/linux-${NVRTC_ARCH}/" + NVRTC_ARCHIVE="$(curl -fsSL "${NVRTC_URL}" 2>/dev/null | grep -oP "(?<=href=')cuda_nvrtc-linux-${NVRTC_ARCH}-${CUDA_DRIVER_SYSTEM}\.[0-9]+-archive\.tar\.xz" | sort -V | tail -n 1)" + if [ -z "${NVRTC_ARCHIVE}" ]; then + FALLBACK_VERSION="${CUDA_DRIVER_SYSTEM}.0" + NVRTC_ARCHIVE=$((curl -fsSL "${NVRTC_URL}" 2>/dev/null | grep -oP "(?<=href=')cuda_nvrtc-linux-${NVRTC_ARCH}-.*?\.tar\.xz" ; \ + echo "cuda_nvrtc-linux-${NVRTC_ARCH}-${FALLBACK_VERSION}-archive.tar.xz") | \ + sort -V | grep -B 1 --fixed-strings "${FALLBACK_VERSION}" | head -n 1) + fi + if [ -n "${NVRTC_ARCHIVE}" ]; then + echo "[svc-selkies] Selected NVRTC archive: ${NVRTC_ARCHIVE}" + mkdir -p "${NVRTC_LIB_DIR}" 2>/dev/null + cd /tmp && curl -fsSL "${NVRTC_URL}${NVRTC_ARCHIVE}" | tar -xJf - -C /tmp && \ + mv -f cuda_nvrtc* cuda_nvrtc && cd cuda_nvrtc/lib && \ + chmod -f 755 libnvrtc* 2>/dev/null && \ + rm -f "${NVRTC_LIB_DIR}/"libnvrtc* 2>/dev/null && \ + mv -f libnvrtc* "${NVRTC_LIB_DIR}/" 2>/dev/null && \ + cd /tmp && rm -rf /tmp/cuda_nvrtc && cd "${HOME}" + echo "[svc-selkies] NVRTC installed to ${NVRTC_LIB_DIR}" + else + echo "[svc-selkies] WARNING: Could not find a compatible NVRTC archive for CUDA ${CUDA_DRIVER_SYSTEM}" >&2 + fi + fi +fi -# Make TURN server script executable (AMD64 only, after final COPY) -RUN if [ "$(dpkg --print-architecture)" = "amd64" ]; then chmod 755 /etc/start-turnserver.sh; fi +if [ "${GPU_VENDOR}" != "none" ] && command -v selkies-gstreamer >/dev/null 2>&1; then + SELKIES_CMD="selkies-gstreamer" + # Build command options for selkies-gstreamer + # Note: Resolution and DPI are controlled by Xorg settings (DISPLAY_WIDTH, DISPLAY_HEIGHT, DPI environment variables) + # selkies-gstreamer will automatically detect and use the X display configuration + CMD_OPTS=(--addr="localhost" --port="${PORT}" --enable_basic_auth="false" --enable_resize="true" --enable_metrics_http="true" --metrics_http_port="${SELKIES_METRICS_HTTP_PORT:-9081}" --enable_clipboard="true") + + # Add TURN/STUN configuration if provided + if [ -n "${SELKIES_TURN_HOST}" ]; then + CMD_OPTS+=(--turn_host="${SELKIES_TURN_HOST}") + fi + if [ -n "${SELKIES_TURN_PORT}" ]; then + CMD_OPTS+=(--turn_port="${SELKIES_TURN_PORT}") + fi + if [ -n "${SELKIES_TURN_USERNAME}" ]; then + CMD_OPTS+=(--turn_username="${SELKIES_TURN_USERNAME}") + fi + if [ -n "${SELKIES_TURN_PASSWORD}" ]; then + CMD_OPTS+=(--turn_password="${SELKIES_TURN_PASSWORD}") + fi + if [ -n "${SELKIES_TURN_PROTOCOL}" ]; then + CMD_OPTS+=(--turn_protocol="${SELKIES_TURN_PROTOCOL}") + fi + if [ -n "${SELKIES_ENCODER}" ]; then + CMD_OPTS+=(--encoder="${SELKIES_ENCODER}") + fi + + if [ -n "${DISPLAY_WIDTH}" ] && [ -n "${DISPLAY_HEIGHT}" ]; then + echo "[svc-selkies] X Display resolution: ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" + fi + + if [ -n "${DPI}" ]; then + echo "[svc-selkies] X Display DPI: ${DPI}" + fi + + echo "[svc-selkies] GPU_VENDOR=${GPU_VENDOR}, using selkies-gstreamer with SELKIES_ENCODER=${SELKIES_ENCODER}" +else + SELKIES_CMD="selkies" + CMD_OPTS=(--addr="localhost" --mode="websockets" --port="${PORT}") + echo "[svc-selkies] GPU_VENDOR=${GPU_VENDOR}, using legacy selkies (WebSocket mode)" +fi -# ports and volumes -EXPOSE 3000 3001 -VOLUME /config +# Start local TURN server for selkies-gstreamer if TURN settings are provided via environment +if [ "${SELKIES_CMD}" = "selkies-gstreamer" ] && [ -n "${SELKIES_TURN_HOST}" ] && [ -n "${SELKIES_TURN_PASSWORD}" ]; then + echo "[svc-selkies] Starting local TURN server on port 3478 (external: ${SELKIES_TURN_HOST}:${SELKIES_TURN_PORT})" + /etc/start-turnserver.sh & +fi +# Default sink setup (wait until pulseaudio is ready, then create virtual sinks) +if [ ! -f '/dev/shm/audio.lock' ]; then + # ensure pulseaudio is up + for i in $(seq 1 30); do + if s6-setuidgid "$TARGET_USER" with-contenv pactl info >/dev/null 2>&1; then + READY=1 + break + fi + sleep 0.5 + done + if [ "${READY:-0}" -eq 1 ]; then + s6-setuidgid "$TARGET_USER" with-contenv pactl \ + load-module module-null-sink \ + sink_name="output" \ + sink_properties=device.description="output" + s6-setuidgid "$TARGET_USER" with-contenv pactl \ + load-module module-null-sink \ + sink_name="input" \ + sink_properties=device.description="input" + touch /dev/shm/audio.lock + else + echo "[svc-selkies] pulseaudio not ready; skipped null-sink setup (audio may be missing)." >&2 + fi +fi -########################################### -# Stage 8: Final webtop image -########################################### -FROM selkies-base +# Setup dev mode if defined +if [ ! -z ${DEV_MODE+x} ]; then + # Dev deps + apt-get update + apt-get install -y \ + nodejs + npm install -g nodemon + rm -Rf $HOME/.npm + # Frontend setup + if [[ "${DEV_MODE}" == "core" ]]; then + # Core just runs from directory + cd $HOME/src/addons/gst-web-core + s6-setuidgid "$TARGET_USER" npm install + s6-setuidgid "$TARGET_USER" npm run serve & + else + # Build core + cd $HOME/src/addons/gst-web-core + s6-setuidgid "$TARGET_USER" npm install + s6-setuidgid "$TARGET_USER" npm run build + s6-setuidgid "$TARGET_USER" cp dist/selkies-core.js ../${DEV_MODE}/src/ + s6-setuidgid "$TARGET_USER" nodemon --watch selkies-core.js --exec "npm run build && cp dist/selkies-core.js ../${DEV_MODE}/src/" & + # Copy touch gamepad + s6-setuidgid "$TARGET_USER" cp ../universal-touch-gamepad/universalTouchGamepad.js ../${DEV_MODE}/src/ + s6-setuidgid "$TARGET_USER" nodemon --watch ../universal-touch-gamepad/universalTouchGamepad.js --exec "cp ../universal-touch-gamepad/universalTouchGamepad.js ../${DEV_MODE}/src/" & + # Copy themes + s6-setuidgid "$TARGET_USER" cp -a nginx ../${DEV_MODE}/ + # Run passed frontend + cd $HOME/src/addons/${DEV_MODE} + s6-setuidgid "$TARGET_USER" npm install + s6-setuidgid "$TARGET_USER" npm run serve & + fi + # Run backend + cd $HOME/src/src + s6-setuidgid "$TARGET_USER" \ + nodemon -V --ext py --exec \ + "python3" -m selkies \ + --addr="localhost" \ + --mode="websockets" \ + --debug="true" +fi -# set version label -ARG VERSION -LABEL build_version="Linuxserver.io version:- ${VERSION}" -LABEL maintainer="thelamer" -ARG DEBIAN_FRONTEND="noninteractive" - -# title -ENV TITLE="Ubuntu KDE" \ - NO_GAMEPAD=true - -RUN \ - echo "**** add icon ****" && \ - curl -o /usr/share/selkies/www/icon.png \ - https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/webtop-logo.png && \ - echo "**** install packages ****" && \ - add-apt-repository ppa:xtradeb/apps && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ - bc chromium dolphin gwenview kde-config-gtk-style kdialog kfind khotkeys \ - kio-extras knewstuff-dialog konsole ksystemstats kubuntu-settings-desktop \ - kubuntu-wallpapers kubuntu-web-shortcuts kwin-addons kwin-x11 kwrite \ - plasma-desktop plasma-workspace qml-module-qt-labs-platform systemsettings kubuntu-desktop && \ - if [ "$(dpkg --print-architecture)" = "amd64" ]; then \ - echo "**** install latest google-chrome (amd64) ****" && \ - cd /tmp && \ - curl -fsSL -o google-chrome-stable.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y ./google-chrome-stable.deb && \ - rm -f /tmp/google-chrome-stable.deb; \ - fi && \ - echo "**** application tweaks ****" && \ - sed -i 's#^Exec=.*#Exec=/usr/local/bin/wrapped-chromium#g' \ - /usr/share/applications/chromium.desktop && \ - echo "**** kde tweaks ****" && \ - sed -i \ - 's/applications:org.kde.discover.desktop,/applications:org.kde.konsole.desktop,/g' \ - /usr/share/plasma/plasmoids/org.kde.plasma.taskmanager/contents/config/main.xml && \ - echo "**** cleanup ****" && \ - apt-get autoclean && \ - rm -rf /config/.cache /config/.launchpadlib /var/lib/apt/lists/* /var/tmp/* /tmp/* - -# Initialize bash-completion and command-not-found databases -# This ensures apt tab completion works properly -RUN apt-get update && \ - apt-get install -y apt-file command-not-found && \ - apt-file update && \ - /usr/lib/cnf-update-db && \ - # Disable docker-clean that prevents apt cache completion - rm -f /etc/apt/apt.conf.d/docker-clean && \ - # Configure apt to keep cache files for completion - mkdir -p /etc/apt/apt.conf.d && \ - echo 'Dir::Cache::pkgcache "/var/cache/apt/pkgcache.bin";' > /etc/apt/apt.conf.d/00-apt-cache-completion && \ - echo 'Dir::Cache::srcpkgcache "/var/cache/apt/srcpkgcache.bin";' >> /etc/apt/apt.conf.d/00-apt-cache-completion && \ - # Generate apt cache for package name completion - apt-cache gencaches && \ - chmod 644 /var/cache/apt/*.bin && \ - # Verify cache files were created - ls -la /var/cache/apt/*.bin - -# add local files for KDE webtop -COPY kde-root/ / - -# ports and volumes -EXPOSE 3000 -VOLUME /config - -ENTRYPOINT ["/init"] +# Start Selkies +echo "[svc-selkies] Starting ${SELKIES_CMD} on port ${PORT}" +exec s6-setuidgid "$TARGET_USER" "${SELKIES_CMD}" "${CMD_OPTS[@]}"