Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23e5ec9fa4 | ||
|
|
e39756c3bf | ||
|
|
77fc0221e5 | ||
|
|
67e55c50af | ||
|
|
c3dc444a8f | ||
|
|
0ac3a94009 | ||
|
|
8dd20185a7 | ||
|
|
f0accf6102 | ||
|
|
14c770bce6 | ||
|
|
6db83d2a22 | ||
|
|
6199455ae7 | ||
|
|
0c4c669ab0 | ||
|
|
920bfa7f84 | ||
|
|
463274d800 | ||
|
|
0241c9f845 | ||
|
|
860451da74 | ||
|
|
b0ba3cfc8a | ||
|
|
77967f2845 | ||
|
|
ac9c4f29ca | ||
|
|
336a6284ec | ||
|
|
9cf971f68f | ||
|
|
47f6f7a176 | ||
|
|
28c19ed1b2 | ||
|
|
728acd0ba1 | ||
|
|
a2caa9f4ec | ||
|
|
9c20a0f1f5 | ||
|
|
f17d31d077 | ||
|
|
e701b8870f | ||
|
|
bd73b199d4 | ||
|
|
12a498e1eb | ||
|
|
63cfefa1fc | ||
|
|
c3941d1f0b | ||
|
|
6cc9f56155 | ||
|
|
a17fe91113 | ||
|
|
a5f189dbc3 | ||
|
|
8f32302c0f | ||
|
|
ca7521d765 | ||
|
|
c165e28f07 | ||
|
|
7f04d8df01 | ||
|
|
f4cad0aab0 | ||
|
|
12cc16459a | ||
|
|
c651034d13 | ||
|
|
93718e1855 | ||
|
|
5a1d20daf5 | ||
|
|
15512a485f | ||
|
|
eeca08ce38 |
164
.github/workflows/build_ci.yml
vendored
164
.github/workflows/build_ci.yml
vendored
@@ -1,48 +1,38 @@
|
||||
---
|
||||
|
||||
name: Build and Deploy CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ 'dev-**', 'pr-**', staging, master ]
|
||||
tags: [ '**' ]
|
||||
branches: ['dev-**', 'pr-**', staging, master]
|
||||
tags: ['**']
|
||||
pull_request:
|
||||
branches: [ staging, master ]
|
||||
branches: [staging, master]
|
||||
schedule:
|
||||
# At 02:30 on Saturday
|
||||
- cron: '30 2 * * 6'
|
||||
|
||||
jobs:
|
||||
|
||||
build_docker:
|
||||
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavour: ["debian", "arch"]
|
||||
flavour: ['debian', 'arch']
|
||||
|
||||
steps:
|
||||
# Fetch shallow git repository
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
# ---
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Use QEMU to build
|
||||
- name: Set up QEMU
|
||||
if: success()
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v1
|
||||
# ---
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0
|
||||
|
||||
# Use docker buildx to build the docker image
|
||||
- name: Build the Docker image
|
||||
uses: docker/setup-buildx-action@v1
|
||||
if: success()
|
||||
id: buildx
|
||||
with:
|
||||
version: latest
|
||||
|
||||
# Generate 'prepare' build arguments to be retrieved later on
|
||||
# ---
|
||||
- name: Prepare
|
||||
if: success()
|
||||
id: prepare
|
||||
@@ -51,34 +41,45 @@ jobs:
|
||||
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/*/}
|
||||
SHA_SHORT="${GITHUB_SHA::7}"
|
||||
ORG=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
|
||||
BUILD_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
|
||||
SERVICE_NAME=steam-headless
|
||||
DOCKER_HUB_IMAGE=docker.io/josh5/${SERVICE_NAME:?}
|
||||
GHCR_IMAGE=ghcr.io/${ORG:?}/${SERVICE_NAME:?}
|
||||
|
||||
DOCKER_TAGS=""
|
||||
if [[ ${VERSION_TAG%/merge} == 'master' ]]; then
|
||||
if [[ ${GITHUB_REF} == refs/heads/master ]]; 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
|
||||
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
|
||||
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_IMAGE}:${FLAVOUR}-${VERSION},"
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:${FLAVOUR}-${VERSION},${GHCR_IMAGE}:${FLAVOUR}-${VERSION},"
|
||||
if [[ ${FLAVOUR} == 'debian' ]]; then
|
||||
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest,"
|
||||
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
|
||||
echo "DOCKER_TAGS='${DOCKER_TAGS}'"
|
||||
|
||||
echo "Build: [$(date +"%F %T")] [${GITHUB_REF_NAME}] [${GITHUB_SHA}] [${FLAVOUR}]" > ./overlay/version.txt
|
||||
|
||||
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"
|
||||
fi
|
||||
if [[ ${VERSION_TAG%/merge} =~ "pr-"* ]]; then
|
||||
@@ -93,52 +94,77 @@ jobs:
|
||||
echo "DOCKER_PUSH='${DOCKER_PUSH}'"
|
||||
cat ./overlay/version.txt
|
||||
|
||||
echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT
|
||||
echo "docker_hub_image:${DOCKER_HUB_IMAGE:?}"
|
||||
echo "docker_hub_image=${DOCKER_HUB_IMAGE:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "ghcr_image:${GHCR_IMAGE:?}"
|
||||
echo "ghcr_image=${GHCR_IMAGE:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "sha_short:${SHA_SHORT:?}"
|
||||
echo "sha_short=${SHA_SHORT:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "service_name:${SERVICE_NAME:?}"
|
||||
echo "service_name=${SERVICE_NAME:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "docker_image:${DOCKER_HUB_IMAGE:?}"
|
||||
echo "docker_image=${DOCKER_HUB_IMAGE:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "docker_tags:$(echo ${DOCKER_TAGS} | sed 's/,$//')"
|
||||
echo "docker_tags=$(echo ${DOCKER_TAGS} | sed 's/,$//')" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "docker_push:${DOCKER_PUSH:?}"
|
||||
echo "docker_push=${DOCKER_PUSH:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "docker_build_date:${BUILD_DATE:?}"
|
||||
echo "docker_build_date=${BUILD_DATE:?}" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "docker_platforms=linux/amd64" >> $GITHUB_OUTPUT
|
||||
echo "docker_push=${DOCKER_PUSH}" >> $GITHUB_OUTPUT
|
||||
|
||||
# Cache the build
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
id: cache
|
||||
# ---
|
||||
- name: Log into GHCR registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ matrix.flavour }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-${{ matrix.flavour }}-
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
# ---
|
||||
- name: Log into Docker Hub registry
|
||||
if: success() && (startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/tags/'))
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
# Run docker build and push
|
||||
- name: Docker Build and Push
|
||||
# ---
|
||||
- name: Docker meta
|
||||
if: success()
|
||||
uses: docker/build-push-action@v2
|
||||
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 }}
|
||||
pull: true
|
||||
platforms: ${{ steps.prepare.outputs.docker_platforms }}
|
||||
pull: 'true'
|
||||
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
|
||||
# https://github.com/docker/build-push-action/issues/252
|
||||
# https://github.com/moby/buildkit/issues/1896
|
||||
- name: Move cache
|
||||
if: always()
|
||||
run: |
|
||||
if [[ -e /tmp/.buildx-cache-new ]]; then
|
||||
echo "Cleaning up old cache..."
|
||||
rm -rf /tmp/.buildx-cache
|
||||
mv -v /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||
fi
|
||||
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
|
||||
|
||||
304
Dockerfile.arch
304
Dockerfile.arch
@@ -35,6 +35,7 @@ RUN \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
@@ -49,6 +50,8 @@ RUN \
|
||||
docbook-xml \
|
||||
docbook-xsl \
|
||||
fakeroot \
|
||||
p7zip \
|
||||
patch \
|
||||
git \
|
||||
jq \
|
||||
less \
|
||||
@@ -67,6 +70,7 @@ RUN \
|
||||
unzip \
|
||||
vim \
|
||||
wget \
|
||||
xmlstarlet \
|
||||
xz \
|
||||
&& \
|
||||
echo "**** Install python ****" \
|
||||
@@ -79,6 +83,7 @@ RUN \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
@@ -111,9 +116,10 @@ RUN \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /home/default/.cache/yay \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/yay* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& rm -rf /tmp/yay* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
@@ -126,51 +132,37 @@ RUN \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# XFS requirements
|
||||
# Install mscorefonts
|
||||
RUN \
|
||||
echo "**** Install XFS requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
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 "**** Install ms fonts ****" \
|
||||
&& su - default -c "yay -Syu --noconfirm --needed ttf-msfonts" \
|
||||
&& \
|
||||
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 X Server requirements
|
||||
ENV \
|
||||
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 \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
avahi \
|
||||
dbus \
|
||||
lib32-fontconfig \
|
||||
ttf-liberation \
|
||||
fuse2 \
|
||||
x11vnc \
|
||||
xorg \
|
||||
xorg-apps \
|
||||
@@ -190,11 +182,14 @@ RUN \
|
||||
xorg-xrandr \
|
||||
xorg-xsetroot \
|
||||
xorg-xwininfo \
|
||||
xf86-input-evdev \
|
||||
xterm \
|
||||
gamescope \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
@@ -213,6 +208,7 @@ RUN \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
@@ -226,110 +222,75 @@ RUN \
|
||||
xfce4-goodies \
|
||||
xfce4-terminal \
|
||||
ttf-liberation \
|
||||
# Delete these as they are not needed at all
|
||||
&& rm -f \
|
||||
/usr/share/applications/software-properties-drivers.desktop \
|
||||
/usr/share/applications/xfce4-about.desktop \
|
||||
/usr/share/applications/xfce4-session-logout.desktop \
|
||||
# Hide these apps. They can be displayed if a user really wants them.
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-accessibility-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-color-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xfce4-mail-reader.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/vim.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar-settings.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/thunar.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/pavucontrol.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/x11vnc.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/xterm.desktop \
|
||||
&& sed -i '/[Desktop Entry]/a\NoDisplay=true' /usr/share/applications/uxterm.desktop \
|
||||
# Force these apps to be "System" Apps rather than "Categories=System;Utility;Core;GTK;Filesystem;"
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/xfce4-appfinder.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/thunar-bulk-rename.desktop \
|
||||
&& sed -i 's/^Categories=.*$/Categories=System;/' /usr/share/applications/org.gnome.gedit.desktop \
|
||||
xdg-user-dirs \
|
||||
xdg-utils \
|
||||
imagemagick \
|
||||
&& \
|
||||
echo "**** Install WoL Manager requirements ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
tcpdump \
|
||||
xprintidle \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# TODO: Add support for flatpaks
|
||||
# Note: Debian Bullseye had bubblewrap v0.4.1 which worked fine in the Nvidia docker runtime
|
||||
# At the moment this is only working beacuse /proc is being mounted again in 10-setup_user.sh
|
||||
# Need to find a better solution for this...
|
||||
ARG BUBBLEWRAP_VERSION=0.8.0
|
||||
# Add support for flatpaks
|
||||
ENV \
|
||||
XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
|
||||
RUN \
|
||||
echo "**** Install flatpak support ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
flatpak \
|
||||
gnome-software \
|
||||
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 ****" \
|
||||
&& chmod u-s /usr/bin/bwrap \
|
||||
&& 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 ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install noVNC
|
||||
# TODO: Add nginx or remove the whole proxy setup and just connect directly for audio (I think that is the better option)
|
||||
ARG NOVNC_VERSION=1.2.0
|
||||
# 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
|
||||
ARG FRONTEND_VERSION=a8eb92f
|
||||
RUN \
|
||||
echo "**** Fetch noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& wget -O /tmp/novnc.tar.gz https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.tar.gz \
|
||||
&& \
|
||||
echo "**** Extract noVNC ****" \
|
||||
&& cd /tmp \
|
||||
&& tar -xvf /tmp/novnc.tar.gz \
|
||||
&& \
|
||||
echo "**** Configure noVNC ****" \
|
||||
&& cd /tmp/noVNC-${NOVNC_VERSION} \
|
||||
&& sed -i 's/credentials: { password: password } });/credentials: { password: password },\n wsProtocols: ["'"binary"'"] });/g' app/ui.js \
|
||||
echo "**** Fetch Web Frontend ****" \
|
||||
&& mkdir -p /opt \
|
||||
&& rm -rf /opt/noVNC \
|
||||
&& cd /opt \
|
||||
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \
|
||||
&& cd /opt/noVNC \
|
||||
&& ln -s vnc.html index.html \
|
||||
&& chmod -R 755 /opt/noVNC \
|
||||
&& rm -rf /opt/frontend \
|
||||
&& git clone https://github.com/Steam-Headless/frontend.git --branch master /opt/frontend \
|
||||
&& cd /opt/frontend \
|
||||
&& git checkout ${FRONTEND_VERSION} 2> /dev/null \
|
||||
&& git submodule init \
|
||||
&& git submodule update --depth 1 --recursive \
|
||||
&& rm -rf /opt/frontend/.git \
|
||||
&& \
|
||||
echo "**** Modify noVNC title ****" \
|
||||
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
|
||||
/opt/noVNC/app/ui.js \
|
||||
&& \
|
||||
echo "**** Install nginx support ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
nginx \
|
||||
echo "**** Configure Web Frontend ****" \
|
||||
&& echo '<!DOCTYPE html>' > /opt/frontend/index.html \
|
||||
&& echo '<html><head><meta http-equiv="refresh" content="0;url=./web/"></head><body><p>If you are not redirected, <a href="./web/">click here</a>.</p></body></html>' >> /opt/frontend/index.html \
|
||||
&& chmod -R 755 /opt/frontend \
|
||||
&& convert /opt/frontend/web/images/icons/novnc-ios-180.png -resize "128x128" /tmp/steam-headless.png \
|
||||
&& xdg-icon-resource install --novendor --size 128 /tmp/steam-headless.png \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/noVNC* \
|
||||
/tmp/novnc.tar.gz \
|
||||
&& \
|
||||
echo
|
||||
&& rm -f /tmp/steam-headless.png
|
||||
|
||||
# Install Websockify
|
||||
ARG WEBSOCKETIFY_VERSION=0.10.0
|
||||
ARG WEBSOCKETIFY_VERSION=0.11.0
|
||||
RUN \
|
||||
echo "**** Fetch Websockify ****" \
|
||||
&& cd /tmp \
|
||||
@@ -345,6 +306,7 @@ RUN \
|
||||
&& \
|
||||
echo "**** Install Websockify to noVNC path ****" \
|
||||
&& cd /tmp \
|
||||
&& mkdir -p /opt/noVNC/utils \
|
||||
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
@@ -365,51 +327,147 @@ RUN \
|
||||
gst-plugins-good \
|
||||
gst-plugins-ugly \
|
||||
&& \
|
||||
echo "**** Fetch ucspi-tcp ****" \
|
||||
&& mkdir -p /tmp/ucspi-tcp-0.88 \
|
||||
&& cd /tmp \
|
||||
#&& wget -O /tmp/ucspi-tcp.tar.gz https://github.com/trafficgate/ucspi-tcp/archive/refs/heads/master.tar.gz \
|
||||
&& wget -O /tmp/ucspi-tcp.tar.gz http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz \
|
||||
&& cd /tmp/ucspi-tcp-0.88 \
|
||||
&& tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \
|
||||
#echo "**** Fetch ucspi-tcp ****" \
|
||||
# && mkdir -p /tmp/ucspi-tcp-0.88 \
|
||||
# && cd /tmp \
|
||||
# #&& wget -O /tmp/ucspi-tcp.tar.gz https://github.com/trafficgate/ucspi-tcp/archive/refs/heads/master.tar.gz \
|
||||
# && wget -O /tmp/ucspi-tcp.tar.gz http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz \
|
||||
# && cd /tmp/ucspi-tcp-0.88 \
|
||||
# && tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \
|
||||
#&& \
|
||||
#echo "**** Build and install ucspi-tcp ****" \
|
||||
# && wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.errno.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.errno.patch \
|
||||
# && wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.a_record.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.a_record.patch \
|
||||
# && patch -p1 --input=ucspi-tcp-0.88.errno.patch \
|
||||
# && patch -p1 --input=ucspi-tcp-0.88.a_record.patch \
|
||||
# && sed -i 's|^/usr/local|/usr|' /tmp/ucspi-tcp-0.88/conf-home \
|
||||
# && make \
|
||||
# && for f in tcpserver tcprules tcprulescheck argv0 recordio tcpclient *\@ tcpcat mconnect mconnect-io addcr delcr fixcrio rblsmtpd; do \
|
||||
# cp $f /usr/bin/$f; \
|
||||
# done \
|
||||
#&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
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
|
||||
|
||||
# Setup video streaming deps
|
||||
RUN \
|
||||
echo "**** Install video streaming deps ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
libva \
|
||||
libva-mesa-driver \
|
||||
libva-intel-driver \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& rm -fr /var/lib/pacman/sync/* \
|
||||
&& rm -rf \
|
||||
/tmp/ucspi-tcp-* \
|
||||
&& rm -fr /var/cache/pacman/pkg/* \
|
||||
&& \
|
||||
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
|
||||
|
||||
# Install Steam
|
||||
RUN \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
echo "**** Install Steam ****" \
|
||||
&& pacman -Syu --noconfirm --needed \
|
||||
steam \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& pacman -Scc --noconfirm \
|
||||
&& 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
|
||||
|
||||
# Add FS overlay
|
||||
COPY overlay /
|
||||
|
||||
# Tweaks as flatpak issue isn't sorted
|
||||
RUN \
|
||||
echo "**** Setup Steam Supervisor ****" \
|
||||
&& sed -i 's#/usr/games/steam#/usr/bin/steam#g' /etc/supervisor.d/steam.ini \
|
||||
echo "**** Tweaks for Arch ****" \
|
||||
&& 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
|
||||
|
||||
@@ -426,6 +484,7 @@ ENV \
|
||||
NVIDIA_VISIBLE_DEVICES="all"
|
||||
|
||||
# Set container configuration environment variables
|
||||
# APPIMAGE_EXTRACT_AND_RUN="0"
|
||||
ENV \
|
||||
MODE="primary" \
|
||||
WEB_UI_MODE="vnc" \
|
||||
@@ -434,8 +493,9 @@ ENV \
|
||||
NEKO_PASSWORD_ADMIN=admin \
|
||||
ENABLE_STEAM="true" \
|
||||
STEAM_ARGS="-silent" \
|
||||
ENABLE_SUNSHINE="false" \
|
||||
ENABLE_EVDEV_INPUTS="false"
|
||||
ENABLE_SUNSHINE="true" \
|
||||
ENABLE_EVDEV_INPUTS="true" \
|
||||
ENABLE_WOL_POWER_MANAGER="false"
|
||||
|
||||
# Configure required ports
|
||||
ENV \
|
||||
|
||||
@@ -144,55 +144,13 @@ RUN \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install mesa and vulkan requirements
|
||||
# TODO: Strip this section back to only what is required for all GPU types.
|
||||
# Anything only required for Intel/AMD/NVIDIA should go in the container init.
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& dpkg --add-architecture i386 \
|
||||
&& 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
|
||||
# TODO: Refine this list of packages to only what is required.
|
||||
ENV \
|
||||
XORG_SOCKET_DIR="/tmp/.X11-unix" \
|
||||
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
|
||||
XDG_SESSION_TYPE="x11"
|
||||
XDG_SESSION_TYPE="x11" \
|
||||
FORCE_X11_DUMMY_CONFIG="false"
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
@@ -244,7 +202,7 @@ RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install X Server requirements ****" \
|
||||
echo "**** Install pulseaudio requirements ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
pulseaudio \
|
||||
alsa-utils \
|
||||
@@ -267,6 +225,14 @@ RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& 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 ****" \
|
||||
&& apt-get install -y \
|
||||
fonts-vlgothic \
|
||||
@@ -341,14 +307,21 @@ RUN \
|
||||
&& \
|
||||
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
|
||||
ARG NODE_VERSION="v20"
|
||||
ARG FRONTEND_VERSION=a8eb92f
|
||||
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 ****" \
|
||||
&& mkdir -p /opt \
|
||||
&& cd /opt \
|
||||
@@ -486,8 +459,30 @@ RUN \
|
||||
&& \
|
||||
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
|
||||
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 \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
@@ -510,28 +505,14 @@ RUN \
|
||||
&& \
|
||||
echo
|
||||
|
||||
# Install Steam
|
||||
RUN \
|
||||
echo "**** Update apt database ****" \
|
||||
&& apt-get update \
|
||||
&& \
|
||||
echo "**** Install Steam ****" \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
steam \
|
||||
&& ln -sf /usr/games/steam /usr/bin/steam \
|
||||
&& \
|
||||
echo "**** Section cleanup ****" \
|
||||
&& apt-get clean autoclean -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& rm -rf \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/* \
|
||||
/tmp/* \
|
||||
&& \
|
||||
echo
|
||||
# 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
|
||||
|
||||
# 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 \
|
||||
@@ -539,6 +520,14 @@ RUN \
|
||||
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
|
||||
|
||||
# Add FS overlay
|
||||
@@ -557,6 +546,7 @@ ENV \
|
||||
NVIDIA_VISIBLE_DEVICES="all"
|
||||
|
||||
# Set container configuration environment variables
|
||||
# TODO: Set the default WEBUI_USER & WEBUI_PASS after release of SHUI
|
||||
ENV \
|
||||
MODE="primary" \
|
||||
WEB_UI_MODE="vnc" \
|
||||
@@ -565,9 +555,12 @@ ENV \
|
||||
NEKO_PASSWORD_ADMIN=admin \
|
||||
ENABLE_STEAM="true" \
|
||||
STEAM_ARGS="-silent" \
|
||||
WEBUI_USER="" \
|
||||
WEBUI_PASS="" \
|
||||
ENABLE_SUNSHINE="true" \
|
||||
ENABLE_EVDEV_INPUTS="false" \
|
||||
ENABLE_WOL_POWER_MANAGER="false"
|
||||
ENABLE_EVDEV_INPUTS="true" \
|
||||
ENABLE_WOL_POWER_MANAGER="false" \
|
||||
ENABLE_SID="false"
|
||||
|
||||
# Configure required ports
|
||||
ENV \
|
||||
|
||||
@@ -11,7 +11,7 @@ Easily deploy a Steam Docker instance in seconds.
|
||||
## Features:
|
||||
- Steam Client configured for running on Linux with Proton
|
||||
- Moonlight compatible server for easy remote desktop streaming
|
||||
- One click installation of EmeDeck, Heroic and Lutris
|
||||
- Easy installation of EmeDeck, Heroic and Lutris via Flatpak
|
||||
- Full video/audio noVNC web access to a Xfce4 Desktop
|
||||
- NVIDIA, AMD and Intel GPU 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".
|
||||
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:
|
||||
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.
|
||||
|
||||
@@ -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}
|
||||
@@ -5,18 +5,20 @@
|
||||
# |____/ \__, |___/\__\___|_| |_| |_|
|
||||
# |___/
|
||||
#
|
||||
NAME='SteamHeadless'
|
||||
TZ='Pacific/Auckland'
|
||||
USER_LOCALES='en_US.UTF-8 UTF-8'
|
||||
DISPLAY=':55'
|
||||
SHM_SIZE='2G'
|
||||
## DOCKER_RUNTIME:
|
||||
## Options: ['runc', 'nvidia']
|
||||
## Description: The name of an implementation of OCI Runtime Spec
|
||||
## Available runtimes are listed when you run `docker info`.
|
||||
## Your system may have other options available. As a simple rule, if you are
|
||||
## using an NVIDIA GPU, set this to 'nvidia' for anything else, set this to 'runc'.
|
||||
DOCKER_RUNTIME='runc'
|
||||
NAME=SteamHeadless
|
||||
TZ=Pacific/Auckland
|
||||
USER_LOCALES=en_US.UTF-8 UTF-8
|
||||
DISPLAY=:55
|
||||
SHM_SIZE=2G
|
||||
## HOME_DIR:
|
||||
## Description: The path to the home directory on your host. Mounts to `/home/default` inside the container.
|
||||
HOME_DIR=/opt/container-data/steam-headless/home
|
||||
## SHARED_SOCKETS_DIR:
|
||||
## Description: Shared sockets such as pulse audio and X11.
|
||||
SHARED_SOCKETS_DIR=/opt/container-data/steam-headless/sockets
|
||||
## 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'
|
||||
PGID='1000'
|
||||
UMASK='000'
|
||||
USER_PASSWORD='password'
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
UMASK=000
|
||||
USER_PASSWORD=password
|
||||
|
||||
# __ __ _
|
||||
# | \/ | ___ __| | ___
|
||||
@@ -42,7 +44,7 @@ USER_PASSWORD='password'
|
||||
## Description: Steam Headless containers can run in a secondary mode that will only start
|
||||
## a Steam process that will then use the X server of either the host or another
|
||||
## Steam Headless container running in 'primary' mode.
|
||||
MODE='primary'
|
||||
MODE=primary
|
||||
|
||||
# ____ _
|
||||
# / ___| ___ _ ____ _(_) ___ ___ ___
|
||||
@@ -56,41 +58,41 @@ MODE='primary'
|
||||
## Options: ['vnc', 'neko', 'none']
|
||||
## Description: Configures the WebUI to use for accessing the virtual desktop.
|
||||
## Supported Modes: ['primary']
|
||||
WEB_UI_MODE='vnc'
|
||||
WEB_UI_MODE=vnc
|
||||
## ENABLE_VNC_AUDIO:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enables audio over for the VNC Web UI if 'WEB_UI_MODE' is set to 'vnc'.
|
||||
ENABLE_VNC_AUDIO='true'
|
||||
ENABLE_VNC_AUDIO=true
|
||||
## PORT_NOVNC_WEB:
|
||||
## Description: Configure the port to use for the WebUI.
|
||||
PORT_NOVNC_WEB='8083'
|
||||
PORT_NOVNC_WEB=8083
|
||||
## NEKO_NAT1TO1:
|
||||
## Description: Configure nat1to1 for the neko WebUI if it is enabled by setting 'WEB_UI_MODE' to 'neko'.
|
||||
## This will need to be the IP address of the host.
|
||||
NEKO_NAT1TO1=''
|
||||
NEKO_NAT1TO1=
|
||||
|
||||
# Steam
|
||||
## ENABLE_STEAM:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enable Steam to run on start. This will also cause steam to restart automatically if closed.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
ENABLE_STEAM='true'
|
||||
ENABLE_STEAM=true
|
||||
## STEAM_ARGS:
|
||||
## Description: Additional steam execution arguments.
|
||||
#STEAM_ARGS='-silent -bigpicture'
|
||||
STEAM_ARGS=-silent
|
||||
|
||||
# Sunshine
|
||||
## ENABLE_SUNSHINE:
|
||||
## Options: ['true', 'false']
|
||||
## Description: Enable Sunshine streaming service.
|
||||
## Supported Modes: ['primary']
|
||||
ENABLE_SUNSHINE='false'
|
||||
ENABLE_SUNSHINE=false
|
||||
## SUNSHINE_USER:
|
||||
## Description: Set the Sunshine service username.
|
||||
#SUNSHINE_USER='admin'
|
||||
SUNSHINE_USER=admin
|
||||
## SUNSHINE_PASS:
|
||||
## Description: Set the Sunshine service password.
|
||||
#SUNSHINE_PASS='admin'
|
||||
SUNSHINE_PASS=admin
|
||||
|
||||
# Xorg
|
||||
## 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
|
||||
## evdev events for Keyboard, Mouse, etc.
|
||||
## 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_DRIVER_CAPABILITIES:
|
||||
## Options: ['all', 'compute', 'compat32', 'graphics', 'utility', 'video', 'display']
|
||||
## Description: Controls which driver libraries/binaries will be mounted inside the container.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
NVIDIA_DRIVER_CAPABILITIES='all'
|
||||
NVIDIA_DRIVER_CAPABILITIES=all
|
||||
## NVIDIA_DRIVER_CAPABILITIES:
|
||||
## Available Options: ['all', 'none', '<GPU UUID>']
|
||||
## Description: Controls which GPUs will be made accessible inside the container.
|
||||
## Supported Modes: ['primary', 'secondary']
|
||||
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=
|
||||
|
||||
76
docs/compose-files/docker-compose.amd+intel.privileged.yml
Normal file
76
docs/compose-files/docker-compose.amd+intel.privileged.yml
Normal 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
|
||||
92
docs/compose-files/docker-compose.amd+intel.yml
Normal file
92
docs/compose-files/docker-compose.amd+intel.yml
Normal 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
|
||||
@@ -1,80 +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:
|
||||
hostname: ${NAME}
|
||||
extra_hosts:
|
||||
- "${NAME}:127.0.0.1"
|
||||
networks:
|
||||
external-macvlan:
|
||||
ipv4_address: ${CONTAINER_IP_ADDRESS}
|
||||
|
||||
# ENVIRONMENT:
|
||||
## Read all config variables from the .env file
|
||||
env_file: .env
|
||||
|
||||
# DEVICES:
|
||||
devices:
|
||||
# Use the host fuse device.
|
||||
- /dev/fuse
|
||||
# Add the host uinput device.
|
||||
- /dev/uinput
|
||||
# Add AMD/Intel HW accelerated video encoding/decoding devices (optional)
|
||||
#- /dev/dri
|
||||
# Ensure container access to devices 13:*
|
||||
device_cgroup_rules:
|
||||
- 'c 13:* rmw'
|
||||
|
||||
# VOLUMES:
|
||||
volumes:
|
||||
# The location of your home directory.
|
||||
- /opt/container-data/steam-headless/home/:/home/default/:rw
|
||||
|
||||
# The location where all games should be installed.
|
||||
# This path needs to be set as a library path in Steam after logging in.
|
||||
# Otherwise, Steam will store games in the home directory above.
|
||||
- /mnt/games/:/mnt/games/:rw
|
||||
|
||||
# The Xorg socket. This will be shared with other containers so they can access the X server.
|
||||
# Select only one option or leave commented out to not share the Xorg socket with any other Docker containers.
|
||||
# Option #1) Start a X server in the container to share with any other containers.
|
||||
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
# Option #2) Use an existing X server running on the host.
|
||||
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
|
||||
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
|
||||
# Leave commented out to not share the pulse socket with any other Docker containers.
|
||||
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
|
||||
|
||||
# Input devices used for mouse and joypad support inside the container.
|
||||
- /dev/input/:/dev/input/:ro
|
||||
# Host udev data required for input devices
|
||||
- /run/udev/data/:/run/udev/data/:ro
|
||||
|
||||
# Store flatpak var files in a volume.
|
||||
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
|
||||
|
||||
volumes:
|
||||
steam-headless-var-lib-flatpak:
|
||||
|
||||
networks:
|
||||
external-macvlan:
|
||||
external: true
|
||||
name: ${NETWORK_NAME}
|
||||
79
docs/compose-files/docker-compose.nvidia.privileged.yml
Normal file
79
docs/compose-files/docker-compose.nvidia.privileged.yml
Normal 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
|
||||
101
docs/compose-files/docker-compose.nvidia.yml
Normal file
101
docs/compose-files/docker-compose.nvidia.yml
Normal 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
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
services:
|
||||
steam-headless:
|
||||
image: josh5/steam-headless:latest
|
||||
restart: unless-stopped
|
||||
runtime: ${DOCKER_RUNTIME}
|
||||
## NOTE: This config uses privileged to access to host to be able to access the required devices
|
||||
privileged: true
|
||||
shm_size: ${SHM_SIZE}
|
||||
ipc: host # Could also be set to 'shareable'
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 1024
|
||||
hard: 524288
|
||||
|
||||
# NETWORK:
|
||||
## NOTE: If we do not use the host network, then physical device input is not possible
|
||||
## and your USB connected controllers will not work in steam games.
|
||||
network_mode: host
|
||||
hostname: ${NAME}
|
||||
extra_hosts:
|
||||
- "${NAME}:127.0.0.1"
|
||||
|
||||
# ENVIRONMENT:
|
||||
## Read all config variables from the .env file
|
||||
env_file: .env
|
||||
|
||||
# VOLUMES:
|
||||
volumes:
|
||||
# The location of your home directory.
|
||||
- /opt/container-data/steam-headless/home/:/home/default/:rw
|
||||
|
||||
# The location where all games should be installed.
|
||||
# This path needs to be set as a library path in Steam after logging in.
|
||||
# Otherwise, Steam will store games in the home directory above.
|
||||
- /mnt/games/:/mnt/games/:rw
|
||||
|
||||
# The Xorg socket. This will be shared with other containers so they can access the X server.
|
||||
# Select only one option:
|
||||
# Option #1) Start a X server in the container to share with any other containers.
|
||||
#- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
# Option #2) Use an existing X server running on the host.
|
||||
#- /tmp/.X11-unix/:/tmp/.X11-unix/:rw
|
||||
|
||||
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
|
||||
# Leave commented out to not share the pulse socket with any other Docker containers.
|
||||
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
|
||||
|
||||
# Input devices used for mouse and joypad support inside the container.
|
||||
- /dev/input/:/dev/input/:ro
|
||||
|
||||
# Store flatpak var files in a volume.
|
||||
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
|
||||
|
||||
volumes:
|
||||
steam-headless-var-lib-flatpak:
|
||||
@@ -38,57 +38,40 @@ sudo chown -R $(id -u):$(id -g) /mnt/games
|
||||
|
||||
Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file.
|
||||
|
||||
Populate this file with the contents of the default [Docker Compose File](./compose-files/docker-compose.default.yml).
|
||||
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).
|
||||
|
||||
## CONFIGURE HOST:
|
||||
#### Multipl AMD or Intel GPUs
|
||||
|
||||
It is recommended that you configure this container to use a Macvlan network. If you know what you are doing, you can also use an IPvlan or Host, but I will not be covering that setup in this documentation.
|
||||
|
||||
To simplify the setup process and allow you to reuse the created Macvlan for other containers, we will create this Macvlan manually rather than have Docker compose handle it. If you know what you are doing with Docker compose and you would rather have the Macvlan managed there, feel free to do so. Otherwise run this command and carry on with the setup:
|
||||
|
||||
### 1) Discover your parent network:
|
||||
To find the parent network device, run the command `ip address show`. Find the device that has the IP address of your Host server.
|
||||
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'`
|
||||
```
|
||||
root@Tower:~# ip address show
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 ::1/128 scope host
|
||||
valid_lft forever preferred_lft forever
|
||||
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
|
||||
link/ipip 0.0.0.0 brd 0.0.0.0
|
||||
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq master br0 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
4: eth0.1@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.1 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
5: eth0.3@eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0.3 state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
6: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
|
||||
link/ether 7c:11:a9:b1:15:b9 brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.1.43/24 brd 192.168.1.255 scope global dynamic noprefixroute br0
|
||||
valid_lft 440sec preferred_lft 365sec
|
||||
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 output, I will select br0 as the parent network device which has the IP address of "192.168.1.43".
|
||||
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) Create a macvlan Docker network
|
||||
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*`.
|
||||
```
|
||||
# Set the parent network device.
|
||||
NETWORK_PARTENT=br0
|
||||
# Name this whatever you like, but ensure you update the `.env` file below to match.
|
||||
NETWORK_NAME=steam-headless-vlan
|
||||
# Choose a network subnet and gateway that matches your host network
|
||||
NETWORK_SUBNET=192.168.1.0/24
|
||||
NETWORK_GATEWAY=192.168.1.1
|
||||
# Execute the docker network create command
|
||||
sudo docker network create -d macvlan \
|
||||
--subnet=${NETWORK_SUBNET:?} \
|
||||
--gateway=${NETWORK_GATEWAY:?} \
|
||||
-o parent=${NETWORK_PARTENT:?} \
|
||||
${NETWORK_NAME:?}
|
||||
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:
|
||||
|
||||
@@ -105,9 +88,8 @@ sudo docker-compose up -d --force-recreate
|
||||
```
|
||||
|
||||
After container executes successfully, navigate to your docker host URL in your browser on port 8083 and click connect.
|
||||
http://<host-ip>:8083/
|
||||

|
||||
`http://<host-ip>:8083/`
|
||||

|
||||
|
||||
If using a `/mnt/games` volume mount, wait until Steam installs and executes, then restart the container. This step
|
||||
is necessary to create the required steamapps folder in the /mnt/games volume after initial installation. If this
|
||||
doesn't occur, you will receive a "disk write error" when trying to install to this location.
|
||||
## Troubleshooting
|
||||
[Troubleshooting Docs](./troubleshooting.md)
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
BIN
docs/images/web_connect.png
Normal file
BIN
docs/images/web_connect.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
@@ -11,7 +11,7 @@ Once your Flatpak refresh is complete, everything should work correctly and your
|
||||
|
||||
## An error occurred while installing <game>: "disk write error"
|
||||
|
||||

|
||||

|
||||
|
||||
1) Stop the container
|
||||
2) Verify your mounted /mnt/games volume is owned by the executing UID/GID, and 777 permissions are set.
|
||||
|
||||
@@ -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!
|
||||
>
|
||||
> This will not work with Ubuntu Desktop.
|
||||
> These steps assume you are running a minimal **Ubuntu Server** installation **without any desktop environment**.
|
||||
> This setup **will not work** on 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-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:
|
||||
|
||||
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.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
@@ -22,6 +22,31 @@ if [[ -f /version.txt ]]; then
|
||||
cat /version.txt
|
||||
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
|
||||
for init_script in /etc/cont-init.d/*.sh ; do
|
||||
echo
|
||||
@@ -59,9 +84,9 @@ touch /tmp/.first-run-user-init-scripts
|
||||
|
||||
# Start supervisord
|
||||
echo
|
||||
echo "**** Starting supervisord ****";
|
||||
echo "Logging all root services to '/var/log/supervisor/'"
|
||||
echo "Logging all user services to '/home/${USER:?}/.cache/log/'"
|
||||
print_header "Starting supervisord";
|
||||
print_step_header "Logging all root services to '/var/log/supervisor/'"
|
||||
print_step_header "Logging all user services to '/home/${USER:?}/.cache/log/'"
|
||||
echo
|
||||
mkdir -p /var/log/supervisor
|
||||
chmod a+rw /var/log/supervisor
|
||||
|
||||
@@ -14,18 +14,18 @@ PGID=${PGID:-100}
|
||||
UMASK=${UMASK:-000}
|
||||
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}
|
||||
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 )
|
||||
for group_name in "${additional_groups[@]}"; do
|
||||
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}
|
||||
fi
|
||||
done
|
||||
@@ -54,20 +54,20 @@ for dev in "${device_nodes[@]}"; do
|
||||
|
||||
# Add group to user
|
||||
if [[ "${added_groups}" != *"${dev_group}"* ]]; then
|
||||
echo "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
|
||||
print_step_header "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
|
||||
usermod -aG ${dev_group} ${USER}
|
||||
added_groups=" ${added_groups} ${dev_group} "
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
echo "Setting umask to ${UMASK}";
|
||||
print_step_header "Setting umask to ${UMASK}";
|
||||
umask ${UMASK}
|
||||
|
||||
|
||||
# TODO: Move this to its own 'display' init script. It does not really belong here
|
||||
# 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}
|
||||
# Ensure it is owned by the 'default' user
|
||||
chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR}
|
||||
@@ -80,19 +80,19 @@ chmod a+r /etc/alternatives/desktop-background
|
||||
|
||||
|
||||
# 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"
|
||||
chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log"
|
||||
|
||||
|
||||
# Set the root and user password
|
||||
echo "Setting root password"
|
||||
print_step_header "Setting root password"
|
||||
echo "root:${USER_PASSWORD}" | chpasswd
|
||||
echo "Setting user password"
|
||||
print_step_header "Setting user password"
|
||||
echo "${USER}:${USER_PASSWORD}" | chpasswd
|
||||
|
||||
# Set root XDG_RUNTIME_DIR path
|
||||
mkdir -p /tmp/runtime-root
|
||||
chown root:root /tmp/runtime-root
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
@@ -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 [ -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
|
||||
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
|
||||
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
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
|
||||
# Configure dbus
|
||||
echo "**** Configure container dbus ****";
|
||||
print_header "Configure container dbus"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); 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
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
|
||||
else
|
||||
echo "Container configured to run its own dbus";
|
||||
print_step_header "Container configured to run its own dbus";
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
|
||||
# Configure dbus to run as USER
|
||||
@@ -25,8 +25,8 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
find /var/run/dbus -name "pid" -exec rm -f {} \;
|
||||
fi
|
||||
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
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,60 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: 30-configure_udev.sh
|
||||
# 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)
|
||||
###
|
||||
|
||||
# Running udev only works in privileged container
|
||||
# Source: https://github.com/balena-io-playground/balena-base-images/
|
||||
tmp_mount='/tmp/privileged_test'
|
||||
mkdir -p "${tmp_mount}"
|
||||
if mount -t devtmpfs none "${tmp_mount}" &> /dev/null; then
|
||||
is_privileged=true
|
||||
umount "${tmp_mount}"
|
||||
else
|
||||
is_privileged=false
|
||||
fi
|
||||
rm -rf "${tmp_mount}"
|
||||
# Configure dbus
|
||||
print_header "Configure udevd"
|
||||
|
||||
|
||||
if [[ "${is_privileged}" == "true" ]]; then
|
||||
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
|
||||
if [ ! -w /sys ]; then
|
||||
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
|
||||
run_dumb_udev="false"
|
||||
if [ ! -w /sys ]; then
|
||||
# Disable supervisord script since we are not able to write to sysfs
|
||||
echo "**** Disable udev - /sys is mounted RO ****";
|
||||
print_step_header "Disable udevd - /sys is mounted RO"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
elif [ ! -w /run/udev ]; then
|
||||
run_dumb_udev="true"
|
||||
elif [ ! -d /run/udev ]; then
|
||||
# Disable supervisord script since we are not able to write to udev/data path
|
||||
echo "**** Disable udev - /run/udev is mounted RO ****";
|
||||
print_step_header "Disable udevd - /run/udev does not exist"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
elif udevadm trigger &> /dev/null; then
|
||||
echo "**** Configure container to run udev management ****";
|
||||
run_dumb_udev="true"
|
||||
elif [ ! -w /run/udev ]; then
|
||||
# Disable supervisord script since we are not able to write to udev/data path
|
||||
print_step_header "Disable udevd - /run/udev is mounted RO"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
run_dumb_udev="false"
|
||||
elif udevadm trigger &> /dev/null; then
|
||||
print_step_header "Configure container to run udev management"
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
|
||||
# Configure udev permissions
|
||||
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
|
||||
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
|
||||
fi
|
||||
else
|
||||
# Disable supervisord script since we are not able to execute "udevadm trigger"
|
||||
echo "**** Disable udev service due to privilege restrictions ****";
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
fi
|
||||
run_dumb_udev="false"
|
||||
else
|
||||
# Disable supervisord script
|
||||
echo "**** Disable udev service ****";
|
||||
# Disable supervisord script since we are not able to execute "udevadm trigger"
|
||||
print_step_header "Disable udev service due to privilege restrictions"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
|
||||
run_dumb_udev="true"
|
||||
fi
|
||||
|
||||
if [ "${run_dumb_udev}" = "true" ]; then
|
||||
# Enable dumb-udev instead of udevd
|
||||
print_step_header "Enable dumb-udev service"
|
||||
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
|
||||
fi
|
||||
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
|
||||
# Configure dbus
|
||||
print_header "Configure local"
|
||||
|
||||
current_local=$(head -n 1 /etc/locale.gen)
|
||||
user_local=$(echo ${USER_LOCALES} | cut -d ' ' -f 1)
|
||||
|
||||
if [ "${current_local}" != "${USER_LOCALES}" ]; then
|
||||
echo "**** Configuring Locales to ${USER_LOCALES} ****";
|
||||
print_step_header "Configuring Locales to ${USER_LOCALES}"
|
||||
rm /etc/locale.gen
|
||||
echo -e "${USER_LOCALES}\nen_US.UTF-8 UTF-8" > "/etc/locale.gen"
|
||||
export LANGUAGE="${user_local}"
|
||||
export LANG="${user_local}"
|
||||
export LC_ALL="${user_local}" 2> /dev/null
|
||||
sleep 2
|
||||
sleep 0.5
|
||||
locale-gen
|
||||
update-locale LC_ALL="${user_local}"
|
||||
else
|
||||
echo "**** Locales already set correctly to ${USER_LOCALES} ****";
|
||||
print_step_header "Locales already set correctly to ${USER_LOCALES}"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
|
||||
echo "**** Configure pulseaudio ****"
|
||||
# Configure dbus
|
||||
print_header "Configure pulseaudio"
|
||||
|
||||
# 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
|
||||
|
||||
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|^; daemon-binary.*$|daemon-binary = /bin/true|' /etc/pulse/client.conf
|
||||
|
||||
sed -i 's|^; flat-volumes.*$|flat-volumes = yes|' /etc/pulse/daemon.conf
|
||||
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
|
||||
mkdir -p \
|
||||
@@ -37,4 +38,4 @@ else
|
||||
fi
|
||||
chown -R ${USER} /etc/pulse
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
# NVIDIA Params
|
||||
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select:?}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)"
|
||||
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select:?}" 2> /dev/null | sed -n 2p)
|
||||
export nvidia_host_driver_version="$(nvidia-smi 2> /dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
|
||||
if [ "X${gpu_select:-}" != "X" ]; then
|
||||
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select:?}" 2>/dev/null | sed -n 2p | cut -d ':' -f2,3)"
|
||||
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select:?}" 2>/dev/null | sed -n 2p)
|
||||
export nvidia_host_driver_version="$(nvidia-smi 2>/dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
|
||||
fi
|
||||
|
||||
# Intel params
|
||||
# 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)"
|
||||
|
||||
function download_driver {
|
||||
local driver_url
|
||||
local stripped_version
|
||||
|
||||
mkdir -p "${USER_HOME:?}/Downloads"
|
||||
chown -R ${USER:?} "${USER_HOME:?}/Downloads"
|
||||
|
||||
if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then
|
||||
echo "Downloading driver v${nvidia_host_driver_version:?}"
|
||||
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
|
||||
print_step_header "Downloading driver v${nvidia_host_driver_version:?}"
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
function install_nvidia_driver {
|
||||
# Check here if the currently installed version matches using nvidia-settings
|
||||
nvidia_settings_version=$(nvidia-settings --version 2> /dev/null | grep version | cut -d ' ' -f 4)
|
||||
nvidia_settings_version=$(nvidia-settings --version 2>/dev/null | grep version | cut -d ' ' -f 4)
|
||||
if [ "${nvidia_settings_version:-}X" != "${nvidia_host_driver_version:-}X" ]; then
|
||||
# Download the driver (if it does not yet exist locally)
|
||||
download_driver
|
||||
|
||||
# if command -v pacman &> /dev/null; then
|
||||
# echo "Install NVIDIA vulkan utils" \
|
||||
# && pacman -Syu --noconfirm --needed \
|
||||
# lib32-nvidia-utils \
|
||||
# lib32-vulkan-icd-loader
|
||||
# nvidia-utils \
|
||||
# vulkan-icd-loader \
|
||||
# && echo
|
||||
# fi
|
||||
if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) >= 550)); then
|
||||
sed -i 's/--no-multigpu//g' /etc/cont-init.d/70-configure_xorg.sh
|
||||
fi
|
||||
|
||||
if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) > 500)); then
|
||||
echo "Installing NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
|
||||
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"
|
||||
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
|
||||
--silent \
|
||||
@@ -77,9 +97,9 @@ function install_nvidia_driver {
|
||||
--no-check-for-alternate-installs \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
>"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
else
|
||||
echo "Installing Legacy NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
|
||||
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"
|
||||
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
|
||||
--silent \
|
||||
@@ -98,8 +118,10 @@ function install_nvidia_driver {
|
||||
--no-check-for-alternate-installs \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
> "${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
>"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
|
||||
fi
|
||||
else
|
||||
print_step_header "NVIDIA driver version ${nvidia_settings_version:-} is already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -110,13 +132,13 @@ function patch_nvidia_driver {
|
||||
(
|
||||
set +e
|
||||
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 \
|
||||
-O "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch.sh"
|
||||
fi
|
||||
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
|
||||
echo "Fetch NVIDIA NvFBC patch"
|
||||
print_step_header "Fetch NVIDIA NvFBC patch"
|
||||
wget -q --show-progress --progress=bar:force:noscroll \
|
||||
-O "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"https://raw.githubusercontent.com/keylase/nvidia-patch/${NVIDIA_PATCH_VERSION:?}/patch-fbc.sh"
|
||||
@@ -125,89 +147,113 @@ function patch_nvidia_driver {
|
||||
"${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
|
||||
"${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
|
||||
echo "Install NVIDIA driver patches"
|
||||
echo "/patched-lib" > /etc/ld.so.conf.d/000-patched-lib.conf
|
||||
print_step_header "Install NVIDIA driver patches"
|
||||
echo "/patched-lib" >/etc/ld.so.conf.d/000-patched-lib.conf
|
||||
mkdir -p "/patched-lib"
|
||||
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
PATCH_OUTPUT_DIR="/patched-lib" "${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
|
||||
|
||||
pushd "/patched-lib" &> /dev/null || { echo "Error: Failed to push directory to /patched-lib"; exit 1; }
|
||||
for f in * ; do
|
||||
pushd "/patched-lib" &>/dev/null || {
|
||||
print_error "Failed to push directory to /patched-lib"
|
||||
exit 1
|
||||
}
|
||||
for f in *; do
|
||||
suffix="${f##*.so}"
|
||||
name="$(basename "$f" "$suffix")"
|
||||
[ -h "$name" ] || ln -sf "$f" "$name"
|
||||
[ -h "$name" ] || ln -sf "$f" "$name.1"
|
||||
done
|
||||
ldconfig
|
||||
popd &> /dev/null || { echo "Error: Failed to pop directory out of /patched-lib"; exit 1; }
|
||||
popd &>/dev/null || {
|
||||
print_error "Failed to pop directory out of /patched-lib"
|
||||
exit 1
|
||||
}
|
||||
)
|
||||
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
|
||||
}
|
||||
|
||||
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 \
|
||||
lib32-vulkan-icd-loader \
|
||||
lib32-vulkan-radeon \
|
||||
vulkan-icd-loader \
|
||||
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
|
||||
# [[ "${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
|
||||
elif command -v apt-get &>/dev/null; then
|
||||
install_deb_mesa
|
||||
fi
|
||||
}
|
||||
|
||||
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 \
|
||||
lib32-vulkan-icd-loader \
|
||||
lib32-vulkan-intel \
|
||||
vulkan-icd-loader \
|
||||
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
|
||||
# [[ "${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
|
||||
elif command -v apt-get &>/dev/null; then
|
||||
install_deb_mesa
|
||||
fi
|
||||
}
|
||||
|
||||
# Intel Arc GPU or Intel CPU with possible iGPU
|
||||
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
|
||||
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
|
||||
else
|
||||
echo "**** No Intel device found ****"
|
||||
print_header "No Intel device found"
|
||||
fi
|
||||
# AMD GPU
|
||||
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
|
||||
else
|
||||
echo "**** No AMD device found ****"
|
||||
print_header "No AMD device found"
|
||||
fi
|
||||
# NVIDIA GPU
|
||||
if [ "${nvidia_pci_address:-}X" != "X" ]; then
|
||||
echo "**** Found NVIDIA device '${nvidia_gpu_name:?}' ****"
|
||||
if [ "${NVIDIA_DRIVER_VERSION:-}X" != "X" ]; then
|
||||
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
|
||||
patch_nvidia_driver
|
||||
else
|
||||
echo "**** No NVIDIA device found ****"
|
||||
print_header "No NVIDIA device found"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
|
||||
echo "**** Configure Desktop ****"
|
||||
print_header "Configure Desktop"
|
||||
|
||||
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
|
||||
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
|
||||
fi
|
||||
|
||||
# Setup home directory
|
||||
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
|
||||
echo "Installing default home directory template"
|
||||
print_step_header "Installing default home directory template"
|
||||
mkdir -p "${USER_HOME:?}"
|
||||
rsync -aq /templates/home_directory_template/ "${USER_HOME:?}"/
|
||||
touch /tmp/.home-directory-template-updated
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -30,36 +30,42 @@ fi
|
||||
|
||||
# Configure a NVIDIA X11 config
|
||||
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)
|
||||
IFS=":." ARR_ID=(${nvidia_gpu_hex_id})
|
||||
unset IFS
|
||||
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)
|
||||
echo "Writing X11 config with ${MODELINE}"
|
||||
print_step_header "Writing X11 config with ${MODELINE}"
|
||||
connected_monitor="--use-display-device=None"
|
||||
if [[ "X${DISPLAY_VIDEO_PORT:-}" != "X" ]]; then
|
||||
connected_monitor="--connected-monitor=${DISPLAY_VIDEO_PORT:?}"
|
||||
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:?}
|
||||
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
|
||||
# Prevent interference between GPUs
|
||||
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
|
||||
function configure_x_server {
|
||||
# Configure x to be run by anyone
|
||||
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 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
|
||||
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
|
||||
echo 'needs_root_rights=yes' >> /etc/X11/Xwrapper.config
|
||||
fi
|
||||
@@ -73,7 +79,7 @@ function configure_x_server {
|
||||
# Clear out old lock files
|
||||
display_file=${XORG_SOCKET_DIR}/X${DISPLAY#:}
|
||||
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 ${display_file}
|
||||
fi
|
||||
@@ -84,46 +90,46 @@ function configure_x_server {
|
||||
chmod 1777 /tmp/.ICE-unix/
|
||||
|
||||
# Check if this container is being run as a secondary instance
|
||||
if [ "${MODE}" == "p" ] | [ "${MODE}" == "primary" ]; then
|
||||
echo "Configure container as primary the X server"
|
||||
if ([ "${MODE}" = "p" ] || [ "${MODE}" = "primary" ]); then
|
||||
print_step_header "Configure container as primary the X server"
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xorg.ini
|
||||
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
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
|
||||
# Enable xvfb supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/xvfb.ini
|
||||
else
|
||||
echo "Configure container with no X server"
|
||||
print_step_header "Configure container with no X server"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/xorg.ini
|
||||
fi
|
||||
|
||||
# Enable KB/Mouse input capture with Xorg if configured
|
||||
if [ ${ENABLE_EVDEV_INPUTS:-} = "true" ]; then
|
||||
echo "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
|
||||
print_step_header "Enabling evdev input class on pointers, keyboards, touchpads, touch screens, etc."
|
||||
cp -f /usr/share/X11/xorg.conf.d/10-evdev.conf /etc/X11/xorg.conf.d/10-evdev.conf
|
||||
else
|
||||
echo "Leaving evdev inputs disabled"
|
||||
print_step_header "Leaving evdev inputs disabled"
|
||||
fi
|
||||
|
||||
# Configure dummy config if no monitor is connected (not applicable to NVIDIA)
|
||||
if [[ "X${monitor_connected}" == "X" ]]; then
|
||||
echo "No monitors connected. Installing dummy xorg.conf"
|
||||
if ([ "X${monitor_connected}" = "X" ] || [ "${FORCE_X11_DUMMY_CONFIG}" = "true" ]); then
|
||||
print_step_header "No monitors connected. Installing dummy xorg.conf"
|
||||
# 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
|
||||
}
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [[ -z ${nvidia_gpu_hex_id} ]]; then
|
||||
echo "**** Generate default xorg.conf ****";
|
||||
print_header "Generate default xorg.conf"
|
||||
configure_x_server
|
||||
else
|
||||
echo "**** Generate NVIDIA xorg.conf ****";
|
||||
print_header "Generate NVIDIA xorg.conf"
|
||||
configure_x_server
|
||||
configure_nvidia_x_server
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
echo "**** Configure Flatpak ****"
|
||||
print_header "Configure Flatpak"
|
||||
|
||||
if [ "X${NVIDIA_VISIBLE_DEVICES:-}" != "X" ]; then
|
||||
# Fix some flatpak quirks (not sure what is happening here) for NVIDIA containers
|
||||
mount -t proc none /proc
|
||||
flatpak list
|
||||
echo "Flatpak configured for running inside a Docker container"
|
||||
print_step_header "Flatpak configured for running inside a Docker container"
|
||||
else
|
||||
echo "Flatpak already configured for running inside a Docker container"
|
||||
print_step_header "Flatpak already configured for running inside a Docker container"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
echo "**** Configure Neko ****"
|
||||
print_header "Configure Neko"
|
||||
# REF: https://neko.m1k1o.net/#/getting-started/configuration
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); 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
|
||||
|
||||
# Make directories for neko
|
||||
@@ -15,9 +15,9 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
# Configure nat1to1 if it is not already set
|
||||
if [[ -z ${NEKO_NAT1TO1} ]]; then
|
||||
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
|
||||
echo "User provided setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
|
||||
print_step_header "User provided setting NEKO_NAT1TO1=${NEKO_NAT1TO1}"
|
||||
fi
|
||||
|
||||
# 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}"
|
||||
fi
|
||||
else
|
||||
echo "Disable Neko server"
|
||||
print_step_header "Disable Neko server"
|
||||
fi
|
||||
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
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
echo "**** Configure Steam ****"
|
||||
print_header "Configure Steam"
|
||||
|
||||
steam_autostart_desktop="$(cat <<EOF
|
||||
steam_autostart_desktop="$(
|
||||
cat <<EOF
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
@@ -17,19 +18,117 @@ Hidden=false
|
||||
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 [ "${MODE}" == "s" ] | [ "${MODE}" == "secondary" ]; then
|
||||
echo "Enable Steam supervisor.d service"
|
||||
if [ "${MODE}" == "s" ] || [ "${MODE}" == "secondary" ]; then
|
||||
print_step_header "Enable Steam supervisor.d service"
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/steam.ini
|
||||
else
|
||||
echo "Enable Steam auto-start script"
|
||||
print_step_header "Enable Steam auto-start script"
|
||||
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
|
||||
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
|
||||
echo "Disable Steam service"
|
||||
print_step_header "Disable Steam service"
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/steam.ini
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
echo "**** Configure Sunshine ****"
|
||||
print_header "Configure Sunshine"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); 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
|
||||
else
|
||||
echo "Disable Sunshine server"
|
||||
print_step_header "Disable Sunshine server"
|
||||
fi
|
||||
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
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
echo "**** Configure VNC ****"
|
||||
print_header "Configure VNC"
|
||||
|
||||
function get_next_unused_port() {
|
||||
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
|
||||
DYNAMIC_PORT_VNC=$(get_next_unused_port 32035)
|
||||
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})
|
||||
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 [ "${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
|
||||
|
||||
# TODO: Remove this... Always enable VNC audio
|
||||
@@ -32,20 +32,20 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
# Enable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/vnc-audio.ini
|
||||
else
|
||||
echo "Disable audio stream"
|
||||
echo "Disable audio websock"
|
||||
print_step_header "Disable audio stream"
|
||||
print_step_header "Disable audio websock"
|
||||
# Disable supervisord script
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/vnc-audio.ini
|
||||
fi
|
||||
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-audio.ini
|
||||
fi
|
||||
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-audio.ini
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
echo -e "\e[34mDONE\e[0m"
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
|
||||
echo "**** Configure WoL Manager ****"
|
||||
print_header "Configure WoL Manager"
|
||||
|
||||
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
if [ "${ENABLE_WOL_POWER_MANAGER:-}" = "true" ]; then
|
||||
if [ -f "/tmp/.wol-monitor" ]; then
|
||||
echo "Container started in WoL Manager mode. Disabling all other services."
|
||||
print_step_header "Container started in WoL Manager mode. Disabling all other services."
|
||||
for init_config in /etc/supervisor.d/*.ini ; do
|
||||
init_config_basename=$(basename "${init_config:?}")
|
||||
init_name="${init_config_basename%.*}"
|
||||
@@ -23,12 +23,12 @@ if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
|
||||
sed -i 's|^autostart.*=.*$|autostart=false|' "${init_config:?}"
|
||||
done
|
||||
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
|
||||
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
|
||||
fi
|
||||
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
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"libraryfolders"
|
||||
[Desktop Entry]
|
||||
NoDisplay=true
|
||||
Version=1.0
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
"image-path": "steam.png",
|
||||
"exclude-global-prep-cmd": "true",
|
||||
"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": [
|
||||
{
|
||||
"do": "",
|
||||
"undo": "sh -c \"sleep 7 && pkill -f -2 \/usr\/bin\/sunshine\""
|
||||
"undo": "sh -c \"sleep 5 && pkill -f -2 \/usr\/bin\/sunshine\""
|
||||
},
|
||||
{
|
||||
"do": "",
|
||||
@@ -27,6 +28,10 @@
|
||||
{
|
||||
"do": "",
|
||||
"undo": "\/usr\/bin\/xfce4-close-all-windows"
|
||||
},
|
||||
{
|
||||
"do": "",
|
||||
"undo": "\/usr\/games\/steam steam:\/\/close\/bigpicture"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ wait_for_x() {
|
||||
wait_for_udev() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while [ ! -f /tmp/.started-udev ]; do
|
||||
while [ ! -e /run/udev/control ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
|
||||
@@ -9,7 +9,6 @@ flatpak --user install --assumeyes --or-update flathub org.mozilla.firefox
|
||||
# Configure Firefox as the default browser
|
||||
echo "Configure Firefox..."
|
||||
custom_webbrowser="$(cat <<EOF
|
||||
"libraryfolders"
|
||||
[Desktop Entry]
|
||||
NoDisplay=true
|
||||
Version=1.0
|
||||
|
||||
35
overlay/usr/bin/set-custom-res.sh
Executable file
35
overlay/usr/bin/set-custom-res.sh
Executable 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
|
||||
26
overlay/usr/bin/start-dumb-udev.sh
Executable file
26
overlay/usr/bin/start-dumb-udev.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
###
|
||||
# File: start-dumb-udev.sh
|
||||
# Project: bin
|
||||
# File Created: Tuesday, 12th January 2022 8:46:47 am
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 14th January 2022 9:21:00 am
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$dumb_udev_pid" 2>/dev/null
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Start dumb-udev
|
||||
dumb-udev &
|
||||
dumb_udev_pid=$!
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$dumb_udev_pid"
|
||||
@@ -19,7 +19,6 @@ trap _term SIGTERM SIGINT
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
echo "PULSEAUDIO: Starting pulseaudio service"
|
||||
sleep 5
|
||||
#/usr/bin/pulseaudio --disallow-module-loading --disallow-exit --exit-idle-time=-1 &
|
||||
/usr/bin/pulseaudio --exit-idle-time=-1 &
|
||||
pulseaudio_pid=$!
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# File Created: Tuesday, 4th October 2022 8:22:17 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Tuesday, 4th October 2022 8:22:17 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
# Last Modified: Wednesday, 27th November 2024 3:54:19 pm
|
||||
# Modified By: Josh5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
source /usr/bin/common-functions.sh
|
||||
@@ -19,15 +19,15 @@ _term() {
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -TERM "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 2
|
||||
[ "$counter" -gt 8 ] && break
|
||||
sleep 0.5
|
||||
done
|
||||
counter=0
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -KILL "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 1
|
||||
[ "$counter" -gt 4 ] && break
|
||||
sleep 0.5
|
||||
done
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
@@ -49,6 +49,10 @@ fi
|
||||
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
|
||||
/usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}"
|
||||
fi
|
||||
# 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
|
||||
if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then
|
||||
rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop"
|
||||
|
||||
@@ -16,12 +16,6 @@ _term() {
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
# Remove lockfile
|
||||
rm -f /tmp/.started-udev
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Start udev
|
||||
if command -v udevd &>/dev/null; then
|
||||
@@ -32,11 +26,8 @@ fi
|
||||
# Monitor kernel uevents
|
||||
udevadm monitor &
|
||||
monitor_pid=$!
|
||||
# Touch lockfile
|
||||
sleep 1
|
||||
touch /tmp/.started-udev
|
||||
# Wait for 10 seconds, then request device events from the kernel
|
||||
sleep 10
|
||||
# Wait for 5 seconds, then request device events from the kernel
|
||||
sleep 5
|
||||
udevadm trigger
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# File Created: Tuesday, 23rd August 2023 3:28:52 pm
|
||||
# Author: Josh.5 (jsunnex@gmail.com)
|
||||
# -----
|
||||
# Last Modified: Friday, 23rd August 2023 4:21:00 pm
|
||||
# Modified By: Josh.5 (jsunnex@gmail.com)
|
||||
# Last Modified: Saturday, 20th July 2024 7:07:00 pm
|
||||
# Modified By: Josh5 (jsunnex@gmail.com)
|
||||
###
|
||||
set -e
|
||||
|
||||
@@ -71,8 +71,12 @@ if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}"
|
||||
__current_refresh_rate=$(echo ${__current_current_mode:?} | awk '{sub(/\*/, "", $2); print $2}')
|
||||
|
||||
# Get the primary output device
|
||||
__primary_output="$(echo "${__xrandr_out:?}" | grep primary | awk '{print $1}')"
|
||||
__primary_output="$(echo "${__xrandr_out:?}" | grep primary | head -n1 | awk '{print $1}')"
|
||||
if [ "X${__primary_output:-}" = "X" ]; then
|
||||
__primary_output="$(echo "${__xrandr_out:?}" | grep -E "\sconnected" | head -n1 | awk '{print $1}')"
|
||||
fi
|
||||
|
||||
if [ "X${__primary_output:-}" != "X" ]; then
|
||||
# Get the modeline from cvt and extract the second line (which contains the modeline)
|
||||
__client_modeline=$(cvt "${SUNSHINE_CLIENT_WIDTH:?}" "${SUNSHINE_CLIENT_HEIGHT:?}" "${SUNSHINE_CLIENT_FPS:?}" | grep Modeline | sed -e 's/Modeline //')
|
||||
# Create a new mode for this. This allows us to force a set refresh rate that may not be supported by the display
|
||||
@@ -136,6 +140,7 @@ if ([ "X${SUNSHINE_CLIENT_WIDTH:-}" != "X" ] && [ "X${SUNSHINE_CLIENT_HEIGHT:-}"
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user