3 Commits

Author SHA1 Message Date
Josh.5
0ad203f89d Testing KasmVNC 2023-07-08 04:57:25 +12:00
Josh.5
63754aaed5 Start using Flatpaks as the main install method for any desktop apps 2023-07-08 02:59:43 +12:00
Josh.5
e717cd209f Improvements to running Xorg with NVIDIA 2023-07-07 15:59:48 +12:00
67 changed files with 954 additions and 1879 deletions

View File

@@ -18,10 +18,6 @@ jobs:
name: Build Docker Image
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
flavour: ["debian", "arch"]
steps:
# Fetch shallow git repository
@@ -47,35 +43,28 @@ jobs:
if: success()
id: prepare
run: |
FLAVOUR=${{ matrix.flavour }}
echo "FLAVOUR='${FLAVOUR}'"
echo "GITHUB_REF='${GITHUB_REF}'"
echo "GITHUB_REPOSITORY='${GITHUB_REPOSITORY}'"
echo "GITHUB_REF:${GITHUB_REF}"
echo "GITHUB_REPOSITORY:${GITHUB_REPOSITORY}"
DOCKER_IMAGE=docker.io/josh5/steam-headless
VERSION_TAG=${GITHUB_REF#refs/*/}
DOCKER_TAGS=""
if [[ ${VERSION_TAG%/merge} == 'master' ]]; then
if [[ ${FLAVOUR} == 'debian' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
fi
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR},"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
elif [[ ${VERSION_TAG%/merge} == 'staging' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-staging,"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:staging,"
elif [[ ${VERSION_TAG%/merge} =~ "dev-"* ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-${VERSION_TAG%/merge},"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION_TAG%/merge},"
fi
if [[ ${GITHUB_REF} == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
if [[ ${VERSION} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}[-\w]*$ ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-${VERSION},"
if [[ ${FLAVOUR} == 'debian' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
fi
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION},"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
fi
fi
echo "DOCKER_TAGS='${DOCKER_TAGS}'"
echo "Build: [$(date +"%F %T")] [${GITHUB_REF_NAME}] [${GITHUB_SHA}] [${FLAVOUR}]" > ./overlay/version.txt
echo "Build: [$(date +"%F %T")] [${GITHUB_REF_NAME}] [${GITHUB_SHA}]" > ./overlay/version.txt
DOCKER_PUSH="true"
if [[ ${DOCKER_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then
@@ -87,16 +76,11 @@ jobs:
if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then
DOCKER_PUSH="false"
fi
if [[ "X${DOCKER_TAGS}" == "X" ]]; then
DOCKER_PUSH="false"
fi
echo "DOCKER_PUSH='${DOCKER_PUSH}'"
cat ./overlay/version.txt
echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT
echo "docker_tags=$(echo ${DOCKER_TAGS} | sed 's/,$//')" >> $GITHUB_OUTPUT
echo "docker_platforms=linux/amd64" >> $GITHUB_OUTPUT
echo "docker_push=${DOCKER_PUSH}" >> $GITHUB_OUTPUT
echo ::set-output name=docker_image::${DOCKER_IMAGE}
echo ::set-output name=docker_tags::$(echo ${DOCKER_TAGS} | sed 's/,$//')
echo ::set-output name=docker_platforms::linux/amd64
echo ::set-output name=docker_push::${DOCKER_PUSH}
# Cache the build
- name: Cache Docker layers
@@ -104,9 +88,9 @@ jobs:
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ matrix.flavour }}-${{ github.sha }}
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ matrix.flavour }}-
${{ runner.os }}-buildx-
# Login to Docker Hub
- name: Login to Docker Hub
@@ -122,7 +106,7 @@ jobs:
uses: docker/build-push-action@v2
with:
context: .
file: Dockerfile.${{ matrix.flavour }}
file: Dockerfile
pull: true
platforms: ${{ steps.prepare.outputs.docker_platforms }}
push: ${{ steps.prepare.outputs.docker_push }}

View File

@@ -1,11 +1,11 @@
FROM debian:bookworm-slim
FROM debian:bullseye-slim
LABEL maintainer="Josh.5 <jsunnex@gmail.com>"
# Update package repos
ARG DEBIAN_FRONTEND=noninteractive
RUN \
echo "**** Update apt database ****" \
&& sed -i '/^Components: main/ s/$/ contrib non-free/' /etc/apt/sources.list.d/debian.sources \
&& sed -i '/^.*main/ s/$/ contrib non-free/' /etc/apt/sources.list \
&& \
echo
@@ -70,7 +70,6 @@ RUN \
mlocate \
nano \
net-tools \
p7zip-full \
patch \
pciutils \
pkg-config \
@@ -83,7 +82,6 @@ RUN \
unzip \
vim \
wget \
xmlstarlet \
xz-utils \
&& \
echo "**** Install python ****" \
@@ -92,7 +90,6 @@ RUN \
python3-numpy \
python3-pip \
python3-setuptools \
python3-venv \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
@@ -104,27 +101,6 @@ RUN \
&& \
echo
# Configure default user and set user env
ENV \
PUID=99 \
PGID=100 \
UMASK=000 \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
&& \
echo
# Install supervisor
RUN \
echo "**** Update apt database ****" \
@@ -145,8 +121,6 @@ RUN \
echo
# Install mesa and vulkan requirements
# TODO: Strip this section back to only what is required for all GPU types.
# Anything only required for Intel/AMD/NVIDIA should go in the container init.
RUN \
echo "**** Update apt database ****" \
&& dpkg --add-architecture i386 \
@@ -188,11 +162,6 @@ RUN \
echo
# Install X Server requirements
# TODO: Refine this list of packages to only what is required.
ENV \
XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
XDG_SESSION_TYPE="x11"
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
@@ -204,7 +173,6 @@ RUN \
libxcomposite-dev \
libxcursor1 \
wmctrl \
libfuse2 \
x11-utils \
x11-xfs-utils \
x11-xkb-utils \
@@ -213,7 +181,6 @@ RUN \
xauth \
xbindkeys \
xclip \
xcvt \
xdotool \
xfishtank \
xfonts-base \
@@ -225,6 +192,7 @@ RUN \
xserver-xorg-legacy \
xserver-xorg-video-all \
xserver-xorg-video-dummy \
xvfb \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
@@ -237,9 +205,6 @@ RUN \
echo
# Install audio requirements
ENV \
PULSE_SOCKET_DIR="/tmp/pulse" \
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
@@ -262,20 +227,17 @@ RUN \
echo
# Install desktop environment
# TODO: Specify all needed packages and add '--no-install-recommends'
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install desktop environment ****" \
&& apt-get install -y \
fonts-vlgothic \
gedit \
imagemagick \
msttcorefonts \
xdg-utils \
xfce4 \
xfce4-terminal \
msttcorefonts \
fonts-vlgothic \
gedit \
# Delete these as they are not needed at all
&& rm -f \
/usr/share/applications/software-properties-drivers.desktop \
@@ -285,26 +247,17 @@ RUN \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-mail-reader.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-web-browser.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/vim.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/pavucontrol.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/x11vnc.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/display-im6.q16.desktop \
# These are named specifically for Debain
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/debian-xterm.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/debian-uxterm.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/debian-xterm.desktop \
# Force these apps to be "System" Apps rather than "Categories=System;Utility;Core;GTK;Filesystem;"
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/xfce4-appfinder.desktop \
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/thunar-bulk-rename.desktop \
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/org.gnome.gedit.desktop \
&& \
echo "**** Install WoL Manager requirements ****" \
&& apt-get install -y \
tcpdump \
xprintidle \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
@@ -316,20 +269,23 @@ RUN \
echo
# Add support for flatpaks
ENV \
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install flatpak support ****" \
&& apt-get install -y --no-install-recommends \
&& apt-get install -y \
bridge-utils \
flatpak \
gnome-software-plugin-flatpak \
libpam-cgfs \
libvirt0 \
lxc \
uidmap \
&& \
echo "**** Configure flatpak ****" \
&& chmod u+s /usr/bin/bwrap \
&& flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo \
&& dpkg-statoverride --update --add root root 0755 /usr/bin/bwrap \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
@@ -341,48 +297,98 @@ RUN \
&& \
echo
# TODO: Deprecate neko
# Setup dind
# Ref:
# - https://github.com/docker-library/docker/blob/master/20.10/dind/Dockerfile
# - https://docs.nvidia.com/ai-enterprise/deployment-guide/dg-docker.html
ARG DOCKER_VERSION=20.10.18
ARG DOCKER_COMPOSE_VERSION=v2.11.2
RUN \
echo "**** Fetch Docker static binary package ****" \
&& cd /tmp \
&& wget -O /tmp/docker-${DOCKER_VERSION}.tgz \
https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \
&& \
echo "**** Extract static binaries ****" \
&& mkdir -p /usr/local/bin \
&& tar --extract \
--file /tmp/docker-${DOCKER_VERSION}.tgz \
--strip-components 1 \
--directory /usr/local/bin/ \
--no-same-owner \
&& \
echo "**** Install docker-compose ****" \
&& wget -O /usr/local/bin/docker-compose "https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-Linux-x86_64" \
&& chmod +x /usr/local/bin/docker-compose \
&& \
echo "**** Install nvidia runtime ****" \
&& distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add - \
&& curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | tee /etc/apt/sources.list.d/nvidia-docker.list \
&& apt-get update \
&& apt-get install -y \
nvidia-container-toolkit \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \
&& \
echo
VOLUME /var/lib/docker
# TODO: Deprecate neko and noVNC for KasmVNC
# Install Neko server
COPY --from=m1k1o/neko:base /usr/bin/neko /usr/bin/neko
COPY --from=m1k1o/neko:base /var/www /var/www
# Install Web Frontend
ARG FRONTEND_VERSION=a8eb92f
# Install noVNC
ARG NOVNC_VERSION=1.2.0
RUN \
echo "**** Fetch Web Frontend ****" \
echo "**** Fetch noVNC ****" \
&& cd /tmp \
&& wget -O /tmp/novnc.tar.gz https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.tar.gz \
&& \
echo "**** Extract noVNC ****" \
&& cd /tmp \
&& tar -xvf /tmp/novnc.tar.gz \
&& \
echo "**** Configure noVNC ****" \
&& cd /tmp/noVNC-${NOVNC_VERSION} \
&& sed -i 's/credentials: { password: password } });/credentials: { password: password },\n wsProtocols: ["'"binary"'"] });/g' app/ui.js \
&& mkdir -p /opt \
&& rm -rf /opt/noVNC \
&& cd /opt \
&& rm -rf /opt/frontend \
&& git clone https://github.com/Steam-Headless/frontend.git --branch master /opt/frontend \
&& cd /opt/frontend \
&& git checkout ${FRONTEND_VERSION} 2> /dev/null \
&& git submodule init \
&& git submodule update --depth 1 --recursive \
&& rm -rf /opt/frontend/.git \
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \
&& cd /opt/noVNC \
&& ln -s vnc.html index.html \
&& chmod -R 755 /opt/noVNC \
&& \
echo "**** Configure Web Frontend ****" \
&& echo '<!DOCTYPE html>' > /opt/frontend/index.html \
&& echo '<html><head><meta http-equiv="refresh" content="0;url=./web/"></head><body><p>If you are not redirected, <a href="./web/">click here</a>.</p></body></html>' >> /opt/frontend/index.html \
&& chmod -R 755 /opt/frontend \
&& convert /opt/frontend/web/images/icons/novnc-ios-180.png -resize "128x128" /tmp/steam-headless.png \
&& xdg-icon-resource install --novendor --size 128 /tmp/steam-headless.png \
echo "**** Modify noVNC title ****" \
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
/opt/noVNC/app/ui.js \
&& \
echo "**** Section cleanup ****" \
&& rm -f /tmp/steam-headless.png
# Install Websockify
ARG WEBSOCKETIFY_VERSION=0.11.0
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install Websockify dependencies ****" \
echo "**** Install nginx support ****" \
&& apt-get install -y \
python3-numpy \
python3-requests \
python3-jwcrypto \
python3-redis \
nginx \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/tmp/noVNC* \
/tmp/novnc.tar.gz
# Install Websockify
ARG WEBSOCKETIFY_VERSION=0.10.0
RUN \
echo "**** Fetch Websockify ****" \
&& cd /tmp \
&& wget -O /tmp/websockify.tar.gz https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.tar.gz \
@@ -391,15 +397,16 @@ RUN \
&& cd /tmp \
&& tar -xvf /tmp/websockify.tar.gz \
&& \
echo "**** Install Websockify to Web Frontend path ****" \
echo "**** Install Websockify to main ****" \
&& cd /tmp/websockify-${WEBSOCKETIFY_VERSION} \
&& python3 ./setup.py install \
&& \
echo "**** Install Websockify to noVNC path ****" \
&& cd /tmp \
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/frontend/utils/websockify \
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/tmp/websockify-* \
/tmp/websockify.tar.gz
@@ -453,26 +460,6 @@ RUN \
intel-media-va-driver-non-free \
i965-va-driver-shaders \
libva2 \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \
&& \
echo
# Install tools for monitoring hardware
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install useful HW monitoring tools ****" \
&& apt-get install -y --no-install-recommends \
cpu-x \
htop \
vainfo \
vdpauinfo \
&& \
@@ -486,58 +473,25 @@ RUN \
&& \
echo
# Install Sunshine
COPY --from=lizardbyte/sunshine:b00d7af-debian-bookworm /sunshine.deb /usr/src/sunshine.deb
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install Sunshine requirements ****" \
&& apt-get install -y \
va-driver-all \
&& \
echo "**** Install Sunshine ****" \
&& apt-get install -y \
/usr/src/sunshine.deb \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \
&& \
echo
# Install Steam
# Configure default user and set env
ENV \
PUID=99 \
PGID=100 \
UMASK=000 \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Update apt database ****" \
&& apt-get update \
&& \
echo "**** Install Steam ****" \
&& apt-get install -y --no-install-recommends \
steam \
&& ln -sf /usr/games/steam /usr/bin/steam \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \
&& \
echo
# Various other tools
ARG DUMB_INIT_VERSION=1.2.5
RUN \
echo "**** Install dumb-init ****" \
&& wget --no-check-certificate --no-cookies --quiet \
-O /usr/bin/dumb-init \
https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
&& chmod +x /usr/bin/dumb-init \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
&& \
echo
@@ -551,10 +505,17 @@ ENV \
DISPLAY_SIZEH="900" \
DISPLAY_SIZEW="1600" \
DISPLAY_VIDEO_PORT="DFP" \
DISPLAY=":55"
ENV \
DISPLAY=":55" \
NVIDIA_DRIVER_CAPABILITIES="all" \
NVIDIA_VISIBLE_DEVICES="all"
NVIDIA_VISIBLE_DEVICES="all" \
XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
# Set pulseaudio environment variables
ENV \
PULSE_SOCKET_DIR="/tmp/pulse" \
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
# Set container configuration environment variables
ENV \
@@ -563,14 +524,12 @@ ENV \
ENABLE_VNC_AUDIO="true" \
NEKO_PASSWORD=neko \
NEKO_PASSWORD_ADMIN=admin \
ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \
ENABLE_SUNSHINE="true" \
ENABLE_EVDEV_INPUTS="false" \
ENABLE_WOL_POWER_MANAGER="false"
ENABLE_SUNSHINE="false" \
ENABLE_EVDEV_INPUTS="false"
# Configure required ports
ENV \
PORT_SSH="" \
PORT_NOVNC_WEB="8083" \
NEKO_NAT1TO1=""

View File

@@ -34,7 +34,6 @@ RUN \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
@@ -42,25 +41,15 @@ RUN \
RUN \
echo "**** Install tools ****" \
&& pacman -Syu --noconfirm --needed \
base-devel \
bash \
bash-completion \
curl \
docbook-xml \
docbook-xsl \
fakeroot \
git \
jq \
less \
locate \
man-db \
nano \
net-tools \
pciutils \
pkg-config \
procps \
psmisc \
psutils \
rsync \
screen \
sudo \
@@ -78,42 +67,6 @@ RUN \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# Configure default user and set user env
ENV \
PUID=99 \
PGID=100 \
UMASK=000 \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
&& \
echo
# Install yay
RUN \
echo "**** Install Yay ****" \
&& pacman -Sy \
&& su - default -c 'git clone https://aur.archlinux.org/yay.git /tmp/yay && cd /tmp/yay && makepkg --noconfirm --syncdeps --install' \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -rf \
/tmp/yay* \
&& \
echo
@@ -125,7 +78,6 @@ RUN \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
@@ -138,7 +90,6 @@ RUN \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
@@ -150,20 +101,18 @@ RUN \
libva-mesa-driver \
mesa-utils \
mesa-vdpau \
opencl-mesa \
pciutils \
vulkan-mesa-layers \
vdpauinfo \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# Install X Server requirements
ENV \
XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run"
# TODO: Remove doubles
# TODO: Things that are not required
RUN \
echo "**** Install X Server requirements ****" \
&& pacman -Syu --noconfirm --needed \
@@ -190,106 +139,62 @@ RUN \
xorg-xrandr \
xorg-xsetroot \
xorg-xwininfo \
xterm \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# pacman -Syu --noconfirm --needed \
# xorg-server \
# xorg-server-xephyr \
# xorg-xwininfo \
# xorg-xhost \
# xorg-xinit \
# xorg-xinput \
# xorg-xrandr \
# xorg-xprop \
# xorg-xkill \
# xorg-xbacklight \
# xorg-xsetroot
# s
# pacman -Syu --noconfirm --needed autorandr xdg-desktop-portal xdg-desktop-portal-gtk wmctrl xbindkeys xdotool xautolock
#
#
# pacman -Syu --noconfirm --needed gestures
# pacman -Syu --noconfirm --needed numlockx
#
# echo 'Server = https://mirror.fsmg.org.nz/archlinux/$repo/os/$arch' >> /etc/pacman.d/mirrorlist
#
# Server = https://mirror.pkgbuild.com/$repo/os/$arch
# Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
# Server = https://mirror.leaseweb.net/archlinux/$repo/os/$arch
# Install audio requirements
ENV \
PULSE_SOCKET_DIR="/tmp/pulse" \
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
RUN \
echo "**** Install X Server requirements ****" \
&& pacman -Syu --noconfirm --needed \
alsa-utils \
pavucontrol \
pulseaudio \
pulseaudio-alsa \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# Install desktop environment
# TODO: Install equivelent of 'msttcorefonts' and 'fonts-vlgothic'
# Install openssh server
RUN \
echo "**** Install desktop environment ****" \
echo "**** Install openssh server ****" \
&& pacman -Syu --noconfirm --needed \
gedit \
xfce4 \
xfce4-goodies \
xfce4-terminal \
ttf-liberation \
# Delete these as they are not needed at all
&& rm -f \
/usr/share/applications/software-properties-drivers.desktop \
/usr/share/applications/xfce4-about.desktop \
/usr/share/applications/xfce4-session-logout.desktop \
# Hide these apps. They can be displayed if a user really wants them.
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-mail-reader.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/vim.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar-settings.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/pavucontrol.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/x11vnc.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xterm.desktop \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/uxterm.desktop \
# Force these apps to be "System" Apps rather than "Categories=System;Utility;Core;GTK;Filesystem;"
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/xfce4-appfinder.desktop \
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/thunar-bulk-rename.desktop \
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/org.gnome.gedit.desktop \
openssh \
&& echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# TODO: Add support for flatpaks
# Note: Debian Bullseye had bubblewrap v0.4.1 which worked fine in the Nvidia docker runtime
# At the moment this is only working beacuse /proc is being mounted again in 10-setup_user.sh
# Need to find a better solution for this...
ARG BUBBLEWRAP_VERSION=0.8.0
ENV \
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
RUN \
echo "**** Install flatpak support ****" \
&& pacman -Syu --noconfirm --needed \
flatpak \
gnome-software \
xdg-desktop-portal-gtk \
&& \
#echo "**** Build and install custom bubblewrap ****" \
# && cd /tmp \
# && wget -O /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz https://github.com/containers/bubblewrap/releases/download/v${BUBBLEWRAP_VERSION:?}/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz \
# && tar -xvf /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?}.tar.xz \
# && cd /tmp/bubblewrap-${BUBBLEWRAP_VERSION:?} \
# && sed -i 's|die ("Unexpected capabilities but not setuid, old file caps config?");|printf ("Unexpected capabilities but not setuid, old file caps config?");|' ./bubblewrap.c \
# && ./autogen.sh \
# && make clean \
# && make \
# && make install
#&& \
echo "**** Configure flatpak ****" \
&& chmod u-s /usr/bin/bwrap \
&& flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# Install noVNC
# TODO: Add nginx or remove the whole proxy setup and just connect directly for audio (I think that is the better option)
# TODO: Add nginx
ARG NOVNC_VERSION=1.2.0
RUN \
echo "**** Fetch noVNC ****" \
@@ -315,18 +220,10 @@ RUN \
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
/opt/noVNC/app/ui.js \
&& \
echo "**** Install nginx support ****" \
&& pacman -Syu --noconfirm --needed \
nginx \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -rf \
/tmp/noVNC* \
/tmp/novnc.tar.gz \
&& \
echo
/tmp/novnc.tar.gz
# Install Websockify
ARG WEBSOCKETIFY_VERSION=0.10.0
@@ -350,97 +247,175 @@ RUN \
echo "**** Section cleanup ****" \
&& rm -rf \
/tmp/websockify-* \
/tmp/websockify.tar.gz \
&& \
echo
/tmp/websockify.tar.gz
# Setup browser audio streaming deps
# Install firefox
# TODO: MOve under de
RUN \
echo "**** Install audio streaming deps ****" \
&& pacman -Syu --noconfirm --needed \
bzip2 \
gst-libav \
gst-plugins-bad \
gst-plugins-base \
gst-plugins-good \
gst-plugins-ugly \
&& \
echo "**** Fetch ucspi-tcp ****" \
&& mkdir -p /tmp/ucspi-tcp-0.88 \
&& cd /tmp \
#&& wget -O /tmp/ucspi-tcp.tar.gz https://github.com/trafficgate/ucspi-tcp/archive/refs/heads/master.tar.gz \
&& wget -O /tmp/ucspi-tcp.tar.gz http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz \
&& cd /tmp/ucspi-tcp-0.88 \
&& tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \
&& \
echo "**** Build and install ucspi-tcp ****" \
&& wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.errno.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.errno.patch \
&& wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.a_record.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.a_record.patch \
&& patch -p1 --input=ucspi-tcp-0.88.errno.patch \
&& patch -p1 --input=ucspi-tcp-0.88.a_record.patch \
&& sed -i 's|^/usr/local|/usr|' /tmp/ucspi-tcp-0.88/conf-home \
&& make \
&& for f in tcpserver tcprules tcprulescheck argv0 recordio tcpclient *\@ tcpcat mconnect mconnect-io addcr delcr fixcrio rblsmtpd; do \
cp $f /usr/bin/$f; \
done \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -rf \
/tmp/ucspi-tcp-* \
&& \
echo
# Install Steam
RUN \
echo "**** Install X Server requirements ****" \
echo "**** Install firefox ****" \
&& pacman -Syu --noconfirm --needed \
steam \
firefox \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# # Install Steam
# RUN \
# echo "**** Install steam ****" \
# && pacman -Syu --noconfirm --needed \
# lib32-vulkan-icd-loader
# steam \
# vulkan-icd-loader \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# Install desktop environment
RUN \
echo "**** Install desktop environment ****" \
&& pacman -Syu --noconfirm --needed \
gedit \
xfce4 \
xfce4-terminal \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& \
echo
# Add support for flatpaks
RUN \
echo "**** Install flatpak support ****" \
&& pacman -Syu --noconfirm --needed \
flatpak \
xdg-desktop-portal-gtk \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& \
echo
# TODO Append to tools
RUN \
echo "**** Install flatpak support ****" \
&& pacman -Syu --noconfirm --needed \
patch \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& \
echo
# # Install desktop environment
# RUN \
# echo "**** Install desktop environment ****" \
# && pacman -Syu --noconfirm --needed \
# kde-system-meta \
# konsole \
# plasma-desktop \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# # Install desktop environment
# RUN \
# echo "**** Install desktop environment ****" \
# && pacman -Syu --noconfirm --needed \
# cinnamon \
# polkit-gnome \
# gnome-terminal \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# # Setup browser audio streaming deps
# RUN \
# echo "**** Update apt database ****" \
# && apt-get update \
# && \
# echo "**** Install audio streaming deps ****" \
# && apt-get install -y --no-install-recommends \
# bzip2 \
# gstreamer1.0-alsa \
# gstreamer1.0-gl \
# gstreamer1.0-gtk3 \
# gstreamer1.0-libav \
# gstreamer1.0-plugins-base \
# gstreamer1.0-plugins-good \
# gstreamer1.0-pulseaudio \
# gstreamer1.0-qt5 \
# gstreamer1.0-tools \
# gstreamer1.0-x \
# libgstreamer1.0-0 \
# libncursesw5 \
# libopenal1 \
# libsdl-image1.2 \
# libsdl-ttf2.0-0 \
# libsdl1.2debian \
# libsndfile1 \
# ucspi-tcp \
# && \
# echo "**** Section cleanup ****" \
# && apt-get clean autoclean -y \
# && apt-get autoremove -y \
# && rm -rf \
# /var/lib/apt/lists/* \
# /var/tmp/* \
# /tmp/* \
# && \
# echo
# Configure default user and set env
ENV \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# Add FS overlay
COPY overlay /
RUN \
echo "**** Setup Steam Supervisor ****" \
&& sed -i 's#/usr/games/steam#/usr/bin/steam#g' /etc/supervisor.d/steam.ini \
&& \
echo
# Set display environment variables
ENV \
DISPLAY_CDEPTH="24" \
DISPLAY_REFRESH="120" \
DISPLAY_REFRESH="60" \
DISPLAY_SIZEH="900" \
DISPLAY_SIZEW="1600" \
DISPLAY_VIDEO_PORT="DFP" \
DISPLAY=":55"
ENV \
DISPLAY=":55" \
NVIDIA_DRIVER_CAPABILITIES="all" \
NVIDIA_VISIBLE_DEVICES="all"
# Set container configuration environment variables
ENV \
MODE="primary" \
WEB_UI_MODE="vnc" \
ENABLE_VNC_AUDIO="true" \
NEKO_PASSWORD=neko \
NEKO_PASSWORD_ADMIN=admin \
ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \
ENABLE_SUNSHINE="false" \
ENABLE_EVDEV_INPUTS="false"
ENABLE_VNC_AUDIO="true"
# Configure required ports
ENV \
PORT_NOVNC_WEB="8083" \
NEKO_NAT1TO1=""
PORT_SSH="" \
PORT_NOVNC_WEB="8083"
# Expose the required ports
EXPOSE 8083

View File

@@ -2,22 +2,14 @@
![](./images/banner.jpg)
Remote Game Streaming Server.
Play your games either in the browser with audio or via Steam Link or Moonlight. Play from another Steam Client with Steam Remote Play.
Easily deploy a Steam Docker instance in seconds.
Play your games in the browser with audio. Connect another device and use it with Steam Remote Play. Easily deploy a Steam Docker instance in seconds.
## Features:
- Steam Client configured for running on Linux with Proton
- Moonlight compatible server for easy remote desktop streaming
- One click installation of EmeDeck, Heroic and Lutris
- NVIDIA GPU support
- AMD GPU support
- Full video/audio noVNC web access to a Xfce4 Desktop
- NVIDIA, AMD and Intel GPU support
- Full controller support
- Support for Flatpak and Appimage installation
- Root access
- Based on Debian Bookworm
---
## Notes:

View File

@@ -10,6 +10,7 @@ TZ='Pacific/Auckland'
USER_LOCALES='en_US.UTF-8 UTF-8'
DISPLAY=':55'
SHM_SIZE='2G'
## DOCKER_RUNTIME:
## Options: ['runc', 'nvidia']
## Description: The name of an implementation of OCI Runtime Spec
@@ -30,20 +31,6 @@ PGID='1000'
UMASK='000'
USER_PASSWORD='password'
# __ __ _
# | \/ | ___ __| | ___
# | |\/| |/ _ \ / _` |/ _ \
# | | | | (_) | (_| | __/
# |_| |_|\___/ \__,_|\___|
#
#
## MODE:
## Options: ['primary', 'secondary']
## Description: Steam Headless containers can run in a secondary mode that will only start
## a Steam process that will then use the X server of either the host or another
## Steam Headless container running in 'primary' mode.
MODE='primary'
# ____ _
# / ___| ___ _ ____ _(_) ___ ___ ___
# \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __|
@@ -51,63 +38,54 @@ MODE='primary'
# |____/ \___|_| \_/ |_|\___\___||___/
#
#
# Mode
## MODE:
## Options: ['primary', 'secondary']
## Description: Steam Headless containers can run in a secondary mode that will only start
## a Steam process that will then use the X server of either the host or another
## Steam Headless container running in 'primary' mode.
MODE='primary'
# Web UI
## WEB_UI_MODE:
## Options: ['vnc', 'neko', 'none']
## Description: Configures the WebUI to use for accessing the virtual desktop.
## Supported Modes: ['primary']
## Options: ['vnc', 'neko', 'none']
## Description: Configures the WebUI to use for accessing the virtual desktop.
WEB_UI_MODE='vnc'
## ENABLE_VNC_AUDIO:
## Options: ['true', 'false']
## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'.
## Options: ['true', 'false']
## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'.
ENABLE_VNC_AUDIO='true'
## PORT_NOVNC_WEB:
## Description: Configure the port to use for the WebUI.
## Description: Configure the port to use for the WebUI.
PORT_NOVNC_WEB='8083'
## NEKO_NAT1TO1:
## Description: Configure nat1to1 for the neko WebUI if it is enabled by setting 'WEB_UI_MODE' to 'neko'.
## This will need to be the IP address of the host.
## Description: Configure nat1to1 for the neko WebUI if it is enabled by setting 'WEB_UI_MODE' to 'neko'. This will need to be the IP address of the host.
NEKO_NAT1TO1=''
# Steam
## ENABLE_STEAM:
## Options: ['true', 'false']
## Description: Enable Steam to run on start. This will also cause steam to restart automatically if closed.
## Supported Modes: ['primary', 'secondary']
ENABLE_STEAM='true'
## STEAM_ARGS:
## Description: Additional steam execution arguments.
#STEAM_ARGS='-silent -bigpicture'
# Sunshine
## ENABLE_SUNSHINE:
## Options: ['true', 'false']
## Description: Enable Sunshine streaming service.
## Supported Modes: ['primary']
## Options: ['true', 'false']
## Description: Enable Sunshine streaming service.
ENABLE_SUNSHINE='false'
## SUNSHINE_USER:
## Description: Set the Sunshine service username.
## Description: Set the Sunshine service username.
#SUNSHINE_USER='admin'
## SUNSHINE_PASS:
## Description: Set the Sunshine service password.
## Description: Set the Sunshine service password.
#SUNSHINE_PASS='admin'
# Xorg
## ENABLE_EVDEV_INPUTS:
## Available Options: ['true', 'false']
## Description: Enable Keyboard and Mouse Passthrough. This will configure the Xorg server to catch all
## evdev events for Keyboard, Mouse, etc.
## Supported Modes: ['primary']
## Options: ['true', 'false']
## Description: Enable Keyboard and Mouse Passthrough. This will configure the Xorg server to catch all evdev events for Keyboard, Mouse, etc.
ENABLE_EVDEV_INPUTS='true'
# Nvidia specific config (not required for non Nvidia GPUs)
## NVIDIA_DRIVER_CAPABILITIES:
## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display']
## Description: Controls which driver libraries/binaries will be mounted inside the container.
## Supported Modes: ['primary', 'secondary']
## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display']
## Description: Controls which driver libraries/binaries will be mounted inside the container.
NVIDIA_DRIVER_CAPABILITIES='all'
## NVIDIA_DRIVER_CAPABILITIES:
## Available Options: ['all', 'none', '<GPU UUID>']
## Description: Controls which GPUs will be made accessible inside the container.
## Supported Modes: ['primary', 'secondary']
## Options: ['all', 'none', '<GPU UUID>']
## Description: Controls which GPUs will be made accessible inside the container.
NVIDIA_VISIBLE_DEVICES='all'

View File

@@ -4,77 +4,47 @@ services:
image: josh5/steam-headless:latest
restart: unless-stopped
runtime: ${DOCKER_RUNTIME}
## NOTE: Requires privileged access to host to be able to access the required devices
privileged: true
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
cap_add:
- NET_ADMIN
- SYS_ADMIN
- SYS_NICE
security_opt:
- seccomp:unconfined
- apparmor:unconfined
# NETWORK:
## NOTE: Steam headless always requires the use of the host network.
## If we do not use the host network, then device input is not possible
## and your controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
networks:
external-macvlan:
ipv4_address: ${CONTAINER_IP_ADDRESS}
# ENVIRONMENT:
## Read all config variables from the .env file
env_file: .env
# DEVICES:
devices:
# Use the host fuse device.
- /dev/fuse
# Add the host uinput device.
- /dev/uinput
# Add AMD/Intel HW accelerated video encoding/decoding devices (optional)
#- /dev/dri
# Ensure container access to devices 13:*
device_cgroup_rules:
- 'c 13:* rmw'
# VOLUMES:
volumes:
# The location of your home directory.
- /opt/container-data/steam-headless/home/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- /mnt/games/:/mnt/games/:rw
# The Xorg socket. This will be shared with other containers so they can access the X server.
# Select only one option or leave commented out to not share the Xorg socket with any other Docker containers.
# Option #1) Start a X server in the container to share with any other containers.
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
# Option #2) Use an existing X server running on the host.
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
# Leave commented out to not share the pulse socket with any other Docker containers.
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro
# Host udev data required for input devices
- /run/udev/data/:/run/udev/data/:ro
# Store flatpak var files in a volume.
# The Xorg socket. This will be shared with other containers so they can access the X server.
- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
# Store dind var files in a volume
- steam-headless-var-lib-docker:/var/lib/docker/:rw
# Store flatpak var files in a volume
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
volumes:
steam-headless-var-lib-docker:
steam-headless-var-lib-flatpak:
networks:
external-macvlan:
external: true
name: ${NETWORK_NAME}

View File

@@ -1,56 +0,0 @@
---
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
runtime: ${DOCKER_RUNTIME}
## NOTE: This config uses privileged to access to host to be able to access the required devices
privileged: true
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
# NETWORK:
## NOTE: If we do not use the host network, then physical device input is not possible
## and your USB connected controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# ENVIRONMENT:
## Read all config variables from the .env file
env_file: .env
# VOLUMES:
volumes:
# The location of your home directory.
- /opt/container-data/steam-headless/home/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- /mnt/games/:/mnt/games/:rw
# The Xorg socket. This will be shared with other containers so they can access the X server.
# Select only one option:
# Option #1) Start a X server in the container to share with any other containers.
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
# Option #2) Use an existing X server running on the host.
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
# Leave commented out to not share the pulse socket with any other Docker containers.
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro
# Store flatpak var files in a volume.
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
volumes:
steam-headless-var-lib-flatpak:

View File

@@ -9,7 +9,7 @@ Follow these instructions to configure a docker-compose.yml for your system.
> Depending on how you have installed this, the commands to execute docker compose may vary.
## PREPARE DIRECTORIES:
## PREPARE DIRECTORY:
> __Warning__
>
@@ -18,96 +18,24 @@ Follow these instructions to configure a docker-compose.yml for your system.
> If you do run these commands as root, you may need to manually fix the permissions and ownership after.
Create a directory for your service:
```shell
```
sudo mkdir -p /opt/container-services/steam-headless
sudo chown -R $(id -u):$(id -g) /opt/container-services/steam-headless
```
Create a directory for your service config data:
```shell
```
sudo mkdir -p /opt/container-data/steam-headless/{home,.X11-unix,pulse}
sudo chown -R $(id -u):$(id -g) /opt/container-data/steam-headless
```
(Optional) Create a directory for your game install location:
```shell
sudo mkdir /mnt/games
sudo chmod -R 777 /mnt/games
sudo chown -R $(id -u):$(id -g) /mnt/games
```
Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file.
Populate this file with the contents of the default [Docker Compose File](./compose-files/docker-compose.default.yml).
## CONFIGURE HOST:
It is recommended that you configure this container to use a Macvlan network. If you know what you are doing, you can also use an IPvlan or Host, but I will not be covering that setup in this documentation.
To simplify the setup process and allow you to reuse the created Macvlan for other containers, we will create this Macvlan manually rather than have Docker compose handle it. If you know what you are doing with Docker compose and you would rather have the Macvlan managed there, feel free to do so. Otherwise run this command and carry on with the setup:
### 1) Discover your parent network:
To find the parent network device, run the command `ip address show`. Find the device that has the IP address of your Host server.
```
root@Tower:~# ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq master br0 state UP group default qlen 1000
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
4: eth0.1@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.1 state UP group default qlen 1000
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
5: eth0.3@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.3 state UP group default qlen 1000
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
6: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.43/24 brd 192.168.1.255 scope global dynamic noprefixroute br0
valid_lft 440sec preferred_lft 365sec
```
In this example output, I will select br0 as the parent network device which has the IP address of "192.168.1.43".
### 2) Create a macvlan Docker network
```
# Set the parent network device.
NETWORK_PARTENT=br0
# Name this whatever you like, but ensure you update the `.env` file below to match.
NETWORK_NAME=steam-headless-vlan
# Choose a network subnet and gateway that matches your host network
NETWORK_SUBNET=192.168.1.0/24
NETWORK_GATEWAY=192.168.1.1
# Execute the docker network create command
sudo docker network create -d macvlan \
--subnet=${NETWORK_SUBNET:?} \
--gateway=${NETWORK_GATEWAY:?} \
-o parent=${NETWORK_PARTENT:?} \
${NETWORK_NAME:?}
```
## CONFIGURE ENV:
Create a Steam Headless `/opt/container-services/steam-headless/.env` file with the contents found in this example [Environment File](./compose-files/.env).
Edit these variables as required.
## EXECUTE:
Navigate to your compose location and execute it.
```shell
cd /opt/container-services/steam-headless
sudo docker-compose up -d --force-recreate
```
After container executes successfully, navigate to your docker host URL in your browser on port 8083 and click connect.
http://<host-ip>:8083/
![img.png](../images/vnc_connect.png)
If using a `/mnt/games` volume mount, wait until Steam installs and executes, then restart the container. This step
is necessary to create the required steamapps folder in the /mnt/games volume after initial installation. If this
doesn't occur, you will receive a "disk write error" when trying to install to this location.

View File

@@ -1,25 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: games
spec:
storageClassName: ssd #Adjust your storageclass as needed
volumeMode: Filesystem
resources:
requests:
storage: 400Gi
accessModes:
- ReadWriteOnce
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: home
spec:
volumeMode: Filesystem
storageClassName: nvme-replicated #Adjust your storageclass as needed
resources:
requests:
storage: 50Gi
accessModes:
- ReadWriteOnce

View File

@@ -1,96 +0,0 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: steam-headless
spec:
serviceName: "steam-headless"
replicas: 1
selector:
matchLabels:
app: steam-headless
template:
metadata:
labels:
app: steam-headless
spec:
hostNetwork: true
securityContext:
fsGroup: 1000
containers:
- name: steam-headless
securityContext:
privileged: true
image: josh5/steam-headless:latest
resources: #Change CPU and Memory below
requests:
memory: "24G"
cpu: "6"
limits:
memory: "24G"
cpu: "6"
nvidia.com/gpu: 1 #If you're using a nvidia GPU, add it here
volumeMounts:
- name: home-dir
mountPath: /home/default/
- name: games-dir
mountPath: /mnt/games/
- name: input-devices
mountPath: /dev/input/
- name: dshm
mountPath: /dev/shm
env: #Environmental Vars
- name: NAME
value: 'SteamHeadless'
- name: TZ
value: 'America/New_York'
- name: USER_LOCALES
value: 'en_US.UTF-8 UTF-8'
- name: DISPLAY
value: ':55'
- name: SHM_SIZE
value: '2G'
- name: DOCKER_RUNTIME
value: 'nvidia'
- name: PUID
value: '1000'
- name: PGID
value: '1000'
- name: UMASK
value: '000'
- name: USER_PASSWORD
value: 'password' #changeme
- name: MODE
value: 'primary'
- name: WEB_UI_MODE
value: 'none'
- name: ENABLE_VNC_AUDIO
value: 'false'
- name: PORT_NOVNC_WEB
value: '8083'
- name: NEKO_NAT1TO1
value: ''
- name: ENABLE_SUNSHINE
value: 'true'
- name: SUNSHINE_USER
value: 'sam'
- name: SUNSHINE_PASS
value: 'password'
- name: ENABLE_EVDEV_INPUTS
value: 'true'
- name: NVIDIA_DRIVER_CAPABILITIES
value: 'all'
- name: NVIDIA_VISIBLE_DEVICES
value: 'all'
volumes:
- name: home-dir
persistentVolumeClaim:
claimName: home
- name: games-dir
persistentVolumeClaim:
claimName: games
- name: input-devices
hostPath:
path: /dev/input/
- name: dshm
emptyDir:
medium: Memory

View File

@@ -1,16 +0,0 @@
# Kubernetes
Have a cluster at home and want to add steam headless to it?
Requirements
- NVIDIA Device plugin (if using nvidia GPU) https://github.com/NVIDIA/k8s-device-plugin
- A storageclass
Tasks
1. Configure the statefulset to your liking. Things to note:
- CPU & Memory
- Env vars (see compose-files/.env for documentation)
2. Change the PVC to your liking. Things to note:
- Storage Class
- Size
3. Deploy it: `kubectl create -f k8s-files/*`

View File

@@ -1,30 +0,0 @@
## Flatpaks not working
Steam runs with Flatpak. These Flatpaks are instlled into the `default` user's home directory so they persist between container updates. Sometimes Flatpaks can get into a knot between major Steam Headless updates. In such cases, it may not work correctly. To fix this, just delete the Flatpak runtime in your `default` user's home directory a restart the container.
1) Stop the container.
2) Delete the directory `<SteamHeadless Home>/.local/share/flatpak`
3) Re-create the container. Don't just restart it. This will trigger an update of the required Flatpak runtimes in the home directory.
4) Reinstall any missing Flatpaks from the Software app.
Once your Flatpak refresh is complete, everything should work correctly and your configuration for each application should have remained intact.
## An error occurred while installing <game>: "disk write error"
![img.png](../images/disk_write_error.png)
1) Stop the container
2) Verify your mounted /mnt/games volume is owned by the executing UID/GID, and 777 permissions are set.
3) Verify the `steamapps` directory exists within the library location.
> __Note__
>
> The directory in the below commands are the default /mnt/games library locations installed upon first execution of this container.
>
> Depending on how you have installed this, the directory path may vary.
```shell
sudo mkdir /mnt/games/GameLibrary/SteamLibrary/steamapps
sudo chmod -R 777 /mnt/games
sudo chown -R $(id -u):$(id -g) /mnt/games
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -25,43 +25,41 @@ fi
# Execute all container init scripts
for init_script in /etc/cont-init.d/*.sh ; do
echo
echo -e "\e[34m[ ${init_script:?}: executing... ]\e[0m"
sed -i 's/\r$//' "${init_script:?}"
source "${init_script:?}"
echo "[ ${init_script}: executing... ]"
sed -i 's/\r$//' "${init_script}"
source "${init_script}"
done
touch /tmp/.first-run-init-scripts
# Execute any user generated init scripts
mkdir -p ${USER_HOME:?}/init.d
chown -R ${USER:?} ${USER_HOME:?}/init.d
for user_init_script in ${USER_HOME:?}/init.d/*.sh ; do
mkdir -p ${USER_HOME}/init.d
chown -R ${USER} ${USER_HOME}/init.d
for user_init_script in ${USER_HOME}/init.d/*.sh ; do
# Check that a file was found
# (If no files exist in this directory, then user_init_script will be empty)
if [[ -e "${user_init_script:?}" ]]; then
if [[ -e "${user_init_script}" ]]; then
echo
echo -e "\e[34m[ USER:${user_init_script:?}: executing... ]\e[0m"
sed -i 's/\r$//' "$(readlink -e "${user_init_script:?}")"
echo "[ USER:${user_init_script}: executing... ]"
sed -i 's/\r$//' "${user_init_script}"
# Execute user script in sub process with 'set +e'.
# This way if it is messed up, we dont get caught in an init loop.
chmod +x "${user_init_script:?}"
(
set +e
"${user_init_script:?}" || echo -e "\e[31mERROR: \e[33mFailed to execute user script '${user_init_script:?}'\e[0m"
)
# Execute user script in sub process.
# This way if it is messed up, we dont get caught in an init loop
chmod +x "${user_init_script}"
cat "${user_init_script}" | bash
fi
done
touch /tmp/.first-run-user-init-scripts
# Ensure all scripts are executable
chmod a+rwx /opt/scripts/*.sh
# Start supervisord
echo
echo "**** Starting supervisord ****";
echo "Logging all root services to '/var/log/supervisor/'"
echo "Logging all user services to '/home/${USER:?}/.cache/log/'"
echo "Logging all user services to '/home/${USER}/.cache/log/'"
echo
mkdir -p /var/log/supervisor
chmod a+rw /var/log/supervisor

View File

@@ -5,8 +5,8 @@
# File Created: Friday, 12th January 2022 8:54:01 am
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Monday, 10th July 2023 5:56:17 pm
# Modified By: Console and webGui login account (jsunnex@gmail.com)
# Last Modified: Tuesday, 4th October 2022 11:27:10 am
# Modified By: Josh.5 (jsunnex@gmail.com)
###
PUID=${PUID:-99}
@@ -21,14 +21,11 @@ usermod -o -u "${PUID}" ${USER}
groupmod -o -g "${PGID}" ${USER}
echo "Adding default user to video, audio, input and pulse groups"
usermod -a -G video,audio,input,pulse ${USER}
echo "Adding default user to any additional required device groups"
additional_groups=( video audio input pulse )
for group_name in "${additional_groups[@]}"; do
if [ $(getent group ${group_name:?}) ]; then
echo "Adding user '${USER}' to group: '${group_name}'"
usermod -aG ${group_name:?} ${USER}
fi
done
device_nodes=( /dev/uinput /dev/input/event* /dev/dri/* )
added_groups=""
for dev in "${device_nodes[@]}"; do
@@ -55,7 +52,7 @@ for dev in "${device_nodes[@]}"; do
# Add group to user
if [[ "${added_groups}" != *"${dev_group}"* ]]; then
echo "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
usermod -aG ${dev_group} ${USER}
usermod -a -G ${dev_group} ${USER}
added_groups=" ${added_groups} ${dev_group} "
fi
done
@@ -79,6 +76,13 @@ ln -sf /usr/share/backgrounds/steam.jpg /etc/alternatives/desktop-background
chmod a+r /etc/alternatives/desktop-background
# Setup home directory and permissions
echo "Adding default home directory template"
mkdir -p ${USER_HOME}
chown -R ${PUID}:${PGID} /etc/home_directory_template
rsync -aq --ignore-existing /etc/home_directory_template/ ${USER_HOME}/
# Setup services log path
echo "Setting ownership of all log files in '${USER_HOME}/.cache/log'"
mkdir -p "${USER_HOME}/.cache/log"
@@ -95,4 +99,4 @@ echo "${USER}:${USER_PASSWORD}" | chpasswd
mkdir -p /tmp/runtime-root
chown root:root /tmp/runtime-root
echo "DONE"
echo "DONE"

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env bash
###
# File: 11-setup_sysctl_values.sh
# Project: cont-init.d
# File Created: Friday, 1st September 2023 3:56:17 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Monday, 1st September 2023 3:56:17 pm
# Modified By: Console and webGui login account (jsunnex@gmail.com)
###
echo "**** Configure some system kernel parameters ****"
if [ "$(cat /proc/sys/vm/max_map_count)" -ge 524288 ]; then
if [ -w "/proc/sys/vm/max_map_count" ]; then
echo "Setting the maximum number of memory map areas a process can create to 524288"
echo 524288 > /proc/sys/vm/max_map_count
else
echo "WARNING: Unable to set max_map_count on unprivileged container"
fi
else
echo "NOTE: vm.max_map_count is already greater than '524288'"
fi
echo "DONE"

View File

@@ -0,0 +1,21 @@
echo "**** Configure SSH server ****"
if [[ "X${PORT_SSH:-}" != "X" ]]; then
# Generate new SSH host keys if they dont exist
if [[ ! -f /etc/ssh/ssh_host_rsa_key ]]; then
echo "**** Generating SSH keys ****";
/usr/bin/ssh-keygen -A
fi
mkdir -p /run/sshd
chmod 744 /run/sshd
echo "Set port to '${PORT_SSH}'"
sed -i "s|^# Port 22.*$|Port ${PORT_SSH}|" /etc/ssh/ssh_config
else
echo "Disable SSH server"
# Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/sshd.ini
fi
echo "DONE"

View File

@@ -1,32 +1,26 @@
# Configure dbus
echo "**** Configure container dbus ****";
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [[ "${HOST_DBUS}" == "true" ]]; then
echo "Container configured to use the host dbus";
# Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
else
echo "Container configured to run its own dbus";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
# Configure dbus to run as USER
sed -i "/ <user>/c\ <user>${USER}</user>" /usr/share/dbus-1/system.conf
# Remove old dbus session
rm -rf ${USER_HOME}/.dbus/session-bus/* 2> /dev/null
# Remove old dbus pids
mkdir -p /var/run/dbus
chown -R ${PUID}:${PGID} /var/run/dbus/
chmod -R 770 /var/run/dbus/
# Generate a dbus machine ID
dbus-uuidgen > /var/lib/dbus/machine-id
# Remove old lockfiles
find /var/run/dbus -name "pid" -exec rm -f {} \;
fi
else
echo "Dbus service not available when container is run in 'secondary' mode."
if [[ "${HOST_DBUS}" == "true" ]]; then
echo "Container configured to use the host dbus";
# Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
else
echo "Container configured to run its own dbus";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
# Configure dbus to run as USER
sed -i "/ <user>/c\ <user>${USER}</user>" /usr/share/dbus-1/system.conf
# Remove old dbus session
rm -rf ${USER_HOME}/.dbus/session-bus/* 2> /dev/null
# Remove old dbus pids
mkdir -p /var/run/dbus
chown -R ${PUID}:${PGID} /var/run/dbus/
chmod -R 770 /var/run/dbus/
# Generate a dbus machine ID
dbus-uuidgen > /var/lib/dbus/machine-id
# Remove old lockfiles
find /var/run/dbus -name "pid" -exec rm -f {} \;
fi
echo "DONE"

View File

@@ -23,31 +23,17 @@ rm -rf "${tmp_mount}"
if [[ "${is_privileged}" == "true" ]]; then
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
if [ ! -w /sys ]; then
# Disable supervisord script since we are not able to write to sysfs
echo "**** Disable udev - /sys is mounted RO ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
elif [ ! -w /run/udev ]; then
# Disable supervisord script since we are not able to write to udev/data path
echo "**** Disable udev - /run/udev is mounted RO ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
elif udevadm trigger &> /dev/null; then
echo "**** Configure container to run udev management ****";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Configure udev permissions
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
fi
else
# Disable supervisord script since we are not able to execute "udevadm trigger"
echo "**** Disable udev service due to privilege restrictions ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
echo "**** Configure container to run udev management ****";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Make startup script executable
chmod +x /usr/bin/start-udev.sh
# Configure udev permissions
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
fi
else
# Disable supervisord script
echo "**** Disable udev service ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
fi

View File

@@ -1,10 +1,6 @@
echo "**** Configure pulseaudio ****"
# Always enable the pulseaudio service
echo "Enable pulseaudio service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/pulseaudio.ini
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
echo "Configure pulseaudio as simple dummy audio"
sed -i 's|^; autospawn.*$|autospawn = no|' /etc/pulse/client.conf

View File

@@ -1,19 +1,19 @@
# Fech NVIDIA GPU device (if one exists)
if [ "${NVIDIA_VISIBLE_DEVICES:-}" = "all" ]; then
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
elif [ "${NVIDIA_VISIBLE_DEVICES:-}X" = "X" ]; then
elif [ -z "${NVIDIA_VISIBLE_DEVICES:-}" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
else
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
if [ "${gpu_select:-}X" = "X" ]; then
if [ -z "$gpu_select" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p)
fi
fi
# NVIDIA Params
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select:?}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)"
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select:?}" 2> /dev/null | sed -n 2p)
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)"
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select}" 2> /dev/null | sed -n 2p)
export nvidia_host_driver_version="$(nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
# Intel params
@@ -27,129 +27,65 @@ export amd_cpu_model="$(lscpu | grep 'Model name:' | grep -i amd | cut -d':' -f2
export amd_gpu_model="$(lspci | grep -i vga | grep -i amd)"
function download_driver {
mkdir -p "${USER_HOME:?}/Downloads"
chown -R ${USER:?} "${USER_HOME:?}/Downloads"
mkdir -p ${USER_HOME}/Downloads
chown -R ${USER} ${USER_HOME}/Downloads
if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then
echo "Downloading driver v${nvidia_host_driver_version:?}"
if [[ ! -f "${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run" ]]; then
echo "Downloading driver v${nvidia_host_driver_version}"
wget -q --show-progress --progress=bar:force:noscroll \
-O /tmp/NVIDIA.run \
"http://download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version:?}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version:?}.run"
http://download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version}.run
[[ $? -gt 0 ]] && echo "Error downloading driver. Exit!" && return 1
mv /tmp/NVIDIA.run "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
mv /tmp/NVIDIA.run ${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run
fi
}
function install_nvidia_driver {
# Check here if the currently installed version matches using nvidia-settings
nvidia_settings_version=$(nvidia-settings --version 2> /dev/null | grep version | cut -d ' ' -f 4)
if [ "${nvidia_settings_version:-}X" != "${nvidia_host_driver_version:-}X" ]; then
# Download the driver (if it does not yet exist locally)
download_driver
[[ "${nvidia_settings_version}x" == "${nvidia_host_driver_version}x" ]] && return 0;
# if command -v pacman &> /dev/null; then
# echo "Install NVIDIA vulkan utils" \
# && pacman -Syu --noconfirm --needed \
# lib32-nvidia-utils \
# lib32-vulkan-icd-loader
# nvidia-utils \
# vulkan-icd-loader \
# && echo
# fi
if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) > 500)); then
echo "Installing NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
--silent \
--accept-license \
--skip-depmod \
--skip-module-unload \
--no-kernel-modules \
--no-kernel-module-source \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-systemd \
--no-distro-scripts \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs \
--no-libglx-indirect \
--no-install-libglvnd \
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
else
echo "Installing Legacy NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
--silent \
--accept-license \
--skip-depmod \
--skip-module-unload \
--no-kernel-module \
--no-kernel-module-source \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-systemd \
--no-distro-scripts \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs \
--no-libglx-indirect \
--no-install-libglvnd \
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
fi
fi
}
# Download the driver (if it does not yet exist locally)
download_driver
function patch_nvidia_driver {
# REF: https://github.com/keylase/nvidia-patch#docker-support
if [ "${NVIDIA_PATCH_VERSION:-}X" != "X" ]; then
# Don't fail boot if something goes wrong here. Set +e
(
set +e
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
echo "Fetch NVIDIA NVENC patch"
wget -q --show-progress --progress=bar:force:noscroll \
-O "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch.sh"
fi
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
echo "Fetch NVIDIA NvFBC patch"
wget -q --show-progress --progress=bar:force:noscroll \
-O "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" \
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch-fbc.sh"
fi
chmod +x \
"${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
"${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
# if command -v pacman &> /dev/null; then
# echo "Install NVIDIA vulkan utils" \
# && pacman -Syu --noconfirm --needed \
# lib32-nvidia-utils \
# lib32-vulkan-icd-loader
# nvidia-utils \
# vulkan-icd-loader \
# && echo
# fi
echo "Install NVIDIA driver patches"
echo "/patched-lib" > /etc/ld.so.conf.d/000-patched-lib.conf
mkdir -p "/patched-lib"
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh"
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
pushd "/patched-lib" &> /dev/null || { echo "Error: Failed to push directory to /patched-lib"; exit 1; }
for f in * ; do
suffix="${f##*.so}"
name="$(basename "$f" "$suffix")"
[ -h "$name" ] || ln -sf "$f" "$name"
[ -h "$name" ] || ln -sf "$f" "$name.1"
done
ldconfig
popd &> /dev/null || { echo "Error: Failed to pop directory out of /patched-lib"; exit 1; }
)
else
echo "Leaving NVIDIA driver stock without patching"
fi
echo "Installing NVIDIA driver v${nvidia_host_driver_version} to match what is running on the host"
chmod +x ${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run
${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run \
--silent \
--accept-license \
--skip-depmod \
--skip-module-unload \
--no-kernel-modules \
--no-kernel-module-source \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-systemd \
--no-distro-scripts \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs \
--no-libglx-indirect \
--no-install-libglvnd \
> ${USER_HOME}/Downloads/nvidia_gpu_install.log 2>&1
}
function install_amd_gpu_driver {
echo "Install AMD vulkan driver"
if command -v pacman &> /dev/null; then
pacman -Syu --noconfirm --needed \
lib32-mesa \
lib32-vulkan-icd-loader \
lib32-vulkan-radeon \
vulkan-icd-loader \
@@ -169,6 +105,7 @@ function install_intel_gpu_driver {
echo "Install Intel vulkan driver"
if command -v pacman &> /dev/null; then
pacman -Syu --noconfirm --needed \
lib32-mesa \
lib32-vulkan-icd-loader \
lib32-vulkan-intel \
vulkan-icd-loader \
@@ -184,30 +121,29 @@ function install_intel_gpu_driver {
fi
}
# NVIDIA GPU
if [[ ! -z ${nvidia_pci_address} ]]; then
echo "**** Found NVIDIA device '${nvidia_gpu_name}' ****";
install_nvidia_driver
else
echo "**** No NVIDIA device found ****";
fi
# Intel Arc GPU or Intel CPU with possible iGPU
if [ "${intel_gpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_gpu_model:?}' ****"
if [[ ! -z ${intel_gpu_model} ]]; then
echo "**** Found Intel device '${intel_gpu_model}' ****";
install_intel_gpu_driver
elif [ "${intel_cpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_cpu_model:?}' ****"
elif [[ ! -z ${intel_cpu_model} ]]; then
echo "**** Found Intel device '${intel_cpu_model}' ****";
install_intel_gpu_driver
else
echo "**** No Intel device found ****"
echo "**** No Intel device found ****";
fi
# AMD GPU
if [ "${amd_gpu_model:-}X" != "X" ]; then
echo "**** Found AMD device '${amd_gpu_model:?}' ****"
if [[ ! -z ${amd_gpu_model} ]]; then
echo "**** Found AMD device '${amd_gpu_model}' ****";
install_amd_gpu_driver
else
echo "**** No AMD device found ****"
fi
# NVIDIA GPU
if [ "${nvidia_pci_address:-}X" != "X" ]; then
echo "**** Found NVIDIA device '${nvidia_gpu_name:?}' ****"
install_nvidia_driver
patch_nvidia_driver
else
echo "**** No NVIDIA device found ****"
echo "**** No AMD device found ****";
fi
echo "DONE"

View File

@@ -1,22 +0,0 @@
echo "**** Configure Desktop ****"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
echo "Enable Desktop service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/desktop.ini
else
echo "Desktop service not available when container is run in 'secondary' mode."
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/desktop.ini
fi
# Setup home directory
if [[ ! -f /tmp/.home-directory-template-updated ]]; then
echo "Ensure home directory template is owned by the default user."
chown -R ${PUID}:${PGID} /templates/home_directory_template
echo "Installing default home directory template"
mkdir -p "${USER_HOME:?}"
rsync -aq /templates/home_directory_template/ "${USER_HOME:?}"/
touch /tmp/.home-directory-template-updated
fi
echo "DONE"

View File

@@ -54,11 +54,7 @@ function configure_nvidia_x_server {
# Allow anybody for running x server
function configure_x_server {
# Configure x to be run by anyone
if [[ ! -f /etc/X11/Xwrapper.config ]]; then
echo "Create Xwrapper.config"
echo 'allowed_users=anybody' > /etc/X11/Xwrapper.config
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
elif grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
if grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
echo "Configure Xwrapper.config"
sed -i "s/allowed_users=console/allowed_users=anybody/" /etc/X11/Xwrapper.config
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
@@ -94,9 +90,6 @@ function configure_x_server {
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
# Enable xvfb supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xvfb.ini
else
echo "Configure container with no X server"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
fi
# Enable KB/Mouse input capture with Xorg if configured

View File

@@ -0,0 +1,24 @@
echo "**** Configure Dockerd ****"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ ! -S /var/run/docker.sock ]; then
echo "Enable Dockerd daemon"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dind.ini
else
echo "Docker socket has been passed in from host. Using that instead"
fi
# Configure 'default' user to run docker commands without sudo
if ! getent group docker &> /dev/null; then
echo "Add user '${USER}' to docker group for sudoless execution"
groupadd docker
usermod -aG docker ${USER}
mkdir -p ${USER_HOME:?}/.docker
chown -R ${PUID}:${PGID} ${USER_HOME:?}/.docker
chmod -R g+rwx ${USER_HOME:?}/.docker
fi
else
echo "Dockerd daemon not available when container is run in 'secondary' mode"
fi
echo "DONE"

View File

@@ -1,13 +0,0 @@
echo "**** Configure Flatpak ****"
if [ "X${NVIDIA_VISIBLE_DEVICES:-}" != "X" ]; then
# Fix some flatpak quirks (not sure what is happening here) for NVIDIA containers
mount -t proc none /proc
flatpak list
echo "Flatpak configured for running inside a Docker container"
else
echo "Flatpak already configured for running inside a Docker container"
fi
echo "DONE"

View File

@@ -1,35 +0,0 @@
echo "**** Configure Steam ****"
steam_autostart_desktop="$(cat <<EOF
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=Steam
Comment=Launch steam on login
Exec=/usr/games/steam %U ${STEAM_ARGS:-}
Icon=steam
OnlyShowIn=XFCE;
RunHook=0
StartupNotify=false
Terminal=false
Hidden=false
EOF
)"
if [ "${ENABLE_STEAM:-}" = "true" ]; then
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
echo "Enable Steam supervisor.d service"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini
else
echo "Enable Steam auto-start script"
mkdir -p "${USER_HOME:?}/.config/autostart"
echo "${steam_autostart_desktop:?}" > "${USER_HOME:?}/.config/autostart/Steam.desktop"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
fi
else
echo "Disable Steam service"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
fi
echo "DONE"

View File

@@ -15,22 +15,55 @@ function get_next_unused_port() {
# Note: Ports 32035-32248 are unallocated port ranges. We should be able to find something in here that we can use
# REF: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=130
DYNAMIC_PORT_VNC=$(get_next_unused_port 32035)
DYNAMIC_PORT_NOVNC_SERVICE=$(get_next_unused_port ${DYNAMIC_PORT_VNC})
DYNAMIC_PORT_AUDIO_WEBSOCKET=$(get_next_unused_port ${DYNAMIC_PORT_NOVNC_SERVICE})
DYNAMIC_PORT_AUDIO_STREAM=$(get_next_unused_port ${DYNAMIC_PORT_AUDIO_WEBSOCKET})
export PORT_VNC=${PORT_VNC:-$DYNAMIC_PORT_VNC}
echo "Configure VNC service port '${PORT_VNC}'"
DYNAMIC_PORT_AUDIO_STREAM=$(get_next_unused_port ${DYNAMIC_PORT_VNC})
export PORT_NOVNC_SERVICE=${PORT_NOVNC_SERVICE:-$DYNAMIC_PORT_NOVNC_SERVICE}
echo "Configure noVNC service port '${PORT_NOVNC_SERVICE}'"
export PORT_AUDIO_WEBSOCKET=${PORT_AUDIO_WEBSOCKET:-$DYNAMIC_PORT_AUDIO_WEBSOCKET}
echo "Configure audio websocket port '${PORT_AUDIO_WEBSOCKET}'"
export PORT_AUDIO_STREAM=${PORT_AUDIO_STREAM:-$DYNAMIC_PORT_AUDIO_STREAM}
echo "Configure pulseaudio encoded stream port '${PORT_AUDIO_STREAM}'"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ "${WEB_UI_MODE:-}" = "vnc" ]; then
if [ ${WEB_UI_MODE} = "vnc" ]; then
echo "Enable VNC server"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc.ini
# Configure Nginx proxy for the websocket and VNC
cp -f /opt/noVNC/nginx.template.conf /opt/noVNC/nginx.conf
sed -i "s|<USER>|${USER}|" /opt/noVNC/nginx.conf
sed -i "s|<PORT_NOVNC_WEB>|${PORT_NOVNC_WEB}|" /opt/noVNC/nginx.conf
sed -i "s|<PORT_NOVNC_SERVICE>|${PORT_NOVNC_SERVICE}|" /opt/noVNC/nginx.conf
sed -i "s|<PORT_AUDIO_WEBSOCKET>|${PORT_AUDIO_WEBSOCKET}|" /opt/noVNC/nginx.conf
mkdir -p /var/log/vncproxy
chown -R ${USER} /var/log/vncproxy
# TODO: Remove this... Always enable VNC audio
if [[ "${ENABLE_VNC_AUDIO}" == "true" ]]; then
# Credits for this audio patch:
# - https://github.com/novnc/noVNC/issues/302
# - https://github.com/vexingcodes/dwarf-fortress-docker
# - https://github.com/calebj/noVNC
if [ -f /opt/noVNC/audio.patch ]; then
echo "Patching noVNC with audio websocket"
# Update port specification in patch file
sed -i "s|<PORT_AUDIO_WEBSOCKET>|${PORT_AUDIO_WEBSOCKET}|" /opt/noVNC/audio.patch
# Apply patch
pushd /opt/noVNC/ &> /dev/null
patch -p1 --input=/opt/noVNC/audio.patch --batch --quiet
popd &> /dev/null
rm /opt/noVNC/audio.patch
fi
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc-audio.ini
# Remove x11vnc from applications menu
if ! grep -q 'Hidden=true' /usr/share/applications/x11vnc.desktop; then
echo 'Hidden=true' >> /usr/share/applications/x11vnc.desktop
fi
else
echo "Disable audio stream"
echo "Disable audio websock"
@@ -39,13 +72,9 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
fi
else
echo "Disable VNC server"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
fi
else
echo "VNC server not available when container is run in 'secondary' mode"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
fi
echo "DONE"

View File

@@ -0,0 +1,37 @@
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
echo "Configure container as secondary"
# Disable dbus
echo " - Disable dbus"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
# Disable desktop
echo " - Disable desktop"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/desktop.ini
# Disable sshd
echo " - Disable sshd"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/sshd.ini
# Disable vnc
echo " - Disable vnc"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
# Disable vnc
echo " - Disable vnc"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
# Disable vnc-audio
echo " - Disable vnc audio stream"
echo " - Disable vnc audio websock"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
# Disable xorg
echo " - Disable xorg"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
# Enable pulseaudio
echo " - Enable pulseaudio"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/pulseaudio.ini
# Enable steam
echo " - Enable steam"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini
# Enable udev
echo " - Enable udev"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
fi
echo "DONE"

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env bash
###
# File: 10-setup_user.sh
# Project: cont-init.d
# File Created: Tuesday, 5th September 2023 6:15:12 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 5th September 2023 6:39:32 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
echo "**** Configure WoL Manager ****"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ "${ENABLE_WOL_POWER_MANAGER:-}" = "true" ]; then
if [ -f "/tmp/.wol-monitor" ]; then
echo "Container started in WoL Manager mode. Disabling all other services."
for init_config in /etc/supervisor.d/*.ini ; do
init_config_basename=$(basename "${init_config:?}")
init_name="${init_config_basename%.*}"
[ "${init_name:?}" = "wol-power-manager" ] && continue
echo " - Disable ${init_name:?}"
sed -i 's|^autostart.*=.*$|autostart=false|' "${init_config:?}"
done
fi
echo "Enable WoL Manager service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/wol-power-manager.ini
else
echo "Disable WoL Manager service."
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/wol-power-manager.ini
fi
else
echo "WoL Manager service not available when container is run in 'secondary' mode."
fi

View File

@@ -0,0 +1,13 @@
[Desktop Entry]
Encoding=UTF-8
Version=0.9.4
Type=Application
Name=Steam
Comment=launch steam on login
Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=/app/bin/steam-wrapper --file-forwarding com.valvesoftware.Steam @@u %U @@ -silent
Icon=steam
OnlyShowIn=XFCE;
RunHook=0
StartupNotify=false
Terminal=false
Hidden=false

View File

@@ -47,25 +47,4 @@
</property>
</property>
</property>
<property name="desktop-icons" type="empty">
<property name="style" type="int" value="0"/>
<property name="icon-size" type="uint" value="48"/>
<property name="show-tooltips" type="bool" value="true"/>
<property name="show-thumbnails" type="bool" value="true"/>
</property>
<property name="last" type="empty">
<property name="window-width" type="int" value="653"/>
<property name="window-height" type="int" value="558"/>
</property>
<property name="windowlist-menu" type="empty">
<property name="show-icons" type="bool" value="true"/>
<property name="show-add-remove-workspaces" type="bool" value="false"/>
<property name="show-workspace-names" type="bool" value="false"/>
<property name="show" type="bool" value="true"/>
</property>
<property name="desktop-menu" type="empty">
<property name="show-delete" type="bool" value="false"/>
<property name="show-icons" type="bool" value="true"/>
<property name="show" type="bool" value="true"/>
</property>
</channel>

View File

@@ -7,14 +7,15 @@
<property name="dark-mode" type="bool" value="true"/>
<property name="panel-1" type="empty">
<property name="position" type="string" value="p=6;x=0;y=0"/>
<property name="length" type="double" value="100"/>
<property name="length" type="uint" value="100"/>
<property name="position-locked" type="bool" value="true"/>
<property name="icon-size" type="uint" value="36"/>
<property name="size" type="uint" value="40"/>
<property name="icon-size" type="uint" value="16"/>
<property name="size" type="uint" value="26"/>
<property name="plugin-ids" type="array">
<value type="int" value="1"/>
<value type="int" value="2"/>
<value type="int" value="3"/>
<value type="int" value="4"/>
<value type="int" value="5"/>
<value type="int" value="6"/>
<value type="int" value="8"/>
@@ -22,17 +23,13 @@
<value type="int" value="11"/>
<value type="int" value="12"/>
<value type="int" value="13"/>
<value type="int" value="14"/>
</property>
<property name="background-style" type="uint" value="0"/>
<property name="mode" type="uint" value="0"/>
<property name="autohide-behavior" type="uint" value="0"/>
<property name="nrows" type="uint" value="1"/>
</property>
</property>
<property name="plugins" type="empty">
<property name="plugin-1" type="string" value="applicationsmenu">
<property name="button-icon" type="string" value="steam-headless"/>
</property>
<property name="plugin-1" type="string" value="applicationsmenu"/>
<property name="plugin-2" type="string" value="tasklist">
<property name="grouping" type="uint" value="1"/>
</property>
@@ -40,6 +37,7 @@
<property name="expand" type="bool" value="true"/>
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-4" type="string" value="pager"/>
<property name="plugin-5" type="string" value="separator">
<property name="style" type="uint" value="0"/>
</property>
@@ -55,11 +53,10 @@
<property name="plugin-11" type="string" value="separator">
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-12" type="string" value="clock">
<property name="mode" type="uint" value="2"/>
</property>
<property name="plugin-12" type="string" value="clock"/>
<property name="plugin-13" type="string" value="separator">
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-14" type="string" value="actions"/>
</property>
</channel>
</channel>

View File

@@ -14,7 +14,7 @@
<property name="EnableInputFeedbackSounds" type="empty"/>
</property>
<property name="Xft" type="empty">
<property name="DPI" type="int" value="110"/>
<property name="DPI" type="empty"/>
<property name="Antialias" type="empty"/>
<property name="Hinting" type="empty"/>
<property name="HintStyle" type="empty"/>
@@ -32,7 +32,7 @@
<property name="MenuImages" type="empty"/>
<property name="ButtonImages" type="empty"/>
<property name="MenuBarAccel" type="empty"/>
<property name="CursorThemeName" type="string" value="default"/>
<property name="CursorThemeName" type="empty"/>
<property name="CursorThemeSize" type="empty"/>
<property name="DecorationLayout" type="empty"/>
<property name="DialogsUseHeader" type="empty"/>
@@ -41,8 +41,4 @@
<property name="Gdk" type="empty">
<property name="WindowScalingFactor" type="empty"/>
</property>
<property name="Xfce" type="empty">
<property name="LastCustomDPI" type="int" value="110"/>
<property name="SyncThemes" type="bool" value="true"/>
</property>
</channel>
</channel>

View File

@@ -0,0 +1,14 @@
[program:dind]
priority=20
autostart=false
autorestart=true
user=root
command=/usr/bin/start-dind.sh
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/dind.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/dind.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7

View File

@@ -0,0 +1,14 @@
[program:sshd]
priority=10
autostart=true
autorestart=true
user=root
command=/usr/sbin/sshd -Ddp "%(ENV_PORT_SSH)s"
stopsignal=INT
stdout_logfile=/var/log/supervisor/sshd.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=7
stderr_logfile=/var/log/supervisor/sshd.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7

View File

@@ -10,7 +10,8 @@ autorestart=true
startretries=50
user=%(ENV_USER)s
directory=/home/%(ENV_USER)s
command=/usr/games/steam %(ENV_STEAM_ARGS)s
# command=/usr/games/steam -bigpicture
command=/usr/games/steam
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/steam.log

View File

@@ -12,3 +12,17 @@ stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/audiostream.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7
[program:audiowebsock]
priority=40
autostart=false
autorestart=true
user=%(ENV_USER)s
command=/usr/local/bin/websockify %(ENV_PORT_AUDIO_WEBSOCKET)s localhost:%(ENV_PORT_AUDIO_STREAM)s
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/audiowebsock.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/audiowebsock.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7

View File

@@ -3,7 +3,7 @@
priority=30
autostart=false
autorestart=true
user=root
user=%(ENV_USER)s
command=/usr/bin/start-x11vnc.sh
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s",PORT_VNC="%(ENV_PORT_VNC)s"
stopsignal=INT
@@ -14,12 +14,12 @@ stderr_logfile=/home/%(ENV_USER)s/.cache/log/x11vnc.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7
[program:frontend]
[program:novnc]
priority=30
autostart=false
autorestart=true
user=root
command=/opt/frontend/utils/run.sh --web-port %(ENV_PORT_NOVNC_WEB)s --remote-host localhost --vnc-port %(ENV_PORT_VNC)s --audio-port %(ENV_PORT_AUDIO_STREAM)s
user=%(ENV_USER)s
command=/opt/noVNC/utils/launch.sh --vnc localhost:%(ENV_PORT_VNC)s --listen %(ENV_PORT_NOVNC_SERVICE)s
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/novnc.log
@@ -28,3 +28,37 @@ stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/novnc.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7
[program:vncproxy]
priority=30
autostart=false
autorestart=true
numprocs=1
startsecs=0
user=%(ENV_USER)s
command=/usr/sbin/nginx -c /opt/noVNC/nginx.conf
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/vncproxy.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/vncproxy.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7
# [program:kasmxproxy]
# priority=30
# autostart=false
# autorestart=true
# numprocs=1
# startsecs=0
# user=%(ENV_USER)s
# command=/usr/sbin/nginx -c /opt/noVNC/nginx.conf
# environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
# stopsignal=INT
# stdout_logfile=/home/%(ENV_USER)s/.cache/log/vncproxy.log
# stdout_logfile_maxbytes=10MB
# stdout_logfile_backups=7
# stderr_logfile=/home/%(ENV_USER)s/.cache/log/vncproxy.err.log
# stderr_logfile_maxbytes=10MB
# stderr_logfile_backups=7

View File

@@ -1,15 +0,0 @@
[program:wol-power-manager]
priority=60
autostart=false
autorestart=true
user=root
command=/usr/bin/steam-headless-wol-power-manager
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s"
stopsignal=INT
stdout_logfile=/home/%(ENV_USER)s/.cache/log/wol-power-manager.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=7
stderr_logfile=/home/%(ENV_USER)s/.cache/log/wol-power-manager.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=7

View File

@@ -0,0 +1,40 @@
daemon off;
worker_processes auto;
pid /tmp/vncproxy.pid;
error_log /home/<USER>/.cache/log/vncproxy.err.log;
events {
}
http {
server {
listen <PORT_NOVNC_WEB> default_server;
access_log /home/<USER>/.cache/log/vncproxy.log;
client_body_temp_path /tmp/client_body;
fastcgi_temp_path /tmp/fastcgi_temp;
proxy_temp_path /tmp/proxy_temp;
scgi_temp_path /tmp/scgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
location / {
proxy_pass http://127.0.0.1:<PORT_NOVNC_SERVICE>/;
}
location /websockify {
proxy_pass http://127.0.0.1:<PORT_NOVNC_SERVICE>/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location /audiowebsock {
proxy_pass http://127.0.0.1:<PORT_AUDIO_WEBSOCKET>/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
}

View File

@@ -4,7 +4,7 @@ echo "**** Installing/upgrading Firefox via flatpak ****"
# Install Firefox
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --user install --assumeyes --or-update flathub org.mozilla.firefox
flatpak --user install --assumeyes --noninteractive --or-update flathub org.mozilla.firefox
# Configure Firefox as the default browser
echo "Configure Firefox..."
@@ -22,9 +22,9 @@ Name=org.mozilla.firefox
X-XFCE-Commands=${USER_HOME:?}/.local/share/flatpak/exports/bin/org.mozilla.firefox
EOF
)"
if [[ ! -f "${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop" ]]; then
mkdir -p "${USER_HOME:?}/.local/share/xfce4/helpers"
echo "${custom_webbrowser}" > "${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop"
if [[ ! -f ${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop ]]; then
mkdir -p ${USER_HOME:?}/.local/share/xfce4/helpers
echo "${custom_webbrowser}" > ${USER_HOME:?}/.local/share/xfce4/helpers/custom-WebBrowser.desktop
gio mime x-scheme-handler/http org.mozilla.firefox.desktop
fi

View File

@@ -4,9 +4,9 @@ echo "**** Installing/upgrading ProtonUp-Qt via flatpak ****"
# Install ProtonUp-Qt
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --user install --assumeyes --or-update net.davidotek.pupgui2
flatpak --user install --assumeyes --noninteractive --or-update net.davidotek.pupgui2
# Configure ProtonUp-Qt
# Configure Firefox as the default browser
echo "Configure ProtonUp-Qt..."
sed -i 's/^Categories=.*$/Categories=Utility;/' \
${USER_HOME}/.local/share/flatpak/exports/share/applications/net.davidotek.pupgui2.desktop

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
echo "**** Installing/upgrading Steam via flatpak ****"
# Install Steam client
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --user install --assumeyes --noninteractive --or-update flathub com.valvesoftware.Steam
# Configure any required overrides
flatpak --user override --filesystem=/mnt/games com.valvesoftware.Steam
# TODO: Check if we should add /dev/dri here??
# Configure default steam library paths
echo "Configure Steam default libraries..."
mkdir -p /mnt/games/GameLibrary/SteamLibrary
libraryfolders="$(cat <<EOF
"libraryfolders"
{
"0"
{
"path" "${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam"
"label" ""
"contentid" "5619710282499379610"
"totalsize" "0"
"update_clean_bytes_tally" "0"
"time_last_update_corruption" "0"
"apps"
{
}
}
"1"
{
"path" "/mnt/games/GameLibrary/SteamLibrary"
"label" "Mounted Games"
"contentid" "4437054932394438372"
"totalsize" "0"
"update_clean_bytes_tally" "0"
"time_last_update_corruption" "0"
"apps"
{
}
}
}
EOF
)"
if [[ ! -f ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/libraryfolders.vdf ]]; then
mkdir -p ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps
echo "${libraryfolders}" > ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/libraryfolders.vdf
fi
if [[ ! -f ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf ]]; then
mkdir -p ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/config
echo "${libraryfolders}" > ${USER_HOME:?}/.var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf
fi
echo "DONE"

View File

@@ -1,7 +0,0 @@
[Default Applications]
x-scheme-handler/http=xfce4-web-browser.desktop
x-scheme-handler/https=xfce4-web-browser.desktop
[Added Associations]
x-scheme-handler/http=xfce4-web-browser.desktop;
x-scheme-handler/https=xfce4-web-browser.desktop;

View File

@@ -1 +0,0 @@
WebBrowser=custom-WebBrowser

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfwm4" version="1.0">
<property name="general" type="empty">
<property name="activate_action" type="string" value="bring"/>
<property name="borderless_maximize" type="bool" value="true"/>
<property name="box_move" type="bool" value="false"/>
<property name="box_resize" type="bool" value="false"/>
<property name="button_layout" type="string" value="O|SHMC"/>
<property name="button_offset" type="int" value="0"/>
<property name="button_spacing" type="int" value="0"/>
<property name="click_to_focus" type="bool" value="true"/>
<property name="cycle_apps_only" type="bool" value="false"/>
<property name="cycle_draw_frame" type="bool" value="true"/>
<property name="cycle_raise" type="bool" value="false"/>
<property name="cycle_hidden" type="bool" value="true"/>
<property name="cycle_minimum" type="bool" value="true"/>
<property name="cycle_minimized" type="bool" value="false"/>
<property name="cycle_preview" type="bool" value="true"/>
<property name="cycle_tabwin_mode" type="int" value="0"/>
<property name="cycle_workspaces" type="bool" value="false"/>
<property name="double_click_action" type="string" value="maximize"/>
<property name="double_click_distance" type="int" value="5"/>
<property name="double_click_time" type="int" value="250"/>
<property name="easy_click" type="string" value="Alt"/>
<property name="focus_delay" type="int" value="250"/>
<property name="focus_hint" type="bool" value="true"/>
<property name="focus_new" type="bool" value="true"/>
<property name="frame_opacity" type="int" value="100"/>
<property name="frame_border_top" type="int" value="0"/>
<property name="full_width_title" type="bool" value="true"/>
<property name="horiz_scroll_opacity" type="bool" value="false"/>
<property name="inactive_opacity" type="int" value="100"/>
<property name="maximized_offset" type="int" value="0"/>
<property name="mousewheel_rollup" type="bool" value="true"/>
<property name="move_opacity" type="int" value="100"/>
<property name="placement_mode" type="string" value="center"/>
<property name="placement_ratio" type="int" value="20"/>
<property name="popup_opacity" type="int" value="100"/>
<property name="prevent_focus_stealing" type="bool" value="false"/>
<property name="raise_delay" type="int" value="250"/>
<property name="raise_on_click" type="bool" value="true"/>
<property name="raise_on_focus" type="bool" value="false"/>
<property name="raise_with_any_button" type="bool" value="true"/>
<property name="repeat_urgent_blink" type="bool" value="false"/>
<property name="resize_opacity" type="int" value="100"/>
<property name="scroll_workspaces" type="bool" value="false"/>
<property name="shadow_delta_height" type="int" value="0"/>
<property name="shadow_delta_width" type="int" value="0"/>
<property name="shadow_delta_x" type="int" value="0"/>
<property name="shadow_delta_y" type="int" value="-3"/>
<property name="shadow_opacity" type="int" value="50"/>
<property name="show_app_icon" type="bool" value="false"/>
<property name="show_dock_shadow" type="bool" value="true"/>
<property name="show_frame_shadow" type="bool" value="true"/>
<property name="show_popup_shadow" type="bool" value="false"/>
<property name="snap_resist" type="bool" value="false"/>
<property name="snap_to_border" type="bool" value="true"/>
<property name="snap_to_windows" type="bool" value="false"/>
<property name="snap_width" type="int" value="10"/>
<property name="vblank_mode" type="string" value="auto"/>
<property name="theme" type="string" value="Default-xhdpi"/>
<property name="tile_on_move" type="bool" value="true"/>
<property name="title_alignment" type="string" value="center"/>
<property name="title_font" type="string" value="Sans Bold 9"/>
<property name="title_horizontal_offset" type="int" value="0"/>
<property name="titleless_maximize" type="bool" value="false"/>
<property name="title_shadow_active" type="string" value="false"/>
<property name="title_shadow_inactive" type="string" value="false"/>
<property name="title_vertical_offset_active" type="int" value="0"/>
<property name="title_vertical_offset_inactive" type="int" value="0"/>
<property name="toggle_workspaces" type="bool" value="false"/>
<property name="unredirect_overlays" type="bool" value="true"/>
<property name="urgent_blink" type="bool" value="false"/>
<property name="use_compositing" type="bool" value="true"/>
<property name="workspace_count" type="int" value="1"/>
<property name="wrap_cycle" type="bool" value="false"/>
<property name="wrap_layout" type="bool" value="false"/>
<property name="wrap_resistance" type="int" value="10"/>
<property name="wrap_windows" type="bool" value="false"/>
<property name="wrap_workspaces" type="bool" value="false"/>
<property name="zoom_desktop" type="bool" value="true"/>
<property name="zoom_pointer" type="bool" value="true"/>
<property name="workspace_names" type="array">
<value type="string" value="Workspace 1"/>
<value type="string" value="Workspace 2"/>
<value type="string" value="Workspace 3"/>
<value type="string" value="Workspace 4"/>
</property>
<property name="margin_top" type="int" value="0"/>
</property>
</channel>

View File

@@ -1,11 +0,0 @@
"libraryfolders"
[Desktop Entry]
NoDisplay=true
Version=1.0
Encoding=UTF-8
Type=X-XFCE-Helper
X-XFCE-Category=WebBrowser
X-XFCE-CommandsWithParameter=/home/default/.local/share/flatpak/exports/bin/org.mozilla.firefox "%s"
Icon=org.mozilla.firefox
Name=org.mozilla.firefox
X-XFCE-Commands=/home/default/.local/share/flatpak/exports/bin/org.mozilla.firefox

View File

@@ -4,30 +4,11 @@
},
"apps": [
{
"name": "Desktop",
"image-path": "desktop.png",
"exclude-global-prep-cmd": "true"
},
{
"name": "Steam Big Picture",
"image-path": "steam.png",
"exclude-global-prep-cmd": "true",
"name": "Steam BigPicture",
"output": "steam.txt",
"cmd": "",
"detached": [
"\/usr\/bin\/sunshine-run \/usr\/games\/steam steam:\/\/open\/bigpicture"
],
"prep-cmd": [
{
"do": "",
"undo": "sh -c \"sleep 7 && pkill -f -2 \/usr\/bin\/sunshine\""
},
{
"do": "",
"undo": "\/usr\/bin\/sunshine-stop"
},
{
"do": "",
"undo": "\/usr\/bin\/xfce4-close-all-windows"
}
"\/usr\/games\/steam steam:\/\/open\/bigpicture"
]
}
]

View File

@@ -28,10 +28,6 @@
#
min_log_level = info
# A list of commands to be run before/after all applications.
# If any of the prep-commands fail, starting the application is aborted.
global_prep_cmd = [{"do":"/usr/bin/xfce4-minimise-all-windows","undo":"/usr/bin/sunshine-stop"}]
# The origin of the remote endpoint address that is not denied for HTTP method /pin
# Could be any of the following values:
# pc|lan|wan
@@ -99,7 +95,7 @@ global_prep_cmd = [{"do":"/usr/bin/xfce4-minimise-all-windows","undo":"/usr/bin/
# ping_timeout = 10000
# The file where configuration for the different applications that Sunshine can run during a stream
file_apps = apps.json
file_apps = /home/default/sunshine/apps.json
# Percentage of error correcting packets per data packet in each video frame
# Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage
@@ -115,7 +111,7 @@ file_apps = apps.json
#
# Unlike simply broadcasting to multiple Client, this will generate distinct video streams.
# Note, CPU usage increases for each distinct video stream generated
channels = 2
# channels = 1
# The back/select button on the controller
# On the Shield, the home and powerbutton are not passed to Moonlight

View File

@@ -1,14 +1,12 @@
Section "Device"
Identifier "Configured Video Device"
Driver "dummy"
VideoRam 256000
EndSection
Section "Monitor"
Identifier "Configured Monitor"
HorizSync 5.0 - 1000.0
VertRefresh 5.0 - 200.0
ModeLine "1920x1080" 148.50 1920 2448 2492 2640 1080 1084 1089 1125 +Hsync +Vsync
HorizSync 31.5-48.5
VertRefresh 50-70
EndSection
Section "Screen"
@@ -18,6 +16,6 @@ Section "Screen"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1920x1080" "1280x800" "1024x768" "1920x1080" "1600x900" "1440x900"
Modes "1600x900"
EndSubSection
EndSection

View File

@@ -28,7 +28,7 @@ wait_for_x() {
wait_for_udev() {
MAX=10
CT=0
while [ ! -f /tmp/.started-udev ]; do
while [ ! -f /tmp/.udev-started ]; do
sleep 1
CT=$(( CT + 1 ))
if [ "$CT" -ge "$MAX" ]; then
@@ -53,20 +53,6 @@ wait_for_docker() {
echo "DOCKERD RUNNING!"
}
# Wait for desktop to start
wait_for_desktop() {
MAX=30
CT=0
while [ ! -f /tmp/.started-desktop ]; do
sleep 1
CT=$(( CT + 1 ))
if [ "$CT" -ge "$MAX" ]; then
echo "FATAL: $0: Gave up waiting for Desktop to start"
exit 11
fi
done
}
# Fech NVIDIA GPU device (if one exists)
get_nvidia_gpu_id() {
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then
@@ -81,24 +67,3 @@ get_nvidia_gpu_id() {
fi
echo ${gpu_select}
}
export_desktop_dbus_session() {
if [ ! -f /tmp/.dbus-desktop-session.env ]; then
echo "$(dbus-launch)" > /tmp/.dbus-desktop-session.env
fi
export $(cat /tmp/.dbus-desktop-session.env)
}
# Wait for desktop dbus session to start
wait_for_desktop_dbus_session() {
MAX=10
CT=0
while [ ! -f /tmp/.dbus-desktop-session.env ]; do
sleep 1
CT=$(( CT + 1 ))
if [ "$CT" -ge "$MAX" ]; then
echo "FATAL: $0: Gave up waiting for Desktop dbus-launch session to be created"
exit 11
fi
done
}

View File

@@ -1,14 +0,0 @@
#!/usr/bin/env bash
echo "**** Installing/upgrading Flatseal via flatpak ****"
# Install Flatseal
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --user install --assumeyes --or-update com.github.tchx84.Flatseal
# Configure Flatseal
echo "Configure Flatseal..."
sed -i 's/^Categories=.*$/Categories=Utility;/' \
${USER_HOME}/.local/share/flatpak/exports/share/applications/com.github.tchx84.Flatseal.desktop
echo "DONE"

View File

@@ -5,7 +5,7 @@
# File Created: Thursday, 1st January 1970 12:00:00 pm
# Author: Console and webGui login account (jsunnex@gmail.com)
# -----
# Last Modified: Saturday, 8th July 2023 6:16:47 pm
# Last Modified: Saturday, 8th July 2023 2:34:11 am
# Modified By: Console and webGui login account (jsunnex@gmail.com)
###
set -e
@@ -19,35 +19,24 @@ trap _term SIGTERM SIGINT
# CONFIGURE:
# Remove lockfile
rm -f /tmp/.started-desktop
# Start a session bus instance of dbus-daemon
# Note: This script should be the only one that waits for X after exporting this dbus session
rm -fv /tmp/.dbus-desktop-session.env
export_desktop_dbus_session
# Configure some XDG environment variables
export XDG_CACHE_HOME="${USER_HOME:?}/.cache"
export XDG_CONFIG_HOME="${USER_HOME:?}/.config"
export XDG_DATA_HOME="${USER_HOME:?}/.local/share"
export $(dbus-launch)
# EXECUTE PROCESS:
# Install/Upgrade user apps
if [[ ! -f /tmp/.desktop-apps-updated.lock ]]; then
source /opt/scripts/install_steam.sh
source /opt/scripts/install_firefox.sh
source /opt/scripts/install_protonup.sh
touch /tmp/.desktop-apps-updated.lock
fi
# Wait for the X server to start
wait_for_x
# Install/Upgrade user apps
if [[ ! -f /tmp/.desktop-apps-updated ]]; then
xterm -geometry 200x50+0+0 -ls -e /bin/bash -c "
source /usr/bin/install_firefox.sh;
source /usr/bin/install_protonup.sh;
sleep 1;
"
touch /tmp/.desktop-apps-updated
fi
# Run the desktop environment
echo "**** Starting Xfce4 ****"
/usr/bin/startxfce4 &
desktop_pid=$!
touch /tmp/.started-desktop
# WAIT FOR CHILD PROCESS:
wait "$desktop_pid"

52
overlay/usr/bin/start-dind.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
###
# File: start-dind.sh
# Project: bin
# File Created: Saturday, 8th October 2022 1:49:45 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Saturday, 8th October 2022 1:49:45 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
# CATCH TERM SIGNAL:
_term() {
kill -TERM "$docker_pid" 2>/dev/null
}
trap _term SIGTERM SIGINT
# CONFIGURE:
# Refrences:
# - https://raw.githubusercontent.com/docker/docker/42b1175eda071c0e9121e1d64345928384a93df1/hack/dind
#
# apparmor sucks and Docker needs to know that it's in a container (c) @tianon
export container=docker
if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security; then
mount -t securityfs none /sys/kernel/security || {
echo >&2 'Could not mount /sys/kernel/security.'
echo >&2 'AppArmor detection and --privileged mode might break.'
}
fi
# cgroup v2: enable nesting
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
# move the processes from the root group to the /init group,
# otherwise writing subtree_control fails with EBUSY.
# An error during moving non-existent process (i.e., "cat") is ignored.
mkdir -p /sys/fs/cgroup/init
xargs -rn1 < /sys/fs/cgroup/cgroup.procs > /sys/fs/cgroup/init/cgroup.procs || :
# enable controllers
sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \
> /sys/fs/cgroup/cgroup.subtree_control
fi
# EXECUTE PROCESS:
/usr/local/bin/dockerd &
docker_pid=$!
# WAIT FOR CHILD PROCESS:
wait "$docker_pid"

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
###
# File: start-kasmvnc.sh
# Project: bin
# File Created: Thursday, 1st January 1970 12:00:00 pm
# Author: Console and webGui login account (jsunnex@gmail.com)
# -----
# Last Modified: Saturday, 8th July 2023 4:44:25 am
# Modified By: Console and webGui login account (jsunnex@gmail.com)
###
set -e
source /usr/bin/common-functions.sh
# CATCH TERM SIGNAL:
_term() {
kill -TERM "$kasmxproxy_pid" 2>/dev/null
pkill --signal TERM -P "$xvnc_pid" 2>/dev/null
}
trap _term SIGTERM SIGINT
# EXECUTE PROCESS:
# Wait for the X server to start
wait_for_x
# Start the Xvnc server
# vncserver :88 -fg -noxstartup -websocketPort ${PORT_NOVNC_WEB:?} -disableBasicAuth -interface 0.0.0.0 -dry-run
#eval "$(vncserver :88 -fg -noxstartup -websocketPort ${PORT_NOVNC_WEB:?} -disableBasicAuth -interface 0.0.0.0 -dry-run)" &
## xvnc_command="$(vncserver :88 -fg -noxstartup -websocketPort 8438 -disableBasicAuth -interface 0.0.0.0 -dry-run)"
## bash -c "${xvnc_command}" &
# NOTE: I've run it like this because the -fg is not doing anything when executed with vncserver.
# This prints the Xvnc command which is then executed.
vnc_server_args="${vnc_server_args:-} -hw3d -drinode /dev/dri/renderD128"
eval "$(vncserver :88 -fg -noxstartup -websocketPort ${PORT_NOVNC_WEB:?} -disableBasicAuth -interface 0.0.0.0 ${vnc_server_args:-} -dry-run)" &
xvnc_pid=$!
# Wait a few seconds for the Xvnc service to start
sleep 3
# Start the Kasm X Proxy
kasmxproxy -a :55 -v :88 &
kasmxproxy_pid=$!
# WAIT FOR CHILD PROCESS:
wait "$xvnc_pid"
wait "$kasmxproxy_pid"

View File

@@ -13,61 +13,42 @@ source /usr/bin/common-functions.sh
# CATCH TERM SIGNAL:
_term() {
kill -INT "$sunshine_pid" 2>/dev/null
sleep 0.5
counter=0
while kill -0 "$sunshine_pid"; do
kill -TERM "$sunshine_pid" 2>/dev/null
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 2
done
counter=0
while kill -0 "$sunshine_pid"; do
kill -KILL "$sunshine_pid" 2>/dev/null
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 1
done
kill -TERM "$sunshine_pid" 2>/dev/null
}
trap _term SIGTERM SIGINT
# CONFIGURE:
# Install default configurations
mkdir -p "${USER_HOME:?}/.config/sunshine"
if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine.conf" ]; then
cp -vf /templates/sunshine/sunshine.conf "${USER_HOME:?}/.config/sunshine/sunshine.conf"
fi
if [ ! -f "${USER_HOME:?}/.config/sunshine/apps.json" ]; then
cp -vf /templates/sunshine/apps.json "${USER_HOME:?}/.config/sunshine/apps.json"
fi
if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine_state.json" ]; then
echo "{}" > "${USER_HOME:?}/.config/sunshine/sunshine_state.json"
mkdir -p /home/${USER}/sunshine
if [[ ! -f /home/${USER}/sunshine/sunshine.conf ]]; then
cp -vf /templates/sunshine/* /home/${USER}/sunshine/
# TODO: Set the default encoder '# encoder = nvenc'
# nvidia_gpu_id=$(get_nvidia_gpu_id)
# if [[ "X${nvidia_gpu_id:-}" != "X" ]]; then
# if [[ "all video" == *"${NVIDIA_DRIVER_CAPABILITIES}"* ]]; then
# # Check if we have a nvidia GPU available
# sed -i 's|^# encoder.*=.*$|encoder = nvenc|' /home/${USER}/sunshine/sunshine.conf
# fi
# else
# # TODO: Enable the vaapi device if not using nvenc
# # vainfo --display drm --device /dev/dri/renderD128 2> /dev/null | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)"
# # Loop over any render devices
# echo
# fi
fi
# Reset the default username/password
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
/usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}"
fi
# Remove any auto-start scripts from user's .local dir
if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then
rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop"
sunshine /home/${USER}/sunshine/sunshine.conf --creds ${SUNSHINE_USER:-} ${SUNSHINE_PASS:-}
fi
# EXECUTE PROCESS:
# Wait for the X server to start
wait_for_x
# Start a session bus instance of dbus-daemon
wait_for_desktop_dbus_session
export_desktop_dbus_session
# Wait for the desktop to start
wait_for_desktop
# Start the sunshine server
/usr/bin/dumb-init /usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" &
sunshine /home/${USER}/sunshine/sunshine.conf &
sunshine_pid=$!

View File

@@ -17,12 +17,9 @@ _term() {
trap _term SIGTERM SIGINT
# CONFIGURE:
# Remove lockfile
rm -f /tmp/.started-udev
# EXECUTE PROCESS:
# Remove lockfile
rm -f /tmp/.udev-started
# Start udev
if command -v udevd &>/dev/null; then
unshare --net udevd --daemon &>/dev/null
@@ -34,7 +31,7 @@ udevadm monitor &
monitor_pid=$!
# Touch lockfile
sleep 1
touch /tmp/.started-udev
touch /tmp/.udev-started
# Wait for 10 seconds, then request device events from the kernel
sleep 10
udevadm trigger

View File

@@ -20,9 +20,7 @@ trap _term SIGTERM SIGINT
# EXECUTE PROCESS:
# Wait for udev
if [ $(grep autostart /etc/supervisor.d/udev.ini 2> /dev/null) == "autostart=true" ]; then
wait_for_udev
fi
wait_for_udev
# Run X server
/usr/bin/Xorg \
-ac \

View File

@@ -1,84 +0,0 @@
#!/usr/bin/env bash
###
# File: steam-headless-wol-power-manager
# Project: bin
# File Created: Tuesday, 5th September 2023 5:35:38 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 5th September 2023 5:35:38 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
# Function to execute restart to WoL monitor
restart_to_wol_monitor() {
# Create WoL monitor lock file. This will be read during the next restart and will trigger a singluar WoL monitor service.
touch /tmp/.wol-monitor
# Stop all processes inside the container by sending a SIGINT to the main supervisord process (PID 1)
kill -2 1
# Exit script
exit 0
}
# Function to execute restart to Desktop
restart_to_desktop_mode() {
# Remove WoL monitor lock file.
rm -f /tmp/.wol-monitor
# Stop all processes inside the container by sending a SIGINT to the main supervisord process (PID 1)
kill -2 1
# Exit script
exit 0
}
# Function to monitor for no user input
start_idle_monitor() {
# Set the idle timeout in milliseconds (60 minutes = 3600000 milliseconds)
local idle_timeout=3600000
# Monitor input. After an hour of no input
echo "Starting idle inputs monitor service..."
while true; do
# Sleep for a short interval (e.g., 1 minute) before checking
sleep 60
# Get the current idle time in milliseconds using xprintidle
idle_time=$(xprintidle)
# Check if the idle time exceeds the specified timeout
if [ "${idle_time:?}" -ge "${idle_timeout:?}" ]; then
# TODO: Check if any sessions exist in sunshine
# Execute restart to WoL monitor function
echo "No user activity for over 60 minutes. Entering WoL Monitor Mode."
restart_to_wol_monitor
fi
done
}
# Function to monitor for WoL events
start_wol_monitor() {
# Specify port to listen to (9 is the default WoL port).
listen_port=9
# Start the WoL monitor service
echo "Starting WoL monitor service..."
while true; do
# Listen for WoL magic packets on the specified port
tcpdump -i any -n -l -c 1 -q "udp port $listen_port and (udp[8:4] = 0xFFFFFFFF)"
# Execute restart to desktop function
echo "WoL event received. Entering Desktop Mode."
restart_to_desktop_mode
done
}
if [ -f "/tmp/.wol-monitor" ]; then
start_wol_monitor
else
start_idle_monitor
fi

View File

@@ -1,158 +0,0 @@
#!/usr/bin/env bash
###
# File: sunshine-run
# Project: bin
# File Created: Tuesday, 23rd August 2023 3:28:52 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Friday, 23rd August 2023 4:21:00 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
exec >> >(tee -a ${USER_HOME:?}/.cache/log/sunshine_run.log) 2>&1
echo
echo "-------------------------------"
echo
date
echo
echo "-------------------------------"
echo
echo "**** Execute sunshine-run ****"
echo
# Trap SIGINT, SIGQUIT, SIGHUP, SIGTERM to forward signals to the child process
_term() {
if [ -n "${proc_pid}" ]; then
# Read all child processes of proc_pid first
child_pids=$(pgrep -P $proc_pid)
# Forward the signal proc_pid
echo " - Checking for status of main process ${proc_pid}"
if kill -0 "${proc_pid}" 2>/dev/null; then
echo " - Forwarding signal $1 to process ${proc_pid}"
kill -s "${1}" "${proc_pid}"
else
echo " - Process ${proc_pid} is already stopped. Nothing to do here."
fi
for child_pid in ${child_pids:-}; do
echo " - Checking for status of child process ${child_pid}"
if kill -0 "${child_pid}" 2>/dev/null; then
echo " - Forwarding signal $1 to process ${child_pid}"
kill -s "${1}" "${child_pid}"
else
echo " - Process ${child_pid} is already stopped. Nothing to do here."
fi
done
fi
}
trap '_term INT' SIGINT
trap '_term QUIT' SIGQUIT
trap '_term HUP' SIGHUP
trap '_term TERM' SIGTERM
# Record sunshine-run PID
echo " - Recording sunshine-run PID '$$' in /tmp/sunshine-exec-run.pid"
echo "$$" > /tmp/sunshine-exec-run.pid
# Wipe session config
echo "" > /tmp/sunshine-exec-run.conf
# Update display resolution and refresh reate if client provided the required details
if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_FPS:-}" != "X" ]); then
# Don't fail script if something goes wrong here. Set +e in subprocess
(
set +e
echo " - Setting display resolution to ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} ${SUNSHINE_CLIENT_FPS:?}Hz"
# Read current display mode and extract resolution and refresh rate from the mode string
__xrandr_out="$(xrandr -q)"
__current_current_mode=$(echo "${__xrandr_out:?}" | awk '/\*/ {print $0}')
__current_resolution=$(echo ${__current_current_mode:?} | awk '{print $1}')
__current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}')
# Get the primary output device
__primary_output="$(echo "${__xrandr_out:?}" | grep primary | awk '{print $1}')"
# Get the modeline from cvt and extract the second line (which contains the modeline)
__client_modeline=$(cvt "${SUNSHINE_CLIENT_WIDTH:?}" "${SUNSHINE_CLIENT_HEIGHT:?}" "${SUNSHINE_CLIENT_FPS:?}" | grep Modeline | sed -e 's/Modeline //')
# Create a new mode for this. This allows us to force a set refresh rate that may not be supported by the display
__client_mode=$(echo "${__client_modeline:?}" | awk -F '"' '{print $2}')
# Check if this custom mode is already created
if ! echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
# Custom mode does not yet exist. Create it
echo " - Adding new mode '${__client_mode:?}' with new modeline '${__client_modeline:?}'"
xrandr --newmode "${__client_mode:?}" ${__client_modeline##*\"}
if [ $? -gt 0 ]; then
echo " - WARNING: Failed to add new mode '${__client_mode:?}'."
else
echo " - SUCCESS"
fi
else
echo " - Custom mode '${__client_mode:?}' already exists."
fi
# Check if custom mode exists
__xrandr_out="$(xrandr -q)"
if echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
# Check if this mode is already added to the primary display
if ! echo "${__xrandr_out:?}" | sed -n "/${__primary_output:?}/,/^[^[:space:]]/ {/^[[:space:]]/p}" | grep -q "${__client_mode:?}"; then
# Custom mode exists, but is not yet added to the primary output device. Add it
echo " - Adding custom mode '${__client_mode:?}' to device '${__primary_output:?}'"
xrandr --addmode "${__primary_output:?}" "${__client_mode:?}"
__mode_added=$?
if [ "${__mode_added:-0}" -gt 0 ]; then
echo " - WARNING: Failed to assign custom mode to primary output device '${__primary_output:?}'."
else
echo " - SUCCESS"
fi
else
echo " - Custom mode '${__client_mode:?}' is already configured for the primary output device."
__mode_added=0
fi
else
echo " - WARNING: Custom mode '${__client_mode:?}' does not exist."
fi
# Set the current resoultion to the new mode
if ([ "X${__mode_added:-}" = "X" ] || [ "${__mode_added:-0}" -gt 0 ]); then
echo " - Attempting to set the display mode to a supported '${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?}' mode. Note that this may not support the configured refresh rate."
xrandr --output "${__primary_output:?}" --mode ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} --refresh ${SUNSHINE_CLIENT_FPS:?}
if [ $? -gt 0 ]; then
echo " - WARNING: Failed to set current output to mode '${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?}' on device '${__primary_output:?}'."
else
echo " - SUCCESS"
fi
else
echo " - Setting the display mode to '${__client_mode:?}'"
xrandr --output "${__primary_output:?}" --mode "${__client_mode:?}" --rate "${SUNSHINE_CLIENT_FPS:?}"
if [ $? -gt 0 ]; then
echo " - WARNING: Failed to set current output to custom mode '${__client_mode:?}' on device '${__primary_output:?}'."
else
echo " - SUCCESS"
fi
fi
# Save original display settings to config file. This will be read and used to restore the original display settings when the client disconnects.
echo "primary_output='${__primary_output:?}'" >> /tmp/sunshine-exec-run.conf
echo "display_mode='${__current_resolution:?}'" >> /tmp/sunshine-exec-run.conf
echo "display_rate='${__current_refresh_rate:?}'" >> /tmp/sunshine-exec-run.conf
)
fi
# Run child process
/usr/bin/dumb-init "${@}" &
proc_pid=$!
# Wait for child process to exit:
echo " - Waiting for PID '${proc_pid}' to exit"
wait "$proc_pid"
# Clean up PID file
if [ -f /tmp/sunshine-exec-run.pid ]; then
echo " - Removing sunshine-run pidfile."
rm -f /tmp/sunshine-exec-run.pid
else
echo " - WARNING: No sunshine-run pidfile found for removal."
fi
echo "DONE"

View File

@@ -1,110 +0,0 @@
#!/usr/bin/env bash
###
# File: sunshine-stop
# Project: bin
# File Created: Tuesday, 23rd August 2023 3:28:52 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Friday, 23rd August 2023 4:21:00 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
exec >> >(tee -a ${USER_HOME:?}/.cache/log/sunshine_stop.log) 2>&1
echo
echo "-------------------------------"
echo
date
echo
echo "-------------------------------"
echo
echo "**** Execute sunshine-stop ****"
echo
# Read the run config
if [ -f /tmp/sunshine-exec-run.conf ]; then
echo " - Reading sunshine-run config."
. /tmp/sunshine-exec-run.conf
else
echo " - WARNING: No sunshine-run config found for import."
fi
# Read the process PID
if [ -f /tmp/sunshine-exec-run.pid ]; then
main_process_pid="$(cat /tmp/sunshine-exec-run.pid)"
echo " - Found initial sunshine-run PID '${main_process_pid}'."
else
echo " - WARNING: No sunshine-run PID found."
fi
# Send a INT signal to the PID (if it is found)
if [ "X${main_process_pid:-}" != "X" ]; then
echo " - Sending SIGINT to PID '${main_process_pid}'."
kill -INT "${main_process_pid}" || true
sleep 1
fi
# Run a loop to check for any other "sunshine-run" processes and send them also a INT signal
echo " - Checking for other sunshine-run processes..."
for process_pid in $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2}'); do
# Ensure this process is still running
if ! kill -0 "$process_pid" 2>/dev/null; then
continue
fi
echo " - Stopping PID '${process_pid}' - $(ps -p ${process_pid} -o command | awk 'NR>1')"
# Send this process a SIGINT
echo " - Sending SIGINT to PID '${process_pid}'."
kill -INT "${process_pid}" 2>/dev/null || true
sleep 0.5
# Send this process a SIGTERM every 2 seconds util stopped or until it has sent 3 signals
counter=0
while kill -0 "$process_pid" 2>/dev/null; do
echo " - Sending SIGTERM to PID '${process_pid}'."
kill -TERM "$process_pid" 2>/dev/null || true
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 2
done
# Send this process a SIGKILL every second until stopped or until it has sent 3 signals
counter=0
while kill -0 "$process_pid" 2>/dev/null; do
echo " - Sending SIGKILL to PID '${process_pid}'."
kill -KILL "$process_pid" 2>/dev/null || true
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 1
done
if ! kill -0 "$process_pid" 2>/dev/null; then
echo " - PID '${process_pid}' stopped."
else
echo " - ERROR: Failed to kill PID '${process_pid}'."
fi
done
echo " - All sunshine-run related processes are stopped."
# Check if the required information was stored for resetting the display resolution and refresh rate
if ([ "X${primary_output:-}" != "X" ] && [ "X${display_mode:-}" != "X" ] && [ "X${display_rate:-}" != "X" ]); then
# Reset display resolution and refresh rate
echo " - Resetting display resolution to ${display_mode:?} ${display_rate:?}Hz"
xrandr --output "${primary_output:?}" --mode "${display_mode:?}" --rate "${display_rate:?}"
else
echo " - WARNING: original display config not found. Resolution will not be reset."
fi
# Clean up config file
if [ -f /tmp/sunshine-exec-run.conf ]; then
echo " - Removing sunshine-run config."
rm -f /tmp/sunshine-exec-run.conf
else
echo " - WARNING: No sunshine-run config found for removal."
fi
# Clean up PID file
if [ -f /tmp/sunshine-exec-run.pid ]; then
echo " - Removing sunshine-run pidfile."
rm -f /tmp/sunshine-exec-run.pid
else
echo " - WARNING: No sunshine-run pidfile found for removal."
fi
echo "DONE"

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
###
# File: xfce4-close-all-windows
# Project: bin
# File Created: Tuesday, 22nd August 2023 3:28:52 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 22nd August 2023 3:28:52 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
# Get a list of open windows
WINDOW_IDS=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
# Close each window
for i in ${WINDOW_IDS}; do
wmctrl -ic "$i";
done
# Keep checking and waiting until all windows are closed
while [ "X${WINDOW_IDS:-}" != "X" ]; do
sleep 0.2;
WINDOW_IDS=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
done

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env bash
###
# File: xfce4-minimise-all-windows
# Project: bin
# File Created: Tuesday, 22nd August 2023 3:28:52 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 22nd August 2023 3:28:52 pm
# Modified By: Josh.5 (jsunnex@gmail.com)
###
set -e
# Get a list of open windows
WINDOW_IDS=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
# Minimise each window
for i in ${WINDOW_IDS}; do
wmctrl -ir "$i" -b add,hidden;
sleep 0.2
done