39 Commits

Author SHA1 Message Date
Josh.5
23e5ec9fa4 Add some sane defaults to Steam config
I can't imagine why we would not want compatibility on for all titles or why we would not want to have a good name and the correct path for the default library.
2025-06-23 06:03:31 +00:00
Josh.5
e39756c3bf If steam is enabled and this is the first boot, create the library config 2025-06-23 05:18:01 +00:00
Josh.5
77fc0221e5 Fix incorrect template for setting firefox as the default browser 2025-06-23 05:13:42 +00:00
Josh.5
67e55c50af Update GH workflow config 2025-06-23 04:30:19 +00:00
Josh.5
c3dc444a8f Fix up Ubnuntu server installation 2025-06-23 04:30:05 +00:00
Josh.5
0ac3a94009 Run NVIDIA driver download attempts in a loop 2025-06-23 02:56:32 +00:00
AlexanderOF
8dd20185a7 Update 60-configure_gpu_driver.sh
Add NVIDIA US Download server as alternative, when Global Download server fails
2025-06-23 14:47:22 +12:00
AlexanderOF
f0accf6102 Change NVIDIA Download Server to US
download.nvidia.com does not provide downloads for drivers and downloading the driver fails. The US Server works perfectly
2025-06-23 14:47:22 +12:00
Pablo Andres Dealbera
14c770bce6 docs: clarify installation of other game launchers 2025-02-06 08:01:43 +13:00
alansari
6db83d2a22 Another stable update for sunshine
not really needed as we arn't using the flatpak version i guess:

build(linux)!: remove legacy input option 
fix(flatpak): fix broken desktop file, icons, and service
fix(web-ui): fix new version notification conditions
chore(l10n): update translations
2025-01-27 17:54:05 +13:00
alansari
6199455ae7 remove libva-vdpau
Just to clean up the actions log, still not recommended to use
2025-01-20 08:52:39 +13:00
alansari
0c4c669ab0 switch back to stable debian sunshine 2025-01-20 08:52:10 +13:00
Josh.5
920bfa7f84 Add 'WEBUI_USER' and 'WEBUI_PASS'
These do not yet do anything, but they will soon enough.
2024-11-27 15:57:20 +13:00
Josh.5
463274d800 Add nodejs to build 2024-11-14 17:02:56 +13:00
alansari
0241c9f845 Update Dockerfile.debian
bump sunshine to latest pre-release
2024-09-05 01:17:55 +12:00
Josh.5
860451da74 Fix NVIDIA driver download for TrueNAS Scale Dragonfish
The previous fix had a few bugs. Because this is executed with `set -e`, the wget will cause the init process to fail if the url does not exist. Also, the github path was looking at an aarch64 download

Closes #156
2024-08-06 23:12:40 +12:00
Josh.5
b0ba3cfc8a Include gamescope with steam installation 2024-08-01 11:11:16 +12:00
Josh.5
77967f2845 Fix primary output detection in sunshine-run
Sometimes (perhaps with some recent update, it is listed as just "connected" not "primary".
2024-08-01 11:10:20 +12:00
Josh.5
ac9c4f29ca Fix default steam big picture launcher 2024-07-14 18:16:11 +12:00
WillKirkmanM
336a6284ec Fix(60-configure_gpu_driver.sh): Add fallback to GitHub for NVIDIA driver downloads
An issue opened https://github.com/Steam-Headless/docker-steam-headless/issues/152, specifically in TrueNas Scale where 4 versions are not available in the repository https://download.nvidia.com/XFree86/Linux-x86_64, (`545.23.08`, `555.42.06`, `545.23.08` and `555.42.06`) However, the saving grace is that these versions are required for GPU acceleration for Flatpaks.

> Thank you. I’m primarily facing issues because flatpak only has a package for .06, so all flatpak apps are no longer GPU accelerated as a result.

From: https://forums.developer.nvidia.com/t/545-23-08-is-not-listed-in-the-nvidia-driver-downloads-page/273181/3

To Solve this, FlatHub has created a NVIDIA Driver repository where these obscure version's `.run` files are available to download.
https://github.com/flathub/org.freedesktop.Platform.GL.nvidia/

The Entire process can be found in my Solution post: https://github.com/Steam-Headless/docker-steam-headless/issues/152#issuecomment-2208788858

This pull request first attempts to download the driver from the NVIDIA repository and then falls back to the Flathub repository while printing an error if it is unable to download the driver.
2024-07-06 20:23:51 +12:00
tem
9cf971f68f Update arch just so it builds 2024-06-20 13:45:38 +12:00
Josh.5
47f6f7a176 Improve documentation for Intel and AMD installations 2024-05-08 17:22:57 +12:00
Josh.5
28c19ed1b2 Update docker compose templates to not rely on NVIDIA runtime
Plenty of setups may have either nvidia container toolkit without the runtime wrapper, or no toolkit at all.
These updated templates allow for all those cases while still providing support for NVIDIA GPUs.
2024-03-15 04:52:32 +13:00
Josh.5
728acd0ba1 Remove env_file and add all env variables to a environment: section 2024-03-15 04:12:55 +13:00
Josh.5
a2caa9f4ec Add missing NVIDIA_DRIVER_VERSION variable to .env template
This is used when nvidia container toolkit is not used
2024-03-14 20:37:53 +13:00
Josh.5
9c20a0f1f5 Add ability to run NVIDIA containers without the NVIDIA container toolkit 2024-03-14 19:23:34 +13:00
Josh.5
f17d31d077 Enable support for external NVIDIA GPUs 2024-03-14 18:47:08 +13:00
Josh.5
e701b8870f Describe how to install the NVIDIA container toolkit on Ubuntu server 2024-03-14 18:38:04 +13:00
alansari
bd73b199d4 Update sunshine again to latest stable 2024-03-05 23:17:46 +13:00
tem
12a498e1eb Make SID repo optional 2024-02-29 13:55:17 +13:00
tem
63cfefa1fc Bump sunshine to stable & include res script from lyzardbyte docs 2024-02-29 13:54:19 +13:00
alansari
c3941d1f0b Quick patch for v550+ drivers 2024-02-29 13:53:37 +13:00
Josh.5
6cc9f56155 Delete out-dated run script
Better to use compose only or properly document a run command for users
2023-10-05 09:34:34 +13:00
Josh.5
a17fe91113 Hide file copy log. No need for this to be verbose 2023-10-02 20:17:29 +13:00
Josh.5
a5f189dbc3 Update to the latest nightly sunshine 2023-10-02 20:15:02 +13:00
Josh.5
8f32302c0f Improvements to the init scripts 2023-10-02 19:43:50 +13:00
Josh.5
ca7521d765 Fix build and install mesa during container startup
This brings the Mesa and Vulkan installation in-line with the NVIDIA driver installation for NVIDIA GPU users.
2023-10-02 19:14:28 +13:00
Josh.5
c165e28f07 Add variable FORCE_X11_DUMMY_CONFIG for forcing the initial use of the dummy xorg config 2023-10-02 11:13:17 +13:00
Josh.5
7f04d8df01 Pull mesa from SID 2023-09-30 13:39:37 +13:00
36 changed files with 1319 additions and 856 deletions

View File

@@ -1,144 +1,170 @@
---
name: Build and Deploy CI name: Build and Deploy CI
on: on:
workflow_dispatch:
push: push:
branches: [ 'dev-**', 'pr-**', staging, master ] branches: ['dev-**', 'pr-**', staging, master]
tags: [ '**' ] tags: ['**']
pull_request: pull_request:
branches: [ staging, master ] branches: [staging, master]
schedule: schedule:
# At 02:30 on Saturday # At 02:30 on Saturday
- cron: '30 2 * * 6' - cron: '30 2 * * 6'
jobs: jobs:
build_docker: build_docker:
name: Build Docker Image name: Build Docker Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
flavour: ["debian", "arch"] flavour: ['debian', 'arch']
steps: steps:
# Fetch shallow git repository # ---
- name: Checkout - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
# Use QEMU to build # ---
- name: Set up QEMU - name: Set up Docker Buildx
if: success() uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0
id: qemu
uses: docker/setup-qemu-action@v1
# Use docker buildx to build the docker image # ---
- name: Build the Docker image - name: Prepare
uses: docker/setup-buildx-action@v1 if: success()
if: success() id: prepare
id: buildx run: |
with: FLAVOUR=${{ matrix.flavour }}
version: latest echo "FLAVOUR='${FLAVOUR}'"
echo "GITHUB_REF='${GITHUB_REF}'"
echo "GITHUB_REPOSITORY='${GITHUB_REPOSITORY}'"
VERSION_TAG=${GITHUB_REF#refs/*/}
SHA_SHORT="${GITHUB_SHA::7}"
ORG=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
BUILD_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
# Generate 'prepare' build arguments to be retrieved later on SERVICE_NAME=steam-headless
- name: Prepare DOCKER_HUB_IMAGE=docker.io/josh5/${SERVICE_NAME:?}
if: success() GHCR_IMAGE=ghcr.io/${ORG:?}/${SERVICE_NAME:?}
id: prepare
run: | DOCKER_TAGS=""
FLAVOUR=${{ matrix.flavour }} if [[ ${GITHUB_REF} == refs/heads/master ]]; then
echo "FLAVOUR='${FLAVOUR}'"
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},"
elif [[ ${VERSION_TAG%/merge} == 'staging' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-staging,"
elif [[ ${VERSION_TAG%/merge} =~ "dev-"* ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${FLAVOUR}-${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 if [[ ${FLAVOUR} == 'debian' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest," DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:latest,${GHCR_IMAGE}:latest,${GHCR_IMAGE}:stable,"
fi fi
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:${FLAVOUR},${GHCR_IMAGE}:${FLAVOUR},"
elif [[ ${GITHUB_REF} == refs/heads/staging ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:${FLAVOUR}-staging,${GHCR_IMAGE}:${FLAVOUR}-staging,"
elif [[ ${GITHUB_REF} == refs/heads/dev-* ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:${FLAVOUR}-${VERSION_TAG},${GHCR_IMAGE}:${FLAVOUR}-${VERSION_TAG},"
elif [[ ${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_HUB_IMAGE}:${FLAVOUR}-${VERSION},${GHCR_IMAGE}:${FLAVOUR}-${VERSION},"
if [[ ${FLAVOUR} == 'debian' ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:latest,${GHCR_IMAGE}:latest,"
fi
fi
elif [[ ${GITHUB_REF} == refs/pull/* ]]; then
PR_NUMBER=$(echo ${GITHUB_REF} | cut -d'/' -f3)
# For PR builds, only tag the GHCR image.
DOCKER_TAGS="${GHCR_IMAGE}:pr-${PR_NUMBER},"
fi fi
fi echo "DOCKER_TAGS='${DOCKER_TAGS}'"
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}] [${FLAVOUR}]" > ./overlay/version.txt
DOCKER_PUSH="true" DOCKER_PUSH="true"
if [[ ${DOCKER_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then if [[ ${DOCKER_HUB_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
if [[ ${VERSION_TAG%/merge} =~ "pr-"* ]]; then if [[ ${VERSION_TAG%/merge} =~ "pr-"* ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
if [[ "X${DOCKER_TAGS}" == "X" ]]; then if [[ "X${DOCKER_TAGS}" == "X" ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
echo "DOCKER_PUSH='${DOCKER_PUSH}'" echo "DOCKER_PUSH='${DOCKER_PUSH}'"
cat ./overlay/version.txt cat ./overlay/version.txt
echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT echo "docker_hub_image:${DOCKER_HUB_IMAGE:?}"
echo "docker_tags=$(echo ${DOCKER_TAGS} | sed 's/,$//')" >> $GITHUB_OUTPUT echo "docker_hub_image=${DOCKER_HUB_IMAGE:?}" >> $GITHUB_OUTPUT
echo "docker_platforms=linux/amd64" >> $GITHUB_OUTPUT
echo "docker_push=${DOCKER_PUSH}" >> $GITHUB_OUTPUT
# Cache the build echo "ghcr_image:${GHCR_IMAGE:?}"
- name: Cache Docker layers echo "ghcr_image=${GHCR_IMAGE:?}" >> $GITHUB_OUTPUT
uses: actions/cache@v2
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ matrix.flavour }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ matrix.flavour }}-
# Login to Docker Hub echo "sha_short:${SHA_SHORT:?}"
- name: Login to Docker Hub echo "sha_short=${SHA_SHORT:?}" >> $GITHUB_OUTPUT
if: success() && (startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/tags/'))
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# Run docker build and push echo "service_name:${SERVICE_NAME:?}"
- name: Docker Build and Push echo "service_name=${SERVICE_NAME:?}" >> $GITHUB_OUTPUT
if: success()
uses: docker/build-push-action@v2
with:
context: .
file: Dockerfile.${{ matrix.flavour }}
pull: true
platforms: ${{ steps.prepare.outputs.docker_platforms }}
push: ${{ steps.prepare.outputs.docker_push }}
tags: |
${{ steps.prepare.outputs.docker_tags }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new
# Keep only latest cache echo "docker_image:${DOCKER_HUB_IMAGE:?}"
# https://github.com/docker/build-push-action/issues/252 echo "docker_image=${DOCKER_HUB_IMAGE:?}" >> $GITHUB_OUTPUT
# https://github.com/moby/buildkit/issues/1896
- name: Move cache echo "docker_tags:$(echo ${DOCKER_TAGS} | sed 's/,$//')"
if: always() echo "docker_tags=$(echo ${DOCKER_TAGS} | sed 's/,$//')" >> $GITHUB_OUTPUT
run: |
if [[ -e /tmp/.buildx-cache-new ]]; then echo "docker_push:${DOCKER_PUSH:?}"
echo "Cleaning up old cache..." echo "docker_push=${DOCKER_PUSH:?}" >> $GITHUB_OUTPUT
rm -rf /tmp/.buildx-cache
mv -v /tmp/.buildx-cache-new /tmp/.buildx-cache echo "docker_build_date:${BUILD_DATE:?}"
fi echo "docker_build_date=${BUILD_DATE:?}" >> $GITHUB_OUTPUT
echo "docker_platforms=linux/amd64" >> $GITHUB_OUTPUT
# ---
- name: Log into GHCR registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# ---
- name: Log into Docker Hub registry
if: success() && (startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/tags/'))
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# ---
- name: Docker meta
if: success()
id: meta
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 #v5.6.1
with:
images: |
${{ steps.prepare.outputs.docker_image }}
labels: |
maintainer=Josh.5
source.version=${{ steps.prepare.outputs.sha_short }}
source.project=Steam Headless
source.service=${{ steps.prepare.outputs.service_name }}
org.opencontainers.image.title=${{ steps.prepare.outputs.service_name }}
org.opencontainers.image.created=${{ steps.prepare.outputs.docker_build_date }}
# ---
- name: Build Image
if: success()
uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc #v6.11.0
with:
context: .
file: Dockerfile.${{ matrix.flavour }}
platforms: ${{ steps.prepare.outputs.docker_platforms }}
pull: 'true'
push: ${{ steps.prepare.outputs.docker_push }}
tags: |
${{ steps.prepare.outputs.docker_tags }}
labels: |
${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ steps.prepare.outputs.service_name }}-${{ matrix.flavour }}-main
cache-to: type=gha,scope=${{ steps.prepare.outputs.service_name }}-${{ matrix.flavour }}-main,mode=max

View File

@@ -35,6 +35,7 @@ RUN \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
@@ -49,6 +50,8 @@ RUN \
docbook-xml \ docbook-xml \
docbook-xsl \ docbook-xsl \
fakeroot \ fakeroot \
p7zip \
patch \
git \ git \
jq \ jq \
less \ less \
@@ -67,6 +70,7 @@ RUN \
unzip \ unzip \
vim \ vim \
wget \ wget \
xmlstarlet \
xz \ xz \
&& \ && \
echo "**** Install python ****" \ echo "**** Install python ****" \
@@ -79,6 +83,7 @@ RUN \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
@@ -111,9 +116,10 @@ RUN \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -rf \ && rm -fr /var/cache/pacman/pkg/* \
/tmp/yay* \ && rm -rf /tmp/yay* \
&& \ && \
echo echo
@@ -126,51 +132,37 @@ RUN \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# XFS requirements # Install mscorefonts
RUN \ RUN \
echo "**** Install XFS requirements ****" \ echo "**** Install ms fonts ****" \
&& pacman -Syu --noconfirm --needed \ && su - default -c "yay -Syu --noconfirm --needed ttf-msfonts" \
xfsdump \
xfsprogs \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& \
echo
# Install mesa requirements
RUN \
echo "**** Install mesa and vulkan requirements ****" \
&& pacman -Syu --noconfirm --needed \
glu \
libva-mesa-driver \
mesa-utils \
mesa-vdpau \
pciutils \
vulkan-mesa-layers \
vdpauinfo \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \ && \
echo echo
# Install X Server requirements # Install X Server requirements
ENV \ ENV \
XORG_SOCKET_DIR="/tmp/.X11-unix" \ XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
XDG_SESSION_TYPE="x11" \
FORCE_X11_DUMMY_CONFIG="false"
RUN \ RUN \
echo "**** Install X Server requirements ****" \ echo "**** Install X Server requirements ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
avahi \ avahi \
dbus \ dbus \
lib32-fontconfig \ lib32-fontconfig \
ttf-liberation \ fuse2 \
x11vnc \ x11vnc \
xorg \ xorg \
xorg-apps \ xorg-apps \
@@ -190,11 +182,14 @@ RUN \
xorg-xrandr \ xorg-xrandr \
xorg-xsetroot \ xorg-xsetroot \
xorg-xwininfo \ xorg-xwininfo \
xf86-input-evdev \
xterm \ xterm \
gamescope \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
@@ -213,6 +208,7 @@ RUN \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
@@ -226,110 +222,75 @@ RUN \
xfce4-goodies \ xfce4-goodies \
xfce4-terminal \ xfce4-terminal \
ttf-liberation \ ttf-liberation \
# Delete these as they are not needed at all xdg-user-dirs \
&& rm -f \ xdg-utils \
/usr/share/applications/software-properties-drivers.desktop \ imagemagick \
/usr/share/applications/xfce4-about.desktop \ && \
/usr/share/applications/xfce4-session-logout.desktop \ echo "**** Install WoL Manager requirements ****" \
# Hide these apps. They can be displayed if a user really wants them. && pacman -Syu --noconfirm --needed \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \ tcpdump \
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \ xprintidle \
&& 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 \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# TODO: Add support for flatpaks # 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 \ ENV \
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/" XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
RUN \ RUN \
echo "**** Install flatpak support ****" \ echo "**** Install flatpak support ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
flatpak \ flatpak \
gnome-software \
xdg-desktop-portal-gtk \ xdg-desktop-portal-gtk \
gnome-software \
&& \ && \
#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 ****" \ echo "**** Configure flatpak ****" \
&& chmod u-s /usr/bin/bwrap \ && chmod u-s /usr/bin/bwrap \
&& flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \ && flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \
&& su - default -c "flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo" \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# Install noVNC # TODO: Deprecate neko
# TODO: Add nginx or remove the whole proxy setup and just connect directly for audio (I think that is the better option) # Install Neko server
ARG NOVNC_VERSION=1.2.0 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
RUN \ RUN \
echo "**** Fetch noVNC ****" \ echo "**** Fetch Web Frontend ****" \
&& 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 \ && mkdir -p /opt \
&& rm -rf /opt/noVNC \
&& cd /opt \ && cd /opt \
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \ && rm -rf /opt/frontend \
&& cd /opt/noVNC \ && git clone https://github.com/Steam-Headless/frontend.git --branch master /opt/frontend \
&& ln -s vnc.html index.html \ && cd /opt/frontend \
&& chmod -R 755 /opt/noVNC \ && git checkout ${FRONTEND_VERSION} 2> /dev/null \
&& git submodule init \
&& git submodule update --depth 1 --recursive \
&& rm -rf /opt/frontend/.git \
&& \ && \
echo "**** Modify noVNC title ****" \ echo "**** Configure Web Frontend ****" \
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \ && echo '<!DOCTYPE html>' > /opt/frontend/index.html \
/opt/noVNC/app/ui.js \ && 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 \
echo "**** Install nginx support ****" \ && convert /opt/frontend/web/images/icons/novnc-ios-180.png -resize "128x128" /tmp/steam-headless.png \
&& pacman -Syu --noconfirm --needed \ && xdg-icon-resource install --novendor --size 128 /tmp/steam-headless.png \
nginx \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && rm -f /tmp/steam-headless.png
&& rm -fr /var/lib/pacman/sync/* \
&& rm -rf \
/tmp/noVNC* \
/tmp/novnc.tar.gz \
&& \
echo
# Install Websockify # Install Websockify
ARG WEBSOCKETIFY_VERSION=0.10.0 ARG WEBSOCKETIFY_VERSION=0.11.0
RUN \ RUN \
echo "**** Fetch Websockify ****" \ echo "**** Fetch Websockify ****" \
&& cd /tmp \ && cd /tmp \
@@ -345,6 +306,7 @@ RUN \
&& \ && \
echo "**** Install Websockify to noVNC path ****" \ echo "**** Install Websockify to noVNC path ****" \
&& cd /tmp \ && cd /tmp \
&& mkdir -p /opt/noVNC/utils \
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \ && mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
@@ -365,51 +327,147 @@ RUN \
gst-plugins-good \ gst-plugins-good \
gst-plugins-ugly \ gst-plugins-ugly \
&& \ && \
echo "**** Fetch ucspi-tcp ****" \ #echo "**** Fetch ucspi-tcp ****" \
&& mkdir -p /tmp/ucspi-tcp-0.88 \ # && mkdir -p /tmp/ucspi-tcp-0.88 \
&& cd /tmp \ # && 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 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 \ # && 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 \ # && cd /tmp/ucspi-tcp-0.88 \
&& tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \ # && 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 -fr /var/cache/pacman/pkg/* \
&& \ && \
echo "**** Build and install ucspi-tcp ****" \ echo
&& 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 \ # Setup video streaming deps
&& patch -p1 --input=ucspi-tcp-0.88.errno.patch \ RUN \
&& patch -p1 --input=ucspi-tcp-0.88.a_record.patch \ echo "**** Install video streaming deps ****" \
&& sed -i 's|^/usr/local|/usr|' /tmp/ucspi-tcp-0.88/conf-home \ && pacman -Syu --noconfirm --needed \
&& make \ libva \
&& for f in tcpserver tcprules tcprulescheck argv0 recordio tcpclient *\@ tcpcat mconnect mconnect-io addcr delcr fixcrio rblsmtpd; do \ libva-mesa-driver \
cp $f /usr/bin/$f; \ libva-intel-driver \
done \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -rf \ && rm -fr /var/cache/pacman/pkg/* \
/tmp/ucspi-tcp-* \ && \
echo
# Install tools for monitoring hardware
RUN \
echo "**** Install audio streaming deps ****" \
&& pacman -Syu --noconfirm --needed \
#cpu-x \
htop \
libva-utils \
vdpauinfo \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \
echo
# Install Sunshine
RUN \
echo "**** Install stable sunshine ****" \
&& su - default -c "yay -Syu --noconfirm --needed miniupnpc sunshine-bin" \
&& setcap cap_sys_admin+p $(readlink -f $(which sunshine)) \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \
echo
# Install Firefox
RUN \
echo "**** Install Firefox ****" \
&& pacman -Syu --noconfirm --needed \
firefox \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# Install Steam # Install Steam
RUN \ RUN \
echo "**** Install X Server requirements ****" \ echo "**** Install Steam ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
steam \ steam \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \ && rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \
echo
# Various other tools
ARG DUMB_INIT_VERSION=1.2.5
ARG DUMB_UDEV_VERSION=64d1427
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 "**** Install dumb-udev ****" \
&& python3 -m pip install \
--break-system-packages \
--pre \
--upgrade \
--no-cache-dir \
git+https://github.com/Steam-Headless/dumb-udev.git@${DUMB_UDEV_VERSION} \
&& \
echo
# Install Protonup replacement
RUN \
echo "**** Install PorotonUP ****" \
&& su - default -c "yay -Sy --noconfirm --needed --overwrite \"/usr/bin/normalizer\" protonup-qt" \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \ && \
echo echo
# Add FS overlay # Add FS overlay
COPY overlay / COPY overlay /
# Tweaks as flatpak issue isn't sorted
RUN \ RUN \
echo "**** Setup Steam Supervisor ****" \ echo "**** Tweaks for Arch ****" \
&& sed -i 's#/usr/games/steam#/usr/bin/steam#g' /etc/supervisor.d/steam.ini \ && sed -i d /usr/bin/install_firefox.sh \
&& sed -i d /usr/bin/install_protonup.sh \
&& sed -i d /templates/home_directory_template/.local/share/xfce4/helpers/custom-WebBrowser.desktop \
&& \ && \
echo echo
@@ -426,6 +484,7 @@ ENV \
NVIDIA_VISIBLE_DEVICES="all" NVIDIA_VISIBLE_DEVICES="all"
# Set container configuration environment variables # Set container configuration environment variables
# APPIMAGE_EXTRACT_AND_RUN="0"
ENV \ ENV \
MODE="primary" \ MODE="primary" \
WEB_UI_MODE="vnc" \ WEB_UI_MODE="vnc" \
@@ -434,8 +493,9 @@ ENV \
NEKO_PASSWORD_ADMIN=admin \ NEKO_PASSWORD_ADMIN=admin \
ENABLE_STEAM="true" \ ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \ STEAM_ARGS="-silent" \
ENABLE_SUNSHINE="false" \ ENABLE_SUNSHINE="true" \
ENABLE_EVDEV_INPUTS="false" ENABLE_EVDEV_INPUTS="true" \
ENABLE_WOL_POWER_MANAGER="false"
# Configure required ports # Configure required ports
ENV \ ENV \

View File

@@ -144,55 +144,13 @@ RUN \
&& \ && \
echo 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 \
&& apt-get update \
&& \
echo "**** Install mesa requirements ****" \
&& apt-get install -y --no-install-recommends \
libgl1-mesa-dri \
libgl1-mesa-glx \
libgles2-mesa \
libglu1-mesa \
mesa-utils \
mesa-utils-extra \
&& \
echo "**** Install vulkan requirements ****" \
&& apt-get install -y --no-install-recommends \
libvulkan1 \
libvulkan1:i386 \
mesa-vulkan-drivers \
mesa-vulkan-drivers:i386 \
vulkan-tools \
&& \
echo "**** Install desktop requirements ****" \
&& apt-get install -y --no-install-recommends \
libdbus-1-3 \
libegl1 \
libgtk-3-0 \
libgtk2.0-0 \
libsdl2-2.0-0 \
&& \
echo "**** Section cleanup ****" \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf \
/var/lib/apt/lists/* \
/var/tmp/* \
/tmp/* \
&& \
echo
# Install X Server requirements # Install X Server requirements
# TODO: Refine this list of packages to only what is required. # TODO: Refine this list of packages to only what is required.
ENV \ ENV \
XORG_SOCKET_DIR="/tmp/.X11-unix" \ XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \ XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
XDG_SESSION_TYPE="x11" XDG_SESSION_TYPE="x11" \
FORCE_X11_DUMMY_CONFIG="false"
RUN \ RUN \
echo "**** Update apt database ****" \ echo "**** Update apt database ****" \
&& apt-get update \ && apt-get update \
@@ -244,7 +202,7 @@ RUN \
echo "**** Update apt database ****" \ echo "**** Update apt database ****" \
&& apt-get update \ && apt-get update \
&& \ && \
echo "**** Install X Server requirements ****" \ echo "**** Install pulseaudio requirements ****" \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
pulseaudio \ pulseaudio \
alsa-utils \ alsa-utils \
@@ -267,6 +225,14 @@ RUN \
echo "**** Update apt database ****" \ echo "**** Update apt database ****" \
&& apt-get update \ && apt-get update \
&& \ && \
echo "**** Install desktop requirements ****" \
&& apt-get install -y --no-install-recommends \
libdbus-1-3 \
libegl1 \
libgtk-3-0 \
libgtk2.0-0 \
libsdl2-2.0-0 \
&& \
echo "**** Install desktop environment ****" \ echo "**** Install desktop environment ****" \
&& apt-get install -y \ && apt-get install -y \
fonts-vlgothic \ fonts-vlgothic \
@@ -341,14 +307,21 @@ RUN \
&& \ && \
echo echo
# TODO: Deprecate neko
# 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 # Install Web Frontend
ARG NODE_VERSION="v20"
ARG FRONTEND_VERSION=a8eb92f ARG FRONTEND_VERSION=a8eb92f
RUN \ RUN \
echo "**** Install Node ${NODE_VERSION} ****" \
&& mkdir -p /tmp/nodejs \
&& rm -rf /opt/nodejs \
&& wget -qO /tmp/nodejs/nodejs.tar.xz \
"https://nodejs.org/dist/latest-${NODE_VERSION:?}.x/node-$(wget -qO- https://nodejs.org/dist/latest-${NODE_VERSION:?}.x/ | sed -nE 's|.*>node-(.*)-linux-x64\.tar.xz</a>.*|\1|p')-linux-x64.tar.xz" \
&& tar -xJf /tmp/nodejs/nodejs.tar.xz -C /tmp/nodejs --strip-components=1 \
&& mv /tmp/nodejs /opt/nodejs \
&& ln -sf /opt/nodejs/bin/node /usr/local/bin/node \
&& ln -sf /opt/nodejs/bin/npm /usr/local/bin/npm \
&& ln -sf /opt/nodejs/bin/npx /usr/local/bin/npx \
&& \
echo "**** Fetch Web Frontend ****" \ echo "**** Fetch Web Frontend ****" \
&& mkdir -p /opt \ && mkdir -p /opt \
&& cd /opt \ && cd /opt \
@@ -486,8 +459,30 @@ RUN \
&& \ && \
echo echo
# Install Steam
RUN \
echo "**** Update apt database ****" \
&& dpkg --add-architecture i386 \
&& apt-get update \
&& \
echo "**** Install Steam ****" \
&& apt-get install -y --no-install-recommends \
steam-installer \
gamescope \
&& 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
# Install Sunshine # Install Sunshine
COPY --from=lizardbyte/sunshine:b00d7af-debian-bookworm /sunshine.deb /usr/src/sunshine.deb COPY --from=lizardbyte/sunshine:v2025.122.141614-debian-bookworm /sunshine.deb /usr/src/sunshine.deb
RUN \ RUN \
echo "**** Update apt database ****" \ echo "**** Update apt database ****" \
&& apt-get update \ && apt-get update \
@@ -510,25 +505,10 @@ RUN \
&& \ && \
echo echo
# Install Steam # TODO: Deprecate neko
RUN \ # Install Neko server
echo "**** Update apt database ****" \ COPY --from=m1k1o/neko:base /usr/bin/neko /usr/bin/neko
&& apt-get update \ COPY --from=m1k1o/neko:base /var/www /var/www
&& \
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 # Various other tools
ARG DUMB_INIT_VERSION=1.2.5 ARG DUMB_INIT_VERSION=1.2.5
@@ -566,6 +546,7 @@ ENV \
NVIDIA_VISIBLE_DEVICES="all" NVIDIA_VISIBLE_DEVICES="all"
# Set container configuration environment variables # Set container configuration environment variables
# TODO: Set the default WEBUI_USER & WEBUI_PASS after release of SHUI
ENV \ ENV \
MODE="primary" \ MODE="primary" \
WEB_UI_MODE="vnc" \ WEB_UI_MODE="vnc" \
@@ -574,9 +555,12 @@ ENV \
NEKO_PASSWORD_ADMIN=admin \ NEKO_PASSWORD_ADMIN=admin \
ENABLE_STEAM="true" \ ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \ STEAM_ARGS="-silent" \
WEBUI_USER="" \
WEBUI_PASS="" \
ENABLE_SUNSHINE="true" \ ENABLE_SUNSHINE="true" \
ENABLE_EVDEV_INPUTS="true" \ ENABLE_EVDEV_INPUTS="true" \
ENABLE_WOL_POWER_MANAGER="false" ENABLE_WOL_POWER_MANAGER="false" \
ENABLE_SID="false"
# Configure required ports # Configure required ports
ENV \ ENV \

View File

@@ -11,7 +11,7 @@ Easily deploy a Steam Docker instance in seconds.
## Features: ## Features:
- Steam Client configured for running on Linux with Proton - Steam Client configured for running on Linux with Proton
- Moonlight compatible server for easy remote desktop streaming - Moonlight compatible server for easy remote desktop streaming
- One click installation of EmeDeck, Heroic and Lutris - Easy installation of EmeDeck, Heroic and Lutris via Flatpak
- Full video/audio noVNC web access to a Xfce4 Desktop - Full video/audio noVNC web access to a Xfce4 Desktop
- NVIDIA, AMD and Intel GPU support - NVIDIA, AMD and Intel GPU support
- Full controller support - Full controller support
@@ -26,6 +26,8 @@ Easily deploy a Steam Docker instance in seconds.
If you wish to install additional applications, you can generate a script inside the `~/init.d` directory ending with ".sh". If you wish to install additional applications, you can generate a script inside the `~/init.d` directory ending with ".sh".
This will be executed on the container startup. This will be executed on the container startup.
Also, you can install applications using the WebUI under **Applications > System > Software**. There you can install other game launchers like Lutris, Heroic or EmuDeck.
### STORAGE PATHS: ### STORAGE PATHS:
Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified. Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified.
All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template. All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template.

View File

@@ -1,136 +0,0 @@
#!/usr/bin/env bash
###
# File: run.sh
# Project: docker-steamos
# File Created: Saturday, 8th January 2022 2:34:23 pm
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 8th February 2022 8:00:29 am
# Modified By: Console and webGui login account (jsunnex@gmail.com)
###
script_path=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd );
project_base_path=$(realpath ${script_path}/..);
# Parse params
additional_docker_params=""
container_name="steam"
tag="develop"
for ARG in ${@}; do
case ${ARG} in
*primary)
primary="true";
;;
*nvidia)
nvidia="true";
;;
*fb)
framebuffer="true";
;;
*br0)
network="br0";
;;
stop)
script_mode="stop"
;;
tail)
script_mode="tail"
;;
user)
script_mode="user"
;;
root)
script_mode="root"
;;
*arch)
tag="arch";
;;
*debian)
tag="debian";
;;
*)
;;
esac
done
if [[ "${primary}" == "true" ]]; then
container_name="${container_name}-p"
additional_docker_params="${additional_docker_params} -e MODE=primary"
hostx="false"
elif [[ "${framebuffer}" == "true" ]]; then
# TODO: Enable xvfb
container_name="${container_name}-fb"
additional_docker_params="${additional_docker_params} -e MODE=framebuffer"
else
container_name="${container_name}-s"
additional_docker_params="${additional_docker_params} -e MODE=secondary"
fi
if [[ "${nvidia}" == "true" ]]; then
container_name="${container_name}-hw"
additional_docker_params="${additional_docker_params} --runtime=nvidia"
fi
if [[ "${network}" == "br0" ]]; then
additional_docker_params="${additional_docker_params} --network=br0 --ip='192.168.1.208'"
else
additional_docker_params="${additional_docker_params} --network=host"
fi
if [[ -e /dev/dri ]]; then
additional_docker_params="${additional_docker_params} --device=/dev/dri"
fi
# If a mode was given, run that instead
if [[ "${script_mode}" == "stop" ]]; then
docker stop ${container_name}
docker rm ${container_name}
exit $?
elif [[ "${script_mode}" == "tail" ]]; then
docker logs -f ${container_name}
exit $?
elif [[ "${script_mode}" == "user" ]]; then
docker exec -ti --user default ${container_name} bash
exit $?
elif [[ "${script_mode}" == "root" ]]; then
docker exec -ti --user 0 ${container_name} bash
exit $?
fi
# Stop previous instance
docker stop ${container_name}
docker rm ${container_name}
sleep 1
# Run
cmd="docker run -d --name='${container_name}' \
--privileged=true \
-e PUID='99' \
-e PGID='100' \
-e UMASK='000' \
-e USER_PASSWORD='password' \
-e USER='default' \
-e USER_HOME='/home/default' \
-e TZ='Pacific/Auckland' \
-e USER_LOCALES='en_US.UTF-8 UTF-8' \
-e DISPLAY_CDEPTH='24' \
-e DISPLAY_REFRESH='60' \
-e DISPLAY_SIZEH='720' \
-e DISPLAY_SIZEW='1280' \
-e DISPLAY_VIDEO_PORT='DFP' \
-e DISPLAY=':55' \
-e NVIDIA_DRIVER_CAPABILITIES='all' \
-e NVIDIA_VISIBLE_DEVICES='all' \
-e ENABLE_VNC_AUDIO='false' \
-v '${project_base_path}/config/home/default-${container_name}':'/home/default':'rw' \
-v '/tmp/.X11-unix/':'/tmp/.X11-unix/':'rw' \
-v '/dev/input':'/dev/input':'ro' \
--hostname='${container_name}' \
--add-host=${container_name}:127.0.0.1 \
--shm-size=2G \
${additional_docker_params} \
josh5/steam-headless:${tag}"
echo ${cmd}
bash -c "${cmd}"
docker logs -f ${container_name}

View File

@@ -5,18 +5,20 @@
# |____/ \__, |___/\__\___|_| |_| |_| # |____/ \__, |___/\__\___|_| |_| |_|
# |___/ # |___/
# #
NAME='SteamHeadless' NAME=SteamHeadless
TZ='Pacific/Auckland' TZ=Pacific/Auckland
USER_LOCALES='en_US.UTF-8 UTF-8' USER_LOCALES=en_US.UTF-8 UTF-8
DISPLAY=':55' DISPLAY=:55
SHM_SIZE='2G' SHM_SIZE=2G
## DOCKER_RUNTIME: ## HOME_DIR:
## Options: ['runc', 'nvidia'] ## Description: The path to the home directory on your host. Mounts to `/home/default` inside the container.
## Description: The name of an implementation of OCI Runtime Spec HOME_DIR=/opt/container-data/steam-headless/home
## Available runtimes are listed when you run `docker info`. ## SHARED_SOCKETS_DIR:
## Your system may have other options available. As a simple rule, if you are ## Description: Shared sockets such as pulse audio and X11.
## using an NVIDIA GPU, set this to 'nvidia' for anything else, set this to 'runc'. SHARED_SOCKETS_DIR=/opt/container-data/steam-headless/sockets
DOCKER_RUNTIME='runc' ## GAMES_DIR:
## Description: The path to the games directory on your host. Mounts to `/mnt/games` inside the container.
GAMES_DIR=/mnt/games
# ____ __ _ _ _ _ # ____ __ _ _ _ _
# | _ \ ___ / _| __ _ _ _| | |_ | | | |___ ___ _ __ # | _ \ ___ / _| __ _ _ _| | |_ | | | |___ ___ _ __
@@ -25,10 +27,10 @@ DOCKER_RUNTIME='runc'
# |____/ \___|_| \__,_|\__,_|_|\__| \___/|___/\___|_| # |____/ \___|_| \__,_|\__,_|_|\__| \___/|___/\___|_|
# #
# #
PUID='1000' PUID=1000
PGID='1000' PGID=1000
UMASK='000' UMASK=000
USER_PASSWORD='password' USER_PASSWORD=password
# __ __ _ # __ __ _
# | \/ | ___ __| | ___ # | \/ | ___ __| | ___
@@ -42,7 +44,7 @@ USER_PASSWORD='password'
## Description: Steam Headless containers can run in a secondary mode that will only start ## 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 ## a Steam process that will then use the X server of either the host or another
## Steam Headless container running in 'primary' mode. ## Steam Headless container running in 'primary' mode.
MODE='primary' MODE=primary
# ____ _ # ____ _
# / ___| ___ _ ____ _(_) ___ ___ ___ # / ___| ___ _ ____ _(_) ___ ___ ___
@@ -56,41 +58,41 @@ MODE='primary'
## Options: ['vnc', 'neko', 'none'] ## Options: ['vnc', 'neko', 'none']
## Description: Configures the WebUI to use for accessing the virtual desktop. ## Description: Configures the WebUI to use for accessing the virtual desktop.
## Supported Modes: ['primary'] ## Supported Modes: ['primary']
WEB_UI_MODE='vnc' WEB_UI_MODE=vnc
## ENABLE_VNC_AUDIO: ## ENABLE_VNC_AUDIO:
## Options: ['true', 'false'] ## Options: ['true', 'false']
## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'. ## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'.
ENABLE_VNC_AUDIO='true' ENABLE_VNC_AUDIO=true
## PORT_NOVNC_WEB: ## 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' PORT_NOVNC_WEB=8083
## NEKO_NAT1TO1: ## NEKO_NAT1TO1:
## Description: Configure nat1to1 for the neko WebUI if it is enabled by setting 'WEB_UI_MODE' to 'neko'. ## 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. ## This will need to be the IP address of the host.
NEKO_NAT1TO1='' NEKO_NAT1TO1=
# Steam # Steam
## ENABLE_STEAM: ## ENABLE_STEAM:
## Options: ['true', 'false'] ## Options: ['true', 'false']
## Description: Enable Steam to run on start. This will also cause steam to restart automatically if closed. ## Description: Enable Steam to run on start. This will also cause steam to restart automatically if closed.
## Supported Modes: ['primary', 'secondary'] ## Supported Modes: ['primary', 'secondary']
ENABLE_STEAM='true' ENABLE_STEAM=true
## STEAM_ARGS: ## STEAM_ARGS:
## Description: Additional steam execution arguments. ## Description: Additional steam execution arguments.
#STEAM_ARGS='-silent -bigpicture' STEAM_ARGS=-silent
# Sunshine # Sunshine
## ENABLE_SUNSHINE: ## ENABLE_SUNSHINE:
## Options: ['true', 'false'] ## Options: ['true', 'false']
## Description: Enable Sunshine streaming service. ## Description: Enable Sunshine streaming service.
## Supported Modes: ['primary'] ## Supported Modes: ['primary']
ENABLE_SUNSHINE='false' ENABLE_SUNSHINE=false
## SUNSHINE_USER: ## SUNSHINE_USER:
## Description: Set the Sunshine service username. ## Description: Set the Sunshine service username.
#SUNSHINE_USER='admin' SUNSHINE_USER=admin
## SUNSHINE_PASS: ## SUNSHINE_PASS:
## Description: Set the Sunshine service password. ## Description: Set the Sunshine service password.
#SUNSHINE_PASS='admin' SUNSHINE_PASS=admin
# Xorg # Xorg
## ENABLE_EVDEV_INPUTS: ## ENABLE_EVDEV_INPUTS:
@@ -98,16 +100,27 @@ ENABLE_SUNSHINE='false'
## Description: Enable Keyboard and Mouse Passthrough. This will configure the Xorg server to catch all ## Description: Enable Keyboard and Mouse Passthrough. This will configure the Xorg server to catch all
## evdev events for Keyboard, Mouse, etc. ## evdev events for Keyboard, Mouse, etc.
## Supported Modes: ['primary'] ## Supported Modes: ['primary']
ENABLE_EVDEV_INPUTS='true' ENABLE_EVDEV_INPUTS=true
## FORCE_X11_DUMMY_CONFIG:
## Available Options: ['true', 'false']
## Description: Forces the installation of xorg.dummy.conf. This should be used when your output device does not have a monitor connected.
## Supported Modes: ['primary']
FORCE_X11_DUMMY_CONFIG=false
# Nvidia specific config (not required for non Nvidia GPUs) # Nvidia specific config (not required for non Nvidia GPUs)
## NVIDIA_DRIVER_CAPABILITIES: ## NVIDIA_DRIVER_CAPABILITIES:
## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display'] ## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display']
## Description: Controls which driver libraries/binaries will be mounted inside the container. ## Description: Controls which driver libraries/binaries will be mounted inside the container.
## Supported Modes: ['primary', 'secondary'] ## Supported Modes: ['primary', 'secondary']
NVIDIA_DRIVER_CAPABILITIES='all' NVIDIA_DRIVER_CAPABILITIES=all
## NVIDIA_DRIVER_CAPABILITIES: ## NVIDIA_DRIVER_CAPABILITIES:
## Available Options: ['all', 'none', '<GPU UUID>'] ## Available Options: ['all', 'none', '<GPU UUID>']
## Description: Controls which GPUs will be made accessible inside the container. ## Description: Controls which GPUs will be made accessible inside the container.
## Supported Modes: ['primary', 'secondary'] ## Supported Modes: ['primary', 'secondary']
NVIDIA_VISIBLE_DEVICES='all' NVIDIA_VISIBLE_DEVICES=all
## NVIDIA_DRIVER_VERSION:
## Description: Specify a driver version to force installation.
## Not meant to be used if nvidia container toolkit is installed.
## Detect current host driver installed with `nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3`
## Supported Modes: ['primary', 'secondary']
NVIDIA_DRIVER_VERSION=

View File

@@ -0,0 +1,76 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
## 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: With this configuration, 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
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/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.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro

View File

@@ -0,0 +1,92 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
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: With this configuration, 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
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# DEVICES:
devices:
# Use the host fuse device [REQUIRED].
- /dev/fuse
# Add the host uinput device [REQUIRED].
- /dev/uinput
# Add AMD/Intel HW accelerated video encoding/decoding devices [REQUIRED].
# NOTE: See documentation for determining which devices to configure here if you have multiple GPUs
- /dev/dri/card1
- /dev/dri/renderD128
# Ensure container access to devices 13:*
device_cgroup_rules:
- 'c 13:* rmw'
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/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.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

View File

@@ -1,64 +0,0 @@
---
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
runtime: ${DOCKER_RUNTIME}
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:
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# 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

View File

@@ -0,0 +1,79 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
## 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
# GPU PASSTHROUGH
runtime: nvidia
# NETWORK:
## NOTE: With this configuration, 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
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/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.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro

View File

@@ -0,0 +1,101 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
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
# GPU PASSTHROUGH
runtime: nvidia
# NETWORK:
## NOTE: With this configuration, 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
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# DEVICES:
devices:
# Use the host fuse device [REQUIRED].
- /dev/fuse
# Add the host uinput device [REQUIRED].
- /dev/uinput
# Add NVIDIA HW accelerated devices [OPTIONAL].
# NOTE: If you use the nvidia container toolkit, this is not needed.
# Installing the nvidia container toolkit is the recommended method for running this container
#- /dev/nvidia0
#- /dev/nvidiactl
#- /dev/nvidia-modeset
#- /dev/nvidia-uvm
#- /dev/nvidia-uvm-tools
#- /dev/nvidia-caps/nvidia-cap1
#- /dev/nvidia-caps/nvidia-cap2
# Ensure container access to devices 13:*
device_cgroup_rules:
- 'c 13:* rmw'
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/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.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

View File

@@ -1,51 +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: With this configuration, 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

View File

@@ -38,8 +38,40 @@ sudo chown -R $(id -u):$(id -g) /mnt/games
Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file. 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). Populate this file with the contents of the default Docker Compose File
### AMD/Intel:
- [AMD and Intel GPUs](./compose-files/docker-compose.amd+intel.yml).
- [Privileged AMD and Intel GPUs Docker Compose Template](./compose-files/docker-compose.amd+intel.privileged.yml) (grants full access to host devices).
#### Multipl AMD or Intel GPUs
If you have multiple AMD or Intel GPUs and you wish to isolate them, then follow these steps to determine the card to passthrough in the docker compose file. This requires that you do not use the privileged compose template.
1) List the PCI devices and get their IDs `lspci | grep -E 'VGA|3D'`
```
00:02.0 VGA compatible controller: Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics] (rev 01)
06:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Cezanne [Radeon Vega Series / Radeon Vega Mobile Series] (rev c6)
```
In this example, the Intel GPU has an ID of `00:02.0` and the AMD GPU has an ID of `06:00.0`.
2) Discover which `/dev/dri/card*` and `/dev/dri/renderD12*` references the `00:02.0` Intel GPU (or whatever your output was). To do this, run the commands `ls -la /sys/class/drm/card*` and `ls -l /sys/class/drm/renderD*`.
```
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-1
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-2 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-2
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-3 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-3
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-4 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-4
```
```
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/renderD128 -> ../../devices/pci0000:00/0000:00:02.0/drm/renderD128
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/renderD129 -> ../../devices/pci0000:00/0000:06:00.0/drm/renderD129
```
From this example output we can see that the Intel GPU is `/dev/dri/card1` and `/dev/dri/renderD128`.
### NVIDIA:
- [NVIDIA GPUs Docker Compose Template](./compose-files/docker-compose.nvidia.yml).
- [Privileged NVIDIA GPUs Docker Compose Template](./compose-files/docker-compose.nvidia.yml) (grants full access to host devices).
## CONFIGURE ENV: ## CONFIGURE ENV:
@@ -58,3 +90,6 @@ 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. After container executes successfully, navigate to your docker host URL in your browser on port 8083 and click connect.
`http://<host-ip>:8083/` `http://<host-ip>:8083/`
![img.png](./images/web_connect.png) ![img.png](./images/web_connect.png)
## Troubleshooting
[Troubleshooting Docs](./troubleshooting.md)

View File

@@ -1,22 +1,57 @@
# Ubuntu Server # Ubuntu Server Setup
Follow these instructions to install Steam Headless on Ubuntu Server. Use these instructions to install **Steam Headless** on an Ubuntu Server system.
> __Note__ > ⚠️ **Note**
> >
> This assumes that your Ubuntu Server has not be configured to run any desktop environment! > These steps assume you are running a minimal **Ubuntu Server** installation **without any desktop environment**.
> > This setup **will not work** on Ubuntu Desktop.
> This will not work with Ubuntu Desktop.
---
## INSTALL NVIDIA DRIVER:
Although you're on a server system, using the `-server` variant of the NVIDIA driver can cause compatibility issues.
Instead, install the standard driver **without recommended extras**:
```bash
apt install --no-install-recommends nvidia-driver-570
```
> 🔍 Feel free to `570` with the latest available version.
To find the latest version of the standard (non-`-server`, non-`-open`) drivers, run:
```bash
apt-cache search ^nvidia-driver- | awk '{print $1}' | grep -vE '(-server|-open)' | xargs -n1 apt-cache policy | awk '/^nvidia-driver-/{driver=$1} /Candidate:/ {print driver, $2}'
```
---
## INSTALL DOCKER: ## INSTALL DOCKER:
Install docker-ce to your Ubuntu server following the [official instrctions](https://docs.docker.com/engine/install/ubuntu/). Install `docker-ce` on your Ubuntu server by following the [official Docker instructions](https://docs.docker.com/engine/install/ubuntu/).
Ensure you install the `docker-compose-plugin` mentioned within these instructions Make sure you also install the `docker-compose-plugin` as noted in the Docker documentation.
---
## INSTALL NVIDIA CONTAINER TOOLKIT
To enable GPU support inside Docker containers, install the [NVIDIA Container Toolkit](https://github.com/NVIDIA/nvidia-container-toolkit?tab=readme-ov-file).
Follow the [APT-based installation steps](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installing-with-apt) provided in the official documentation.
Once installed, configure Docker to use the NVIDIA runtime by default:
```bash
sudo nvidia-ctk runtime configure --runtime=docker
```
> 💡 You *can* also run the container without the NVIDIA runtime by manually uncommenting the `/dev/nvidia*` device entries in the Compose file — but this approach is **not recommended**.
---
## CONFIGURE DOCKER COMPOSE: ## CONFIGURE DOCKER COMPOSE:
Once you have installed docker, follow the [Compose Files](./docker-compose.md) section and select the right configuration file for your hardware. After installing Docker, proceed to the [Compose Files](./docker-compose.md) section and select the appropriate configuration for your hardware setup.

View File

@@ -22,6 +22,31 @@ if [[ -f /version.txt ]]; then
cat /version.txt cat /version.txt
fi fi
function print_header {
# Magenta
echo -e "\e[35m**** ${@} ****\e[0m"
}
function print_step_header {
# Cyan
echo -e "\e[36m - ${@}\e[0m"
}
function print_warning {
# Yellow
echo -e "\e[33mWARNING: ${@}\e[0m"
}
function print_error {
# Red
echo -e "\e[31mERROR: ${@}\e[0m"
}
function print_note {
# Cyan
echo -e "\e[36mNOTE: ${@}\e[0m"
}
# Execute all container init scripts # Execute all container init scripts
for init_script in /etc/cont-init.d/*.sh ; do for init_script in /etc/cont-init.d/*.sh ; do
echo echo
@@ -59,9 +84,9 @@ touch /tmp/.first-run-user-init-scripts
# Start supervisord # Start supervisord
echo echo
echo "**** Starting supervisord ****"; print_header "Starting supervisord";
echo "Logging all root services to '/var/log/supervisor/'" print_step_header "Logging all root services to '/var/log/supervisor/'"
echo "Logging all user services to '/home/${USER:?}/.cache/log/'" print_step_header "Logging all user services to '/home/${USER:?}/.cache/log/'"
echo echo
mkdir -p /var/log/supervisor mkdir -p /var/log/supervisor
chmod a+rw /var/log/supervisor chmod a+rw /var/log/supervisor

View File

@@ -14,18 +14,18 @@ PGID=${PGID:-100}
UMASK=${UMASK:-000} UMASK=${UMASK:-000}
USER_PASSWORD=${USER_PASSWORD:-password} USER_PASSWORD=${USER_PASSWORD:-password}
echo "**** Configure default user ****" print_header "Configure default user"
echo "Setting default user uid=${PUID}(${USER}) gid=${PGID}(${USER})" print_step_header "Setting default user uid=${PUID}(${USER}) gid=${PGID}(${USER})"
usermod -o -u "${PUID}" ${USER} usermod -o -u "${PUID}" ${USER}
groupmod -o -g "${PGID}" ${USER} groupmod -o -g "${PGID}" ${USER}
echo "Adding default user to any additional required device groups" print_step_header "Adding default user to any additional required device groups"
additional_groups=( video audio input pulse ) additional_groups=( video audio input pulse )
for group_name in "${additional_groups[@]}"; do for group_name in "${additional_groups[@]}"; do
if [ $(getent group ${group_name:?}) ]; then if [ $(getent group ${group_name:?}) ]; then
echo "Adding user '${USER}' to group: '${group_name}'" print_step_header "Adding user '${USER}' to group: '${group_name}'"
usermod -aG ${group_name:?} ${USER} usermod -aG ${group_name:?} ${USER}
fi fi
done done
@@ -54,20 +54,20 @@ for dev in "${device_nodes[@]}"; do
# Add group to user # Add group to user
if [[ "${added_groups}" != *"${dev_group}"* ]]; then if [[ "${added_groups}" != *"${dev_group}"* ]]; then
echo "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}" print_step_header "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
usermod -aG ${dev_group} ${USER} usermod -aG ${dev_group} ${USER}
added_groups=" ${added_groups} ${dev_group} " added_groups=" ${added_groups} ${dev_group} "
fi fi
done done
echo "Setting umask to ${UMASK}"; print_step_header "Setting umask to ${UMASK}";
umask ${UMASK} umask ${UMASK}
# TODO: Move this to its own 'display' init script. It does not really belong here # TODO: Move this to its own 'display' init script. It does not really belong here
# Configure the 'XDG_RUNTIME_DIR' path # Configure the 'XDG_RUNTIME_DIR' path
echo "Create the user XDG_RUNTIME_DIR path '${XDG_RUNTIME_DIR}'" print_step_header "Create the user XDG_RUNTIME_DIR path '${XDG_RUNTIME_DIR}'"
mkdir -p ${XDG_RUNTIME_DIR} mkdir -p ${XDG_RUNTIME_DIR}
# Ensure it is owned by the 'default' user # Ensure it is owned by the 'default' user
chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR} chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR}
@@ -80,19 +80,19 @@ chmod a+r /etc/alternatives/desktop-background
# Setup services log path # Setup services log path
echo "Setting ownership of all log files in '${USER_HOME}/.cache/log'" print_step_header "Setting ownership of all log files in '${USER_HOME}/.cache/log'"
mkdir -p "${USER_HOME}/.cache/log" mkdir -p "${USER_HOME}/.cache/log"
chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log" chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log"
# Set the root and user password # Set the root and user password
echo "Setting root password" print_step_header "Setting root password"
echo "root:${USER_PASSWORD}" | chpasswd echo "root:${USER_PASSWORD}" | chpasswd
echo "Setting user password" print_step_header "Setting user password"
echo "${USER}:${USER_PASSWORD}" | chpasswd echo "${USER}:${USER_PASSWORD}" | chpasswd
# Set root XDG_RUNTIME_DIR path # Set root XDG_RUNTIME_DIR path
mkdir -p /tmp/runtime-root mkdir -p /tmp/runtime-root
chown root:root /tmp/runtime-root chown root:root /tmp/runtime-root
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,26 +1,17 @@
#!/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 ****" # Configure kernel parameters
print_header "Configure some system kernel parameters"
if [ "$(cat /proc/sys/vm/max_map_count)" -ge 524288 ]; then if [ "$(cat /proc/sys/vm/max_map_count)" -ge 524288 ]; then
if [ -w "/proc/sys/vm/max_map_count" ]; 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" print_step_header "Setting the maximum number of memory map areas a process can create to 524288"
echo 524288 > /proc/sys/vm/max_map_count echo 524288 > /proc/sys/vm/max_map_count
else else
echo "WARNING: Unable to set max_map_count on unprivileged container" print_warning "Unable to set vm.max_map_count on unprivileged container"
fi fi
else else
echo "NOTE: vm.max_map_count is already greater than '524288'" print_step_header "The vm.max_map_count is already greater than '524288'"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,14 +1,14 @@
# Configure dbus # Configure dbus
echo "**** Configure container dbus ****"; print_header "Configure container dbus"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [[ "${HOST_DBUS}" == "true" ]]; then if [[ "${HOST_DBUS}" == "true" ]]; then
echo "Container configured to use the host dbus"; print_step_header "Container configured to use the host dbus";
# Disable supervisord script # Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
else else
echo "Container configured to run its own dbus"; print_step_header "Container configured to run its own dbus";
# Enable supervisord script # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
# Configure dbus to run as USER # Configure dbus to run as USER
@@ -25,8 +25,8 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
find /var/run/dbus -name "pid" -exec rm -f {} \; find /var/run/dbus -name "pid" -exec rm -f {} \;
fi fi
else else
echo "Dbus service not available when container is run in 'secondary' mode." print_step_header "Dbus service not available when container is run in 'secondary' mode."
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,33 +1,26 @@
#!/usr/bin/env bash
### # Configure dbus
# File: 30-configure_udev.sh print_header "Configure udevd"
# Project: cont-init.d
# File Created: Friday, 12th January 2022 8:54:01 am
# Author: Josh.5 (jsunnex@gmail.com)
# -----
# Last Modified: Tuesday, 4th October 2022 11:20:48 am
# Modified By: Josh.5 (jsunnex@gmail.com)
###
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger" # Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
run_dumb_udev="false" run_dumb_udev="false"
if [ ! -w /sys ]; then if [ ! -w /sys ]; then
# Disable supervisord script since we are not able to write to sysfs # Disable supervisord script since we are not able to write to sysfs
echo "**** Disable udevd - /sys is mounted RO ****"; print_step_header "Disable udevd - /sys is mounted RO"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="true" run_dumb_udev="true"
elif [ ! -d /run/udev ]; then elif [ ! -d /run/udev ]; then
# Disable supervisord script since we are not able to write to udev/data path # Disable supervisord script since we are not able to write to udev/data path
echo "**** Disable udevd - /run/udev does not exist ****"; print_step_header "Disable udevd - /run/udev does not exist"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="true" run_dumb_udev="true"
elif [ ! -w /run/udev ]; then elif [ ! -w /run/udev ]; then
# Disable supervisord script since we are not able to write to udev/data path # Disable supervisord script since we are not able to write to udev/data path
echo "**** Disable udevd - /run/udev is mounted RO ****"; print_step_header "Disable udevd - /run/udev is mounted RO"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="false" run_dumb_udev="false"
elif udevadm trigger &> /dev/null; then elif udevadm trigger &> /dev/null; then
echo "**** Configure container to run udev management ****"; print_step_header "Configure container to run udev management"
# Enable supervisord script # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Configure udev permissions # Configure udev permissions
@@ -37,22 +30,22 @@ elif udevadm trigger &> /dev/null; then
run_dumb_udev="false" run_dumb_udev="false"
else else
# Disable supervisord script since we are not able to execute "udevadm trigger" # Disable supervisord script since we are not able to execute "udevadm trigger"
echo "**** Disable udev service due to privilege restrictions ****"; print_step_header "Disable udev service due to privilege restrictions"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="true" run_dumb_udev="true"
fi fi
if [ "${run_dumb_udev}" = "true" ]; then if [ "${run_dumb_udev}" = "true" ]; then
# Enable dumb-udev instead of udevd # Enable dumb-udev instead of udevd
echo "**** Enable dumb-udev service ****"; print_step_header "Enable dumb-udev service"
sed -i 's|^command.*=.*$|command=start-dumb-udev.sh|' /etc/supervisor.d/udev.ini sed -i 's|^command.*=.*$|command=start-dumb-udev.sh|' /etc/supervisor.d/udev.ini
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
fi fi
if [[ -e /dev/uinput ]]; then if [[ -e /dev/uinput ]]; then
echo "**** Ensure the default user has permission to r/w on input devices ****"; print_step_header "Ensure the default user has permission to r/w on input devices"
chmod 0666 /dev/uinput chmod 0666 /dev/uinput
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,9 +1,12 @@
# Configure dbus
print_header "Configure local"
current_local=$(head -n 1 /etc/locale.gen) current_local=$(head -n 1 /etc/locale.gen)
user_local=$(echo ${USER_LOCALES} | cut -d ' ' -f 1) user_local=$(echo ${USER_LOCALES} | cut -d ' ' -f 1)
if [ "${current_local}" != "${USER_LOCALES}" ]; then if [ "${current_local}" != "${USER_LOCALES}" ]; then
echo "**** Configuring Locales to ${USER_LOCALES} ****"; print_step_header "Configuring Locales to ${USER_LOCALES}"
rm /etc/locale.gen rm /etc/locale.gen
echo -e "${USER_LOCALES}\nen_US.UTF-8 UTF-8" > "/etc/locale.gen" echo -e "${USER_LOCALES}\nen_US.UTF-8 UTF-8" > "/etc/locale.gen"
export LANGUAGE="${user_local}" export LANGUAGE="${user_local}"
@@ -13,7 +16,7 @@ if [ "${current_local}" != "${USER_LOCALES}" ]; then
locale-gen locale-gen
update-locale LC_ALL="${user_local}" update-locale LC_ALL="${user_local}"
else else
echo "**** Locales already set correctly to ${USER_LOCALES} ****"; print_step_header "Locales already set correctly to ${USER_LOCALES}"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,18 +1,19 @@
echo "**** Configure pulseaudio ****" # Configure dbus
print_header "Configure pulseaudio"
# Always enable the pulseaudio service # Always enable the pulseaudio service
echo "Enable pulseaudio service." print_step_header "Enable pulseaudio service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/pulseaudio.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/pulseaudio.ini
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
echo "Configure pulseaudio as simple dummy audio" print_step_header "Configure pulseaudio as simple dummy audio"
sed -i 's|^; autospawn.*$|autospawn = no|' /etc/pulse/client.conf sed -i 's|^; autospawn.*$|autospawn = no|' /etc/pulse/client.conf
sed -i 's|^; daemon-binary.*$|daemon-binary = /bin/true|' /etc/pulse/client.conf sed -i 's|^; daemon-binary.*$|daemon-binary = /bin/true|' /etc/pulse/client.conf
sed -i 's|^; flat-volumes.*$|flat-volumes = yes|' /etc/pulse/daemon.conf sed -i 's|^; flat-volumes.*$|flat-volumes = yes|' /etc/pulse/daemon.conf
else else
echo "Configure pulseaudio to pipe audio to a socket" print_step_header "Configure pulseaudio to pipe audio to a socket"
# Ensure pulseaudio directories have the correct permissions # Ensure pulseaudio directories have the correct permissions
mkdir -p \ mkdir -p \
@@ -37,4 +38,4 @@ else
fi fi
chown -R ${USER} /etc/pulse chown -R ${USER} /etc/pulse
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,20 +1,22 @@
# Fech NVIDIA GPU device (if one exists) # 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) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
elif [ "${NVIDIA_VISIBLE_DEVICES:-}X" = "X" ]; then elif [ "${NVIDIA_VISIBLE_DEVICES:-}X" = "X" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
else else
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p) 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 [ "${gpu_select:-}X" = "X" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2> /dev/null | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
fi fi
fi fi
# NVIDIA Params # 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)" if [ "X${gpu_select:-}" != "X" ]; then
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_host_driver_version="$(nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)" 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)"
fi
# Intel params # Intel params
# This figures out if it's an intel CPU with integrated GPU # This figures out if it's an intel CPU with integrated GPU
@@ -27,38 +29,56 @@ 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)" export amd_gpu_model="$(lspci | grep -i vga | grep -i amd)"
function download_driver { function download_driver {
local driver_url
local stripped_version
mkdir -p "${USER_HOME:?}/Downloads" mkdir -p "${USER_HOME:?}/Downloads"
chown -R ${USER:?} "${USER_HOME:?}/Downloads" chown -R ${USER:?} "${USER_HOME:?}/Downloads"
if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then
echo "Downloading driver v${nvidia_host_driver_version:?}" print_step_header "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"
[[ $? -gt 0 ]] && echo "Error downloading driver. Exit!" && return 1
mv /tmp/NVIDIA.run "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" # Try downloading from a list of NVIDIA driver hosting servers
stripped_version="${nvidia_host_driver_version#v}" # Strip 'v' if present
declare -a sources=(
"https://download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version}.run"
"https://us.download.nvidia.com/XFree86/Linux-x86_64/${nvidia_host_driver_version}/NVIDIA-Linux-x86_64-${nvidia_host_driver_version}.run"
"https://github.com/flathub/org.freedesktop.Platform.GL.nvidia/releases/download/cuda/NVIDIA-Linux-x86_64-${stripped_version}.run"
)
for driver_url in "${sources[@]}"; do
if wget -q --show-progress --progress=bar:force:noscroll \
-O /tmp/NVIDIA.run \
"${driver_url:?}"; then
mv /tmp/NVIDIA.run "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
return 0
mv /tmp/NVIDIA.run "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
return 0
else
print_warning "Download failed from: ${driver_url}"
fi
done
print_note "Visit https://download.nvidia.com/XFree86/Linux-x86_64/ in a browser and find the closest match to version '${nvidia_host_driver_version:?}', then set that version in the NVIDIA_DRIVER_VERSION environment variable."
print_error "Unable to download driver from any source. Exit!"
sleep 10
return 1
fi fi
} }
function install_nvidia_driver { function install_nvidia_driver {
# Check here if the currently installed version matches using nvidia-settings # 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) 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 if [ "${nvidia_settings_version:-}X" != "${nvidia_host_driver_version:-}X" ]; then
# Download the driver (if it does not yet exist locally) # Download the driver (if it does not yet exist locally)
download_driver download_driver
# if command -v pacman &> /dev/null; then if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) >= 550)); then
# echo "Install NVIDIA vulkan utils" \ sed -i 's/--no-multigpu//g' /etc/cont-init.d/70-configure_xorg.sh
# && pacman -Syu --noconfirm --needed \ fi
# 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 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" print_step_header "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" chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \ "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
--silent \ --silent \
@@ -77,9 +97,9 @@ function install_nvidia_driver {
--no-check-for-alternate-installs \ --no-check-for-alternate-installs \
--no-libglx-indirect \ --no-libglx-indirect \
--no-install-libglvnd \ --no-install-libglvnd \
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1 >"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
else else
echo "Installing Legacy NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host" print_step_header "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" chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \ "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
--silent \ --silent \
@@ -98,8 +118,10 @@ function install_nvidia_driver {
--no-check-for-alternate-installs \ --no-check-for-alternate-installs \
--no-libglx-indirect \ --no-libglx-indirect \
--no-install-libglvnd \ --no-install-libglvnd \
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1 >"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
fi fi
else
print_step_header "NVIDIA driver version ${nvidia_settings_version:-} is already installed"
fi fi
} }
@@ -110,13 +132,13 @@ function patch_nvidia_driver {
( (
set +e set +e
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" ]; then if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
echo "Fetch NVIDIA NVENC patch" print_step_header "Fetch NVIDIA NVENC patch"
wget -q --show-progress --progress=bar:force:noscroll \ wget -q --show-progress --progress=bar:force:noscroll \
-O "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \ -O "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch.sh" "https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch.sh"
fi fi
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" ]; then if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
echo "Fetch NVIDIA NvFBC patch" print_step_header "Fetch NVIDIA NvFBC patch"
wget -q --show-progress --progress=bar:force:noscroll \ wget -q --show-progress --progress=bar:force:noscroll \
-O "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" \ -O "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" \
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch-fbc.sh" "https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch-fbc.sh"
@@ -125,89 +147,113 @@ function patch_nvidia_driver {
"${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \ "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
"${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
echo "Install NVIDIA driver patches" print_step_header "Install NVIDIA driver patches"
echo "/patched-lib" > /etc/ld.so.conf.d/000-patched-lib.conf echo "/patched-lib" >/etc/ld.so.conf.d/000-patched-lib.conf
mkdir -p "/patched-lib" 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.${NVIDIA_PATCH_VERSION:?}.sh"
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${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; } pushd "/patched-lib" &>/dev/null || {
for f in * ; do print_error "Failed to push directory to /patched-lib"
exit 1
}
for f in *; do
suffix="${f##*.so}" suffix="${f##*.so}"
name="$(basename "$f" "$suffix")" name="$(basename "$f" "$suffix")"
[ -h "$name" ] || ln -sf "$f" "$name" [ -h "$name" ] || ln -sf "$f" "$name"
[ -h "$name" ] || ln -sf "$f" "$name.1" [ -h "$name" ] || ln -sf "$f" "$name.1"
done done
ldconfig ldconfig
popd &> /dev/null || { echo "Error: Failed to pop directory out of /patched-lib"; exit 1; } popd &>/dev/null || {
print_error "Failed to pop directory out of /patched-lib"
exit 1
}
) )
else else
echo "Leaving NVIDIA driver stock without patching" print_step_header "Leaving NVIDIA driver stock without patching"
fi
}
function install_deb_mesa {
if [ ! -f /tmp/init-mesa-libs-install.log ]; then
print_step_header "Enable i386 arch"
dpkg --add-architecture i386
if [ "${ENABLE_SID:-}" = "true" ]; then
print_step_header "Add Debian SID sources"
echo "deb http://deb.debian.org/debian/ sid main" >/etc/apt/sources.list
fi
apt-get update &>>/tmp/init-mesa-libs-install.log
print_step_header "Install mesa vulkan drivers"
echo "" >>/tmp/init-mesa-libs-install.log
apt-get install -y --no-install-recommends \
libvulkan1 \
libvulkan1:i386 \
mesa-vulkan-drivers \
mesa-vulkan-drivers:i386 \
mesa-utils \
mesa-utils-extra \
vulkan-tools \
&>>/tmp/init-mesa-libs-install.log
else
print_step_header "Mesa has already been installed into this container"
fi fi
} }
function install_amd_gpu_driver { function install_amd_gpu_driver {
echo "Install AMD vulkan driver" if command -v pacman &>/dev/null; then
if command -v pacman &> /dev/null; then print_step_header "Install AMD Mesa driver"
pacman -Syu --noconfirm --needed \ pacman -Syu --noconfirm --needed \
lib32-vulkan-icd-loader \ lib32-vulkan-icd-loader \
lib32-vulkan-radeon \ lib32-vulkan-radeon \
vulkan-icd-loader \ vulkan-icd-loader \
vulkan-radeon vulkan-radeon
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required elif command -v apt-get &>/dev/null; then
# elif command -v apt-get &> /dev/null; then install_deb_mesa
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
# apt-get install -y \
# libvulkan1 \
# libvulkan1:i386 \
# mesa-vulkan-drivers \
# mesa-vulkan-drivers:i386
fi fi
} }
function install_intel_gpu_driver { function install_intel_gpu_driver {
echo "Install Intel vulkan driver" if command -v pacman &>/dev/null; then
if command -v pacman &> /dev/null; then print_step_header "Install Intel Mesa driver"
pacman -Syu --noconfirm --needed \ pacman -Syu --noconfirm --needed \
lib32-vulkan-icd-loader \ lib32-vulkan-icd-loader \
lib32-vulkan-intel \ lib32-vulkan-intel \
vulkan-icd-loader \ vulkan-icd-loader \
vulkan-intel vulkan-intel
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required elif command -v apt-get &>/dev/null; then
# elif command -v apt-get &> /dev/null; then install_deb_mesa
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
# apt-get install -y \
# libvulkan1 \
# libvulkan1:i386 \
# mesa-vulkan-drivers \
# mesa-vulkan-drivers:i386
fi fi
} }
# Intel Arc GPU or Intel CPU with possible iGPU # Intel Arc GPU or Intel CPU with possible iGPU
if [ "${intel_gpu_model:-}X" != "X" ]; then if [ "${intel_gpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_gpu_model:?}' ****" print_header "Found Intel device '${intel_gpu_model:?}'"
install_intel_gpu_driver install_intel_gpu_driver
elif [ "${intel_cpu_model:-}X" != "X" ]; then elif [ "${intel_cpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_cpu_model:?}' ****" print_header "Found Intel device '${intel_cpu_model:?}'"
install_intel_gpu_driver install_intel_gpu_driver
else else
echo "**** No Intel device found ****" print_header "No Intel device found"
fi fi
# AMD GPU # AMD GPU
if [ "${amd_gpu_model:-}X" != "X" ]; then if [ "${amd_gpu_model:-}X" != "X" ]; then
echo "**** Found AMD device '${amd_gpu_model:?}' ****" print_header "Found AMD device '${amd_gpu_model:?}'"
install_amd_gpu_driver install_amd_gpu_driver
else else
echo "**** No AMD device found ****" print_header "No AMD device found"
fi fi
# NVIDIA GPU # NVIDIA GPU
if [ "${nvidia_pci_address:-}X" != "X" ]; then if [ "${NVIDIA_DRIVER_VERSION:-}X" != "X" ]; then
echo "**** Found NVIDIA device '${nvidia_gpu_name:?}' ****" export nvidia_host_driver_version="${NVIDIA_DRIVER_VERSION:?}"
print_header "Forcing install of NVIDIA driver version '${nvidia_host_driver_version:?}' because the 'NVIDIA_DRIVER_VERSION' variable is set."
install_nvidia_driver
patch_nvidia_driver
elif [ "${nvidia_pci_address:-}X" != "X" ]; then
print_header "Found NVIDIA device '${nvidia_gpu_name:?}'"
install_nvidia_driver install_nvidia_driver
patch_nvidia_driver patch_nvidia_driver
else else
echo "**** No NVIDIA device found ****" print_header "No NVIDIA device found"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

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

View File

@@ -30,36 +30,42 @@ fi
# Configure a NVIDIA X11 config # Configure a NVIDIA X11 config
function configure_nvidia_x_server { function configure_nvidia_x_server {
echo "Configuring X11 with GPU ID: '${gpu_select}'" print_step_header "Configuring X11 with GPU ID: '${gpu_select}'"
nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p) nvidia_gpu_hex_id=$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p)
IFS=":." ARR_ID=(${nvidia_gpu_hex_id}) IFS=":." ARR_ID=(${nvidia_gpu_hex_id})
unset IFS unset IFS
bus_id=PCI:$((16#${ARR_ID[1]})):$((16#${ARR_ID[2]})):$((16#${ARR_ID[3]})) bus_id=PCI:$((16#${ARR_ID[1]})):$((16#${ARR_ID[2]})):$((16#${ARR_ID[3]}))
echo "Configuring X11 with PCI bus ID: '${bus_id}'" print_step_header "Configuring X11 with PCI bus ID: '${bus_id}'"
export MODELINE=$(cvt -r "${DISPLAY_SIZEW}" "${DISPLAY_SIZEH}" "${DISPLAY_REFRESH}" | sed -n 2p) export MODELINE=$(cvt -r "${DISPLAY_SIZEW}" "${DISPLAY_SIZEH}" "${DISPLAY_REFRESH}" | sed -n 2p)
echo "Writing X11 config with ${MODELINE}" print_step_header "Writing X11 config with ${MODELINE}"
connected_monitor="--use-display-device=None" connected_monitor="--use-display-device=None"
if [[ "X${DISPLAY_VIDEO_PORT:-}" != "X" ]]; then if [[ "X${DISPLAY_VIDEO_PORT:-}" != "X" ]]; then
connected_monitor="--connected-monitor=${DISPLAY_VIDEO_PORT:?}" connected_monitor="--connected-monitor=${DISPLAY_VIDEO_PORT:?}"
fi fi
nvidia-xconfig --virtual="${DISPLAY_SIZEW:?}x${DISPLAY_SIZEH:?}" --depth="${DISPLAY_CDEPTH:?}" --mode=$(echo "${MODELINE:?}" | awk '{print $2}' | tr -d '"') --allow-empty-initial-configuration --no-probe-all-gpus --busid="${bus_id:?}" --no-multigpu --no-sli --no-base-mosaic --only-one-x-screen ${connected_monitor:?} nvidia-xconfig --virtual="${DISPLAY_SIZEW:?}x${DISPLAY_SIZEH:?}" --depth="${DISPLAY_CDEPTH:?}" --mode=$(echo "${MODELINE:?}" | awk '{print $2}' | tr -d '"') --allow-empty-initial-configuration --no-probe-all-gpus --busid="${bus_id:?}" --no-multigpu --no-sli --no-base-mosaic --only-one-x-screen ${connected_monitor:?}
sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPClkCheck, NoEdidMaxPClkCheck, NoMaxSizeCheck, NoHorizSyncCheck, NoVertRefreshCheck, NoVirtualSizeCheck, NoTotalSizeCheck, NoDualLinkDVICheck, NoDisplayPortBandwidthCheck, AllowNon3DVisionModes, AllowNonHDMI3DModes, AllowNonEdidModes, NoEdidHDMI2Check, AllowDpInterlaced"\n Option "HardDPMS" "False"' /etc/X11/xorg.conf # Allow SteamHeadless to run with an eGPU
sed -i '/Driver\s\+"nvidia"/a\ Option "AllowExternalGpus" "True"' /etc/X11/xorg.conf
# Configure primary GPU
sed -i '/Driver\s\+"nvidia"/a\ Option "PrimaryGPU" "yes"' /etc/X11/xorg.conf
# Force X server to start even if no display devices are connected
sed -i '/Driver\s\+"nvidia"/a\ Option "AllowEmptyInitialConfiguration"' /etc/X11/xorg.conf
# Disable some mode validation checks
sed -i '/Driver\s\+"nvidia"/a\ Option "ModeValidation" "NoMaxPClkCheck, NoEdidMaxPClkCheck, NoMaxSizeCheck, NoHorizSyncCheck, NoVertRefreshCheck, NoVirtualSizeCheck, NoTotalSizeCheck, NoDualLinkDVICheck, NoDisplayPortBandwidthCheck, AllowNon3DVisionModes, AllowNonHDMI3DModes, AllowNonEdidModes, NoEdidHDMI2Check, AllowDpInterlaced"' /etc/X11/xorg.conf
# Configure the default modeline
sed -i '/Section\s\+"Monitor"/a\ '"${MODELINE}" /etc/X11/xorg.conf sed -i '/Section\s\+"Monitor"/a\ '"${MODELINE}" /etc/X11/xorg.conf
# Prevent interference between GPUs # Prevent interference between GPUs
echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | tee -a /etc/X11/xorg.conf > /dev/null echo -e "Section \"ServerFlags\"\n Option \"AutoAddGPU\" \"false\"\nEndSection" | tee -a /etc/X11/xorg.conf > /dev/null
# Configure primary GPU
sed -i '/Driver\s\+"nvidia"/a\ Option "AllowEmptyInitialConfiguration"\n Option "PrimaryGPU" "yes"' /usr/share/X11/xorg.conf.d/nvidia-drm-outputclass.conf
} }
# Allow anybody for running x server # Allow anybody for running x server
function configure_x_server { function configure_x_server {
# Configure x to be run by anyone # Configure x to be run by anyone
if [[ ! -f /etc/X11/Xwrapper.config ]]; then if [[ ! -f /etc/X11/Xwrapper.config ]]; then
echo "Create Xwrapper.config" print_step_header "Create Xwrapper.config"
echo 'allowed_users=anybody' > /etc/X11/Xwrapper.config echo 'allowed_users=anybody' > /etc/X11/Xwrapper.config
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
elif grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then elif grep -Fxq "allowed_users=console" /etc/X11/Xwrapper.config; then
echo "Configure Xwrapper.config" print_step_header "Configure Xwrapper.config"
sed -i "s/allowed_users=console/allowed_users=anybody/" /etc/X11/Xwrapper.config sed -i "s/allowed_users=console/allowed_users=anybody/" /etc/X11/Xwrapper.config
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
fi fi
@@ -73,7 +79,7 @@ function configure_x_server {
# Clear out old lock files # Clear out old lock files
display_file=${XORG_SOCKET_DIR}/X${DISPLAY#:} display_file=${XORG_SOCKET_DIR}/X${DISPLAY#:}
if [ -S ${display_file} ]; then if [ -S ${display_file} ]; then
echo "Removing ${display_file} before starting" print_step_header "Removing ${display_file} before starting"
rm -f /tmp/.X${DISPLAY#:}-lock rm -f /tmp/.X${DISPLAY#:}-lock
rm ${display_file} rm ${display_file}
fi fi
@@ -84,46 +90,46 @@ function configure_x_server {
chmod 1777 /tmp/.ICE-unix/ chmod 1777 /tmp/.ICE-unix/
# Check if this container is being run as a secondary instance # Check if this container is being run as a secondary instance
if [ "${MODE}" == "p" ] | [ "${MODE}" == "primary" ]; then if ([ "${MODE}" = "p" ] || [ "${MODE}" = "primary" ]); then
echo "Configure container as primary the X server" print_step_header "Configure container as primary the X server"
# Enable supervisord script # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xorg.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xorg.ini
elif [ "${MODE}" == "fb" ] | [ "${MODE}" == "framebuffer" ]; then elif [ "${MODE}" == "fb" ] | [ "${MODE}" == "framebuffer" ]; then
echo "Configure container to use a virtual framebuffer as the X server" print_step_header "Configure container to use a virtual framebuffer as the X server"
# Disable xorg supervisord script # Disable xorg supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
# Enable xvfb supervisord script # Enable xvfb supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xvfb.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xvfb.ini
else else
echo "Configure container with no X server" print_step_header "Configure container with no X server"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
fi fi
# Enable KB/Mouse input capture with Xorg if configured # Enable KB/Mouse input capture with Xorg if configured
if [ ${ENABLE_EVDEV_INPUTS:-} = "true" ]; then if [ ${ENABLE_EVDEV_INPUTS:-} = "true" ]; then
echo "Enabling evdev input class on pointers, keyboards, touchpads, touch screens, etc." print_step_header "Enabling evdev input class on pointers, keyboards, touchpads, touch screens, etc."
cp -fv /usr/share/X11/xorg.conf.d/10-evdev.conf /etc/X11/xorg.conf.d/10-evdev.conf cp -f /usr/share/X11/xorg.conf.d/10-evdev.conf /etc/X11/xorg.conf.d/10-evdev.conf
else else
echo "Leaving evdev inputs disabled" print_step_header "Leaving evdev inputs disabled"
fi fi
# Configure dummy config if no monitor is connected (not applicable to NVIDIA) # Configure dummy config if no monitor is connected (not applicable to NVIDIA)
if [[ "X${monitor_connected}" == "X" ]]; then if ([ "X${monitor_connected}" = "X" ] || [ "${FORCE_X11_DUMMY_CONFIG}" = "true" ]); then
echo "No monitors connected. Installing dummy xorg.conf" print_step_header "No monitors connected. Installing dummy xorg.conf"
# Use a dummy display input # Use a dummy display input
cp -fv /templates/xorg/xorg.dummy.conf /etc/X11/xorg.conf cp -f /templates/xorg/xorg.dummy.conf /etc/X11/xorg.conf
fi fi
} }
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [[ -z ${nvidia_gpu_hex_id} ]]; then if [[ -z ${nvidia_gpu_hex_id} ]]; then
echo "**** Generate default xorg.conf ****"; print_header "Generate default xorg.conf"
configure_x_server configure_x_server
else else
echo "**** Generate NVIDIA xorg.conf ****"; print_header "Generate NVIDIA xorg.conf"
configure_x_server configure_x_server
configure_nvidia_x_server configure_nvidia_x_server
fi fi
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

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

View File

@@ -1,10 +1,10 @@
echo "**** Configure Neko ****" print_header "Configure Neko"
# REF: https://neko.m1k1o.net/#/getting-started/configuration # REF: https://neko.m1k1o.net/#/getting-started/configuration
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ ${WEB_UI_MODE} = "neko" ]; then if [ ${WEB_UI_MODE} = "neko" ]; then
echo "Enable Neko server" print_step_header "Enable Neko server"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/neko.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/neko.ini
# Make directories for neko # Make directories for neko
@@ -15,9 +15,9 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
# Configure nat1to1 if it is not already set # Configure nat1to1 if it is not already set
if [[ -z ${NEKO_NAT1TO1} ]]; then if [[ -z ${NEKO_NAT1TO1} ]]; then
export NEKO_NAT1TO1=$(ip route get 1 | awk '{print $(NF-2);exit}') export NEKO_NAT1TO1=$(ip route get 1 | awk '{print $(NF-2);exit}')
echo "Setting NEKO_NAT1TO1=${NEKO_NAT1TO1}" print_step_header "Setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
else else
echo "User provided setting NEKO_NAT1TO1=${NEKO_NAT1TO1}" print_step_header "User provided setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
fi fi
# Configure hardware acceleration if it is not already set # Configure hardware acceleration if it is not already set
@@ -39,10 +39,10 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
export NEKO_SCREEN="${DISPLAY_SIZEW}x${DISPLAY_SIZEH}@${DISPLAY_REFRESH}" export NEKO_SCREEN="${DISPLAY_SIZEW}x${DISPLAY_SIZEH}@${DISPLAY_REFRESH}"
fi fi
else else
echo "Disable Neko server" print_step_header "Disable Neko server"
fi fi
else else
echo "Neko server not available when container is run in 'secondary' mode" print_step_header "Neko server not available when container is run in 'secondary' mode"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,7 +1,8 @@
echo "**** Configure Steam ****" print_header "Configure Steam"
steam_autostart_desktop="$(cat <<EOF steam_autostart_desktop="$(
cat <<EOF
[Desktop Entry] [Desktop Entry]
Encoding=UTF-8 Encoding=UTF-8
Type=Application Type=Application
@@ -17,19 +18,117 @@ Hidden=false
EOF EOF
)" )"
default_steam_config="$(
cat <<EOF
"InstallConfigStore"
{
"Software"
{
"Valve"
{
"Steam"
{
"CompatToolMapping"
{
"0"
{
"name" "proton_hotfix"
"config" ""
"priority" "75"
}
}
}
}
}
}
EOF
)"
default_steam_library_config="$(
cat <<EOF
"libraryfolders"
{
"0"
{
"path" "/home/default/.steam/steam"
"label" "Home"
"totalsize" "0"
"update_clean_bytes_tally" "0"
"time_last_update_verified" "0"
"apps"
{
}
}
"1"
{
"path" "/mnt/games/GameLibrary/Steam"
"label" "Games"
"contentid" "4532270033051814356"
"totalsize" "0"
"update_clean_bytes_tally" "0"
"time_last_update_verified" "0"
"apps"
{
}
}
}
EOF
)"
games_steam_library_config="$(
cat <<EOF
"libraryfolder"
{
"contentid" "4532270033051814356"
"label" "Games"
}
EOF
)"
if [ "${ENABLE_STEAM:-}" = "true" ]; then if [ "${ENABLE_STEAM:-}" = "true" ]; then
if [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then if [ "${MODE}" == "s" ] || [ "${MODE}" == "secondary" ]; then
echo "Enable Steam supervisor.d service" print_step_header "Enable Steam supervisor.d service"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini
else else
echo "Enable Steam auto-start script" print_step_header "Enable Steam auto-start script"
mkdir -p "${USER_HOME:?}/.config/autostart" mkdir -p "${USER_HOME:?}/.config/autostart"
echo "${steam_autostart_desktop:?}" > "${USER_HOME:?}/.config/autostart/Steam.desktop" echo "${steam_autostart_desktop:?}" >"${USER_HOME:?}/.config/autostart/Steam.desktop"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
fi fi
# Ensuring Steam Play is enabled for all titles
CONFIG_VDF="${USER_HOME:?}/.steam/steam/config/config.vdf"
if [ ! -f "${CONFIG_VDF}" ]; then
print_step_header "Initializing Steam config"
mkdir -p "$(dirname "${CONFIG_VDF}")"
echo "${default_steam_config}" >"${CONFIG_VDF}"
chown -R "${USER:?}:${USER:?}" "${USER_HOME:?}/.steam"
else
print_step_header "Steam config already exists, skipping initialization"
fi
# Ensure Steam library folder is set to /mnt/games if not already
LIBRARY_VDF="${USER_HOME:?}/.steam/steam/steamapps/libraryfolders.vdf"
if [ ! -f "${LIBRARY_VDF}" ]; then
print_step_header "Initializing Steam library"
mkdir -p "$(dirname "${LIBRARY_VDF}")"
echo "${default_steam_library_config}" >"${LIBRARY_VDF}"
chown -R "${USER:?}:${USER:?}" "${USER_HOME:?}/.steam"
# Only if we have mounted a /mnt/games path, then make the default games library for steam
if [ -d "/mnt/games" ]; then
mkdir -p "/mnt/games/GameLibrary/Steam/steamapps"
chown "${USER:?}:${USER:?}" \
"/mnt/games/GameLibrary" \
"/mnt/games/GameLibrary/Steam" \
"/mnt/games/GameLibrary/Steam/steamapps"
echo "${games_steam_library_config}" >"/mnt/games/GameLibrary/Steam/libraryfolder.vdf"
fi
else
print_step_header "Steam library config already exists, skipping initialization"
fi
else else
echo "Disable Steam service" print_step_header "Disable Steam service"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,15 +1,15 @@
echo "**** Configure Sunshine ****" print_header "Configure Sunshine"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ "${ENABLE_SUNSHINE:-}" = "true" ]; then if [ "${ENABLE_SUNSHINE:-}" = "true" ]; then
echo "Enable Sunshine server" print_step_header "Enable Sunshine server"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/sunshine.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/sunshine.ini
else else
echo "Disable Sunshine server" print_step_header "Disable Sunshine server"
fi fi
else else
echo "Sunshine server not available when container is run in 'secondary' mode" print_step_header "Sunshine server not available when container is run in 'secondary' mode"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -1,5 +1,5 @@
echo "**** Configure VNC ****" print_header "Configure VNC"
function get_next_unused_port() { function get_next_unused_port() {
local __start_port=${1} local __start_port=${1}
@@ -16,15 +16,15 @@ function get_next_unused_port() {
# REF: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=130 # 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_VNC=$(get_next_unused_port 32035)
export PORT_VNC=${PORT_VNC:-$DYNAMIC_PORT_VNC} export PORT_VNC=${PORT_VNC:-$DYNAMIC_PORT_VNC}
echo "Configure VNC service port '${PORT_VNC}'" print_step_header "Configure VNC service port '${PORT_VNC}'"
DYNAMIC_PORT_AUDIO_STREAM=$(get_next_unused_port ${DYNAMIC_PORT_VNC}) DYNAMIC_PORT_AUDIO_STREAM=$(get_next_unused_port ${DYNAMIC_PORT_VNC})
export PORT_AUDIO_STREAM=${PORT_AUDIO_STREAM:-$DYNAMIC_PORT_AUDIO_STREAM} export PORT_AUDIO_STREAM=${PORT_AUDIO_STREAM:-$DYNAMIC_PORT_AUDIO_STREAM}
echo "Configure pulseaudio encoded stream port '${PORT_AUDIO_STREAM}'" print_step_header "Configure pulseaudio encoded stream port '${PORT_AUDIO_STREAM}'"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ "${WEB_UI_MODE:-}" = "vnc" ]; then if [ "${WEB_UI_MODE:-}" = "vnc" ]; then
echo "Enable VNC server" print_step_header "Enable VNC server"
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc.ini
# TODO: Remove this... Always enable VNC audio # TODO: Remove this... Always enable VNC audio
@@ -32,20 +32,20 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
# Enable supervisord script # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc-audio.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc-audio.ini
else else
echo "Disable audio stream" print_step_header "Disable audio stream"
echo "Disable audio websock" print_step_header "Disable audio websock"
# Disable supervisord script # Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
fi fi
else else
echo "Disable VNC server" print_step_header "Disable VNC server"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc.ini
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
fi fi
else else
echo "VNC server not available when container is run in 'secondary' mode" print_step_header "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.ini
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -9,12 +9,12 @@
# Modified By: Josh.5 (jsunnex@gmail.com) # Modified By: Josh.5 (jsunnex@gmail.com)
### ###
echo "**** Configure WoL Manager ****" print_header "Configure WoL Manager"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [ "${ENABLE_WOL_POWER_MANAGER:-}" = "true" ]; then if [ "${ENABLE_WOL_POWER_MANAGER:-}" = "true" ]; then
if [ -f "/tmp/.wol-monitor" ]; then if [ -f "/tmp/.wol-monitor" ]; then
echo "Container started in WoL Manager mode. Disabling all other services." print_step_header "Container started in WoL Manager mode. Disabling all other services."
for init_config in /etc/supervisor.d/*.ini ; do for init_config in /etc/supervisor.d/*.ini ; do
init_config_basename=$(basename "${init_config:?}") init_config_basename=$(basename "${init_config:?}")
init_name="${init_config_basename%.*}" init_name="${init_config_basename%.*}"
@@ -23,12 +23,12 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
sed -i 's|^autostart.*=.*$|autostart=false|' "${init_config:?}" sed -i 's|^autostart.*=.*$|autostart=false|' "${init_config:?}"
done done
fi fi
echo "Enable WoL Manager service." print_step_header "Enable WoL Manager service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/wol-power-manager.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/wol-power-manager.ini
else else
echo "Disable WoL Manager service." print_step_header "Disable WoL Manager service."
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/wol-power-manager.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/wol-power-manager.ini
fi fi
else else
echo "WoL Manager service not available when container is run in 'secondary' mode." print_step_header "WoL Manager service not available when container is run in 'secondary' mode."
fi fi

View File

@@ -1,4 +1,3 @@
"libraryfolders"
[Desktop Entry] [Desktop Entry]
NoDisplay=true NoDisplay=true
Version=1.0 Version=1.0

View File

@@ -13,12 +13,13 @@
"image-path": "steam.png", "image-path": "steam.png",
"exclude-global-prep-cmd": "true", "exclude-global-prep-cmd": "true",
"detached": [ "detached": [
"\/usr\/bin\/sunshine-run \/usr\/games\/steam steam:\/\/open\/bigpicture" "\/usr\/games\/steam steam:\/\/open\/bigpicture",
"\/usr\/bin\/sunshine-run sleep infinity"
], ],
"prep-cmd": [ "prep-cmd": [
{ {
"do": "", "do": "",
"undo": "sh -c \"sleep 7 && pkill -f -2 \/usr\/bin\/sunshine\"" "undo": "sh -c \"sleep 5 && pkill -f -2 \/usr\/bin\/sunshine\""
}, },
{ {
"do": "", "do": "",
@@ -27,6 +28,10 @@
{ {
"do": "", "do": "",
"undo": "\/usr\/bin\/xfce4-close-all-windows" "undo": "\/usr\/bin\/xfce4-close-all-windows"
},
{
"do": "",
"undo": "\/usr\/games\/steam steam:\/\/close\/bigpicture"
} }
] ]
} }

View File

@@ -9,7 +9,6 @@ flatpak --user install --assumeyes --or-update flathub org.mozilla.firefox
# Configure Firefox as the default browser # Configure Firefox as the default browser
echo "Configure Firefox..." echo "Configure Firefox..."
custom_webbrowser="$(cat <<EOF custom_webbrowser="$(cat <<EOF
"libraryfolders"
[Desktop Entry] [Desktop Entry]
NoDisplay=true NoDisplay=true
Version=1.0 Version=1.0

View File

@@ -0,0 +1,35 @@
#!/bin/bash
###
# File: set-custom-res.sh
# Project: bin
# Author: LyzardByte Community Docs
###
# Get params and set any defaults
width=${1:-1920}
height=${2:-1080}
refresh_rate=${3:-60}
# You may need to adjust the scaling differently so the UI/Text isn't too small / big
scale=${4:-1}
# Get the name of the active display
display_output=$(xrandr | grep " connected" | awk '{print $1 }')
# Get the modeline info from the 2nd row in the cvt output
modeline=$(cvt ${width} ${height} ${refresh_rate} | awk 'FNR == 2')
xrandr_mode_str=${modeline//Modeline \"*\" /}
mode_alias="${width}x${height}"
echo "xrandr setting new mode ${mode_alias} ${xrandr_mode_str}"
xrandr --newmode ${mode_alias} ${xrandr_mode_str}
xrandr --addmode ${display_output} ${mode_alias}
# Reset Scaling
xrandr --output ${display_output} --scale ${scale}
# Apply new xrandr mode
xrandr --output ${display_output} --primary --mode ${mode_alias} --pos 0x0 --rotate normal --scale ${scale}
# Optionally reset your wallpaper
# xwallpaper --zoom /path/to/wallpaper.png

View File

@@ -5,8 +5,8 @@
# File Created: Tuesday, 4th October 2022 8:22:17 pm # File Created: Tuesday, 4th October 2022 8:22:17 pm
# Author: Josh.5 (jsunnex@gmail.com) # Author: Josh.5 (jsunnex@gmail.com)
# ----- # -----
# Last Modified: Tuesday, 4th October 2022 8:22:17 pm # Last Modified: Wednesday, 27th November 2024 3:54:19 pm
# Modified By: Josh.5 (jsunnex@gmail.com) # Modified By: Josh5 (jsunnex@gmail.com)
### ###
set -e set -e
source /usr/bin/common-functions.sh source /usr/bin/common-functions.sh
@@ -49,6 +49,10 @@ fi
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
/usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}" /usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}"
fi fi
# If we are running the SHUI, then force the same user upon sunshine
if ([ "X${WEBUI_USER:-}" != "X" ] && [ "X${WEBUI_PASS:-}" != "X" ]); then
/usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${WEBUI_USER:?}" "${WEBUI_PASS:?}"
fi
# Remove any auto-start scripts from user's .local dir # Remove any auto-start scripts from user's .local dir
if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then
rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop" rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop"

View File

@@ -5,8 +5,8 @@
# File Created: Tuesday, 23rd August 2023 3:28:52 pm # File Created: Tuesday, 23rd August 2023 3:28:52 pm
# Author: Josh.5 (jsunnex@gmail.com) # Author: Josh.5 (jsunnex@gmail.com)
# ----- # -----
# Last Modified: Friday, 23rd August 2023 4:21:00 pm # Last Modified: Saturday, 20th July 2024 7:07:00 pm
# Modified By: Josh.5 (jsunnex@gmail.com) # Modified By: Josh5 (jsunnex@gmail.com)
### ###
set -e set -e
@@ -71,71 +71,76 @@ if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}"
__current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}') __current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}')
# Get the primary output device # Get the primary output device
__primary_output="$(echo "${__xrandr_out:?}" | grep primary | awk '{print $1}')" __primary_output="$(echo "${__xrandr_out:?}" | grep primary | head -n1 | awk '{print $1}')"
if [ "X${__primary_output:-}" = "X" ]; then
# Get the modeline from cvt and extract the second line (which contains the modeline) __primary_output="$(echo "${__xrandr_out:?}" | grep -E "\sconnected" | head -n1 | awk '{print $1}')"
__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 fi
# Check if custom mode exists
__xrandr_out="$(xrandr -q)" if [ "X${__primary_output:-}" != "X" ]; then
if echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then # Get the modeline from cvt and extract the second line (which contains the modeline)
# Check if this mode is already added to the primary display __client_modeline=$(cvt "${SUNSHINE_CLIENT_WIDTH:?}" "${SUNSHINE_CLIENT_HEIGHT:?}" "${SUNSHINE_CLIENT_FPS:?}" | grep Modeline | sed -e 's/Modeline //')
if ! echo "${__xrandr_out:?}" | sed -n "/${__primary_output:?}/,/^[^[:space:]]/ {/^[[:space:]]/p}" | grep -q "${__client_mode:?}"; then # Create a new mode for this. This allows us to force a set refresh rate that may not be supported by the display
# Custom mode exists, but is not yet added to the primary output device. Add it __client_mode=$(echo "${__client_modeline:?}" | awk -F '"' '{print $2}')
echo " - Adding custom mode '${__client_mode:?}' to device '${__primary_output:?}'"
xrandr --addmode "${__primary_output:?}" "${__client_mode:?}" # Check if this custom mode is already created
__mode_added=$? if ! echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
if [ "${__mode_added:-0}" -gt 0 ]; then # Custom mode does not yet exist. Create it
echo " - WARNING: Failed to assign custom mode to primary output device '${__primary_output:?}'." 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 else
echo " - SUCCESS" echo " - SUCCESS"
fi fi
else else
echo " - Custom mode '${__client_mode:?}' is already configured for the primary output device." echo " - Custom mode '${__client_mode:?}' already exists."
__mode_added=0
fi fi
else # Check if custom mode exists
echo " - WARNING: Custom mode '${__client_mode:?}' does not exist." __xrandr_out="$(xrandr -q)"
fi if echo "${__xrandr_out:?}" | grep -q "${__client_mode:?}"; then
# Check if this mode is already added to the primary display
# Set the current resoultion to the new mode if ! echo "${__xrandr_out:?}" | sed -n "/${__primary_output:?}/,/^[^[:space:]]/ {/^[[:space:]]/p}" | grep -q "${__client_mode:?}"; then
if ([ "X${__mode_added:-}" = "X" ] || [ "${__mode_added:-0}" -gt 0 ]); then # Custom mode exists, but is not yet added to the primary output device. Add it
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." echo " - Adding custom mode '${__client_mode:?}' to device '${__primary_output:?}'"
xrandr --output "${__primary_output:?}" --mode ${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?} --refresh ${SUNSHINE_CLIENT_FPS:?} xrandr --addmode "${__primary_output:?}" "${__client_mode:?}"
if [ $? -gt 0 ]; then __mode_added=$?
echo " - WARNING: Failed to set current output to mode '${SUNSHINE_CLIENT_WIDTH:?}x${SUNSHINE_CLIENT_HEIGHT:?}' on device '${__primary_output:?}'." 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 else
echo " - SUCCESS" echo " - WARNING: Custom mode '${__client_mode:?}' does not exist."
fi 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. # Set the current resoultion to the new mode
echo "primary_output='${__primary_output:?}'" >> /tmp/sunshine-exec-run.conf if ([ "X${__mode_added:-}" = "X" ] || [ "${__mode_added:-0}" -gt 0 ]); then
echo "display_mode='${__current_resolution:?}'" >> /tmp/sunshine-exec-run.conf 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."
echo "display_rate='${__current_refresh_rate:?}'" >> /tmp/sunshine-exec-run.conf 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
) )
fi fi