135 Commits

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

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

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

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

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

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

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

This pull request first attempts to download the driver from the NVIDIA repository and then falls back to the Flathub repository while printing an error if it is unable to download the driver.
2024-07-06 20:23:51 +12:00
tem
9cf971f68f Update arch just so it builds 2024-06-20 13:45:38 +12:00
Josh.5
47f6f7a176 Improve documentation for Intel and AMD installations 2024-05-08 17:22:57 +12:00
Josh.5
28c19ed1b2 Update docker compose templates to not rely on NVIDIA runtime
Plenty of setups may have either nvidia container toolkit without the runtime wrapper, or no toolkit at all.
These updated templates allow for all those cases while still providing support for NVIDIA GPUs.
2024-03-15 04:52:32 +13:00
Josh.5
728acd0ba1 Remove env_file and add all env variables to a environment: section 2024-03-15 04:12:55 +13:00
Josh.5
a2caa9f4ec Add missing NVIDIA_DRIVER_VERSION variable to .env template
This is used when nvidia container toolkit is not used
2024-03-14 20:37:53 +13:00
Josh.5
9c20a0f1f5 Add ability to run NVIDIA containers without the NVIDIA container toolkit 2024-03-14 19:23:34 +13:00
Josh.5
f17d31d077 Enable support for external NVIDIA GPUs 2024-03-14 18:47:08 +13:00
Josh.5
e701b8870f Describe how to install the NVIDIA container toolkit on Ubuntu server 2024-03-14 18:38:04 +13:00
alansari
bd73b199d4 Update sunshine again to latest stable 2024-03-05 23:17:46 +13:00
tem
12a498e1eb Make SID repo optional 2024-02-29 13:55:17 +13:00
tem
63cfefa1fc Bump sunshine to stable & include res script from lyzardbyte docs 2024-02-29 13:54:19 +13:00
alansari
c3941d1f0b Quick patch for v550+ drivers 2024-02-29 13:53:37 +13:00
Josh.5
6cc9f56155 Delete out-dated run script
Better to use compose only or properly document a run command for users
2023-10-05 09:34:34 +13:00
Josh.5
a17fe91113 Hide file copy log. No need for this to be verbose 2023-10-02 20:17:29 +13:00
Josh.5
a5f189dbc3 Update to the latest nightly sunshine 2023-10-02 20:15:02 +13:00
Josh.5
8f32302c0f Improvements to the init scripts 2023-10-02 19:43:50 +13:00
Josh.5
ca7521d765 Fix build and install mesa during container startup
This brings the Mesa and Vulkan installation in-line with the NVIDIA driver installation for NVIDIA GPU users.
2023-10-02 19:14:28 +13:00
Josh.5
c165e28f07 Add variable FORCE_X11_DUMMY_CONFIG for forcing the initial use of the dummy xorg config 2023-10-02 11:13:17 +13:00
Josh.5
7f04d8df01 Pull mesa from SID 2023-09-30 13:39:37 +13:00
Josh.5
f4cad0aab0 Update documentation with new deployment configuration 2023-09-30 10:40:32 +13:00
Josh.5
12cc16459a Reduce some of the excessive sleep times for various things 2023-09-29 23:39:26 +13:00
Josh.5
c651034d13 dumb-udev needs ENABLE_EVDEV_INPUTS enabled by default 2023-09-29 23:27:35 +13:00
Josh.5
93718e1855 Update to how we choose if we are running udevd or dumb-udev
This fixes some issues I found with startup.
2023-09-29 21:26:17 +13:00
Josh.5
5a1d20daf5 Install dumb-udev further down to optimise build caches 2023-09-29 20:34:42 +13:00
Josh.5
15512a485f Fix error in Dockerfile syntax 2023-09-29 20:26:17 +13:00
Josh.5
eeca08ce38 Add dumb-udev as a replacemet for 2023-09-29 20:20:21 +13:00
Josh.5
96d318ebd0 Fix issue for using the host udev in unprivileged mode 2023-09-27 17:04:51 +13:00
Josh.5
8b11bca749 Update web frontend 2023-09-22 15:16:07 +12:00
Josh.5
9d43f152b9 Add Python venv to base packages 2023-09-22 15:15:55 +12:00
Josh.5
0dd343aea9 Improvements to default modes for dummy display device 2023-09-20 17:52:28 +12:00
Josh.5
37f7280dba Move home directory config installation to desktop config init.d script 2023-09-19 15:59:35 +12:00
Josh.5
7552680a01 Add flatseal as a default app 2023-09-18 16:12:28 +12:00
Josh.5
9a460b27e6 Add some forced changes to the way the desktop looks 2023-09-18 01:49:39 +12:00
Josh.5
c452e67fd7 Configure Firfox as the default browser 2023-09-18 01:16:27 +12:00
Josh.5
22cf7e5980 Use custom fork of noVNC 2023-09-18 01:15:47 +12:00
Josh.5
20c6b515ed Ignore setting max_map_count when container is run unprivileged 2023-09-17 15:54:43 +12:00
Josh.5
ae88645245 Remove logout actions 2023-09-12 17:05:04 +12:00
Josh.5
868def8906 Remove desktop icons for a cleaner look 2023-09-12 17:02:34 +12:00
Josh.5
5cef857d34 Fix another issue with the resolution setting 2023-09-12 10:26:53 +12:00
Josh.5
b5cb3fb0db Further improvements to display setting scripts 2023-09-12 09:48:12 +12:00
Josh.5
3867701a6b Fix an error in checking for xrandr modes 2023-09-12 00:43:25 +12:00
Josh.5
35722dfa84 Add a fallback to a possible existing supported mode when auto switching refresh rates 2023-09-11 20:24:56 +12:00
Josh.5
acee2481c1 Add some missing XDG environment variables 2023-09-11 19:13:53 +12:00
Josh.5
cc8bc1b02d Add a symlink to /usr/bin/steam
This is needed by MoonDeck Buddy
2023-09-11 17:58:18 +12:00
Josh.5
cb751f5a80 Update the default Steam BP launch config for Sunshine 2023-09-11 13:14:23 +12:00
Josh.5
aa1edd48e0 Add support for running proper detached processes with sunshine-run
This allows things like Steam BP to run with sunshine-run which will auto set the resolution. And then still have sunshine-stop restore the original resolution.
2023-09-11 12:29:48 +12:00
Josh.5
771c47d602 Fix direct execution of AppImages
Fetch a list of all child PIDs before forwarding the termination signal.
Once the main process is terminated, forward that term signal to all found children also (if they are still running)
2023-09-11 12:21:23 +12:00
Josh.5
0981af0a17 Further imporvements to sunshine-run and its logging 2023-09-11 11:54:30 +12:00
Josh.5
608f772ccc Add support for automatic refresh rate switching in Sunshine/Moonlight 2023-09-10 19:40:00 +12:00
Josh.5
60fa2363eb Create some temp files to indicate that the container has executed the init scripts for the first time
This could be useful for the user scripts to read to know if this is the first time they are running on this container or if the container was just restarted
2023-09-09 20:50:29 +12:00
Josh.5
7513c19bfd Hide ImageMagic from menu 2023-09-09 20:42:53 +12:00
Josh.5
e4cf09dcb0 Add 7z to tools 2023-09-06 00:38:20 +12:00
Josh.5
3cce8f79f8 Improvements to NVIDIA Patch installation
The GitHub servers had a small outage today while I was working. This prevented the containers from being able to start.
This change allows for the patch to be re-used between container re-creations and also prevents the failure from stopping boot. If the patch fails to download or install, then it will continue with an unpatched driver.
2023-09-06 00:10:02 +12:00
Josh.5
90510bd8ea Add a WoL Manager service 2023-09-06 00:06:18 +12:00
Josh.5
c8d613da5b Install the NVIDIA patch on container restarts 2023-09-04 17:43:05 +12:00
Josh.5
63137d43ec Add imagemagick package 2023-09-04 17:26:03 +12:00
Josh.5
3faf8df134 Add missing xdg-utils package
This is required for better directory management when installing applications. We need its tools for installing icons etc.
2023-09-04 16:48:59 +12:00
Josh.5
c3480448ff Add a script to setup sysctl values 2023-09-01 17:07:18 +12:00
Josh.5
e0dc046470 Add NvFBC support for Sunshine 2023-09-01 10:06:52 +12:00
Josh.5
269e71a0db Create an empty sunshine_state.json file on first startup 2023-09-01 09:05:47 +12:00
Josh.5
97613b227f Run Sunshine as a service
Goodbye Flatpak Sunshine. Hello AppImage.
Until a deb package is available for Debian Bookworm, we can just run sunshine as an AppImage.
It is faster to startup and is a little less bloated.

The goal here is to run Sunshine as a service managed by supervisord so that it is kept running and is restarted automatically if stopped.
2023-08-29 18:02:03 +12:00
Josh Sunnex
39d4ce0a0c Merge pull request #82 from 21st-centuryman/Develop
Fix: syntax bug
2023-08-28 13:32:36 +12:00
Josh.5
b7bb479635 Fix up some of the default config for sunshine 2023-08-26 20:26:44 +12:00
Josh.5
b89e2f565d Prevent symlinks from being turned into files with sed in-place edit 2023-08-26 14:59:04 +12:00
Josh.5
1b7873833c Improvements to user script execution in entrypoint 2023-08-26 14:46:38 +12:00
Josh.5
890b9d22d2 Add some useful tools for monitoring hardware 2023-08-26 14:46:10 +12:00
Josh.5
2f118e4a51 Remove xvfb package 2023-08-26 14:45:06 +12:00
Josh.5
dd3f079d71 Add xmlstarlet for modifying XML config 2023-08-25 14:37:16 +12:00
21st
c925ff8c87 Fix: syntax bug 2023-08-23 18:11:26 +02:00
Josh.5
aea4d51159 Use dumb-init for sunshine-run wrapper 2023-08-23 16:57:40 +12:00
Josh.5
1454b704a2 Fix minimise windows script 2023-08-23 16:40:46 +12:00
Josh.5
d899ebd965 Add a tool for minimising all currently open windows 2023-08-23 16:28:54 +12:00
Josh.5
b51036a697 Add sunshin-run and -stop wrapper scripts
These can be used to manage starting and stopping processes that spawn children that otherwise would not be terminated when the moonlight session ends
2023-08-23 16:19:55 +12:00
Josh.5
8ad830d5e4 Hide xfce4-web-browser from menu 2023-08-23 16:02:16 +12:00
Josh.5
2c8f6150e9 Update features in readme 2023-08-22 20:05:23 +12:00
Josh.5
6be269a3bb Update the default steam bigpicture command for sunshine
we are not using flatpak steam any longer.
2023-08-22 20:05:23 +12:00
Josh.5
ee4fd33e72 Move app install scripts to /usr/bin 2023-08-22 20:05:23 +12:00
Josh.5
c671ba85cc Add a script to close all open windows
This can be called from Sunshine
2023-08-22 20:05:23 +12:00
Josh.5
4f94568262 Add missing font to Arch build 2023-08-22 20:05:23 +12:00
Josh.5
fed3000700 Run container unprivileged by default using a macvlan 2023-08-22 20:05:23 +12:00
Josh.5
c731e2e0a0 Run x11vnc as root inside the container 2023-08-22 20:05:23 +12:00
Josh.5
02a94566b2 Revert to starting steam from desktop autostart 2023-08-22 20:05:23 +12:00
Josh.5
5837843aa2 Disable Udev on unprivileged container 2023-08-22 20:05:23 +12:00
Josh.5
ac7dc533e7 Remove support for DinD 2023-08-22 20:05:23 +12:00
Josh Sunnex
577d0ef299 Merge pull request #79 from alansari/patch-steamdelay
If ENABLE_STEAM supervised; enable after desktop is loaded
2023-08-21 17:56:04 +12:00
Josh Sunnex
ca5821774b Merge pull request #78 from alansari/patch-legacynv
Apply EqualsDee's Fix for legacy Nvidia Drivers
2023-08-21 17:54:51 +12:00
Ali Ansari
edab557c20 If Steam supervisor is enabled, only enable after desktop is loaded 2023-08-15 07:55:34 +03:00
Ali Ansari
0414726448 Apply EqualsDee's Fix for legacy Nvidia Drivers 2023-08-14 08:03:15 +03:00
Josh Sunnex
d2b4d2cae7 Merge pull request #75 from alansari/dev-arch
Update arch just so it builds
2023-08-06 15:07:05 +12:00
Josh Sunnex
53af510b45 Merge pull request #73 from alansari/patch-appimage
Add libfuse2 as appimages are not built yet with libfuse3
2023-08-05 20:07:53 +12:00
Tem
cfeb39c268 Add libfuse2 as appimages are not built yet with libfuse3 2023-08-03 09:35:57 +03:00
Ali Ansari
6913938585 cleanup 2023-08-01 09:49:39 +03:00
Ali Ansari
9c3497d73a Adjust supervisor path 2023-08-01 09:42:19 +03:00
Ali Ansari
658b18a634 remove opencl-mesa 2023-08-01 09:25:44 +03:00
Tem
d386c282e6 Update Arch Dockerfile 2023-08-01 09:14:52 +03:00
Josh.5
af1c17fdfd Enable parsing STEAM_ARGS to the steam supervisor config 2023-07-21 11:08:43 +12:00
Josh.5
b75b496283 Tidy up the compose examples 2023-07-21 11:08:19 +12:00
Josh.5
659bde74f5 Revert to installing steam as a .deb package
Flatpak seems to complicate Steam's execution of Proton
2023-07-17 12:35:28 +12:00
Josh Sunnex
23c5df2996 Merge pull request #60 from tnielsen2/master
Add `/mnt/games` troubleshooting steps and steamapps folder creation init.d script
2023-07-12 23:54:18 +12:00
tnielsen2
9fe592672a Update disk error troubleshooting step 2023-07-11 11:55:23 -04:00
tnielsen2
932e15314a Add steamapps troubleshooting and autocreation script 2023-07-11 11:13:30 -04:00
Josh.5
3be80a920e Build both the debian and arch flavours of Steam Headless in CI 2023-07-10 20:33:16 +12:00
Josh.5
35de069bf1 Add the start of some troubleshooting docs 2023-07-10 19:30:35 +12:00
Josh.5
8da0bd023d Hacky fix for bwrap execution inside the Debian container running under the NVIDIA Docker runtime
Ref: https://github.com/flatpak/flatpak/wiki/User-namespace-requirements
2023-07-10 19:30:35 +12:00
Josh.5
26b775f66e Rebase debian build to Debian 12 (Bookworm) 2023-07-10 19:30:35 +12:00
Josh.5
555bd8991d Some more tweaks to the Arch build 2023-07-10 19:30:35 +12:00
Josh.5
42ebc826b8 Update Arch build with latest changes 2023-07-10 19:30:35 +12:00
Josh.5
0b600108f7 Add Sunshine to initial desktop apps 2023-07-09 13:25:38 +12:00
Josh.5
8d43f93b55 Ensure autostart path exists before creating a file for steam 2023-07-08 17:16:07 +12:00
Josh.5
f92fb55290 Replace previous auto-start script if it contains '/usr/games/steam' 2023-07-08 17:01:39 +12:00
Josh.5
417ab4488b Display the progress of desktop app installation before starting the desktop
This just prevents people from seeing a black screen for a long time and assuming something is going wrong.
This initial setup is installaing flatpaks to the mounted home directory. This will not need to happen on every container startup. So this black screen is only a problem on the first start. But this change at least gives people something to look at.

Closes #50
2023-07-08 16:04:38 +12:00
Josh.5
fc700e2200 Start using Flatpaks as the main install method for any desktop apps 2023-07-08 05:19:50 +12:00
Josh.5
df9423ccad Improvements to running Xorg with NVIDIA 2023-07-07 16:01:14 +12:00
Josh Sunnex
68244060ff Merge pull request #47 from sfxworks/master
k8s-inclusion
2023-07-04 07:35:50 +12:00
Samuel Walker
8c6051aec7 k8s-inclusion 2023-06-29 15:49:57 +00:00
78 changed files with 2787 additions and 1450 deletions

View File

@@ -1,8 +1,7 @@
---
name: Build and Deploy CI name: Build and Deploy CI
on: on:
workflow_dispatch:
push: push:
branches: ['dev-**', 'pr-**', staging, master] branches: ['dev-**', 'pr-**', staging, master]
tags: ['**'] tags: ['**']
@@ -13,61 +12,74 @@ on:
- cron: '30 2 * * 6' - cron: '30 2 * * 6'
jobs: jobs:
build_docker: build_docker:
name: Build Docker Image name: Build Docker Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
flavour: ['debian', 'arch']
steps: steps:
# Fetch shallow git repository # ---
- name: Checkout - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
# Use QEMU to build # ---
- name: Set up QEMU - name: Set up Docker Buildx
if: success() uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0
id: qemu
uses: docker/setup-qemu-action@v1
# Use docker buildx to build the docker image # ---
- name: Build the Docker image
uses: docker/setup-buildx-action@v1
if: success()
id: buildx
with:
version: latest
# Generate 'prepare' build arguments to be retrieved later on
- name: Prepare - name: Prepare
if: success() if: success()
id: prepare id: prepare
run: | run: |
echo "GITHUB_REF:${GITHUB_REF}" FLAVOUR=${{ matrix.flavour }}
echo "GITHUB_REPOSITORY:${GITHUB_REPOSITORY}" echo "FLAVOUR='${FLAVOUR}'"
DOCKER_IMAGE=docker.io/josh5/steam-headless echo "GITHUB_REF='${GITHUB_REF}'"
echo "GITHUB_REPOSITORY='${GITHUB_REPOSITORY}'"
VERSION_TAG=${GITHUB_REF#refs/*/} 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="" DOCKER_TAGS=""
if [[ ${VERSION_TAG%/merge} == 'master' ]]; then if [[ ${GITHUB_REF} == refs/heads/master ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest," if [[ ${FLAVOUR} == 'debian' ]]; then
elif [[ ${VERSION_TAG%/merge} == 'staging' ]]; then DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:latest,${GHCR_IMAGE}:latest,${GHCR_IMAGE}:stable,"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:staging,"
elif [[ ${VERSION_TAG%/merge} =~ "dev-"* ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION_TAG%/merge},"
fi 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/} VERSION=${GITHUB_REF#refs/tags/}
if [[ ${VERSION} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}[-\w]*$ ]]; then if [[ ${VERSION} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}[-\w]*$ ]]; then
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:${VERSION}," DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:${FLAVOUR}-${VERSION},${GHCR_IMAGE}:${FLAVOUR}-${VERSION},"
DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_IMAGE}:latest," if [[ ${FLAVOUR} == 'debian' ]]; then
fi DOCKER_TAGS="${DOCKER_TAGS}${DOCKER_HUB_IMAGE}:latest,${GHCR_IMAGE}:latest,"
fi fi
echo "Build: [$(date +"%F %T")] [${GITHUB_REF_NAME}] [${GITHUB_SHA}]" > ./overlay/version.txt 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" DOCKER_PUSH="true"
if [[ ${DOCKER_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then if [[ ${DOCKER_HUB_IMAGE} != 'docker.io/josh5/steam-headless' ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
if [[ ${VERSION_TAG%/merge} =~ "pr-"* ]]; then if [[ ${VERSION_TAG%/merge} =~ "pr-"* ]]; then
@@ -76,53 +88,83 @@ jobs:
if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then if [[ ${VERSION_TAG%/merge} =~ ^[0-9]+$ ]]; then
DOCKER_PUSH="false" DOCKER_PUSH="false"
fi fi
if [[ "X${DOCKER_TAGS}" == "X" ]]; then
DOCKER_PUSH="false"
fi
echo "DOCKER_PUSH='${DOCKER_PUSH}'"
cat ./overlay/version.txt
echo ::set-output name=docker_image::${DOCKER_IMAGE} echo "docker_hub_image:${DOCKER_HUB_IMAGE:?}"
echo ::set-output name=docker_tags::$(echo ${DOCKER_TAGS} | sed 's/,$//') echo "docker_hub_image=${DOCKER_HUB_IMAGE:?}" >> $GITHUB_OUTPUT
echo ::set-output name=docker_platforms::linux/amd64
echo ::set-output name=docker_push::${DOCKER_PUSH}
# Cache the build echo "ghcr_image:${GHCR_IMAGE:?}"
- name: Cache Docker layers echo "ghcr_image=${GHCR_IMAGE:?}" >> $GITHUB_OUTPUT
uses: actions/cache@v2
id: cache 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
# ---
- name: Log into GHCR registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with: with:
path: /tmp/.buildx-cache registry: ghcr.io
key: ${{ runner.os }}-buildx-${{ github.sha }} username: ${{ github.actor }}
restore-keys: | password: ${{ secrets.GITHUB_TOKEN }}
${{ runner.os }}-buildx-
# 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/')) 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: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
# Run docker build and push # ---
- name: Docker Build and Push - name: Docker meta
if: success() 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: with:
context: . context: .
file: Dockerfile file: Dockerfile.${{ matrix.flavour }}
pull: true
platforms: ${{ steps.prepare.outputs.docker_platforms }} platforms: ${{ steps.prepare.outputs.docker_platforms }}
pull: 'true'
push: ${{ steps.prepare.outputs.docker_push }} push: ${{ steps.prepare.outputs.docker_push }}
tags: | tags: |
${{ steps.prepare.outputs.docker_tags }} ${{ steps.prepare.outputs.docker_tags }}
cache-from: type=local,src=/tmp/.buildx-cache labels: |
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ steps.prepare.outputs.service_name }}-${{ matrix.flavour }}-main
# Keep only latest cache cache-to: type=gha,scope=${{ steps.prepare.outputs.service_name }}-${{ matrix.flavour }}-main,mode=max
# 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

View File

@@ -34,6 +34,8 @@ RUN \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
@@ -41,21 +43,34 @@ RUN \
RUN \ RUN \
echo "**** Install tools ****" \ echo "**** Install tools ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
base-devel \
bash \ bash \
bash-completion \ bash-completion \
curl \ curl \
docbook-xml \
docbook-xsl \
fakeroot \
p7zip \
patch \
git \ git \
jq \
less \ less \
locate \
man-db \ man-db \
nano \ nano \
net-tools \ net-tools \
pciutils \
pkg-config \ pkg-config \
procps \
psmisc \
psutils \
rsync \ rsync \
screen \ screen \
sudo \ sudo \
unzip \ unzip \
vim \ vim \
wget \ wget \
xmlstarlet \
xz \ xz \
&& \ && \
echo "**** Install python ****" \ echo "**** Install python ****" \
@@ -67,6 +82,44 @@ RUN \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \
echo
# Configure default user and set user env
ENV \
PUID=99 \
PGID=100 \
UMASK=000 \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \
&& \
echo
# Install yay
RUN \
echo "**** Install Yay ****" \
&& pacman -Sy \
&& su - default -c 'git clone https://aur.archlinux.org/yay.git /tmp/yay && cd /tmp/yay && makepkg --noconfirm --syncdeps --install' \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \ && \
echo echo
@@ -78,48 +131,38 @@ RUN \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# XFS requirements # Install mscorefonts
RUN \ RUN \
echo "**** Install XFS requirements ****" \ echo "**** Install ms fonts ****" \
&& pacman -Syu --noconfirm --needed \ && su - default -c "yay -Syu --noconfirm --needed ttf-msfonts" \
xfsdump \
xfsprogs \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& \
echo
# Install mesa requirements
RUN \
echo "**** Install mesa and vulkan requirements ****" \
&& pacman -Syu --noconfirm --needed \
glu \
libva-mesa-driver \
mesa-utils \
mesa-vdpau \
opencl-mesa \
pciutils \
vulkan-mesa-layers \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \ && \
echo echo
# Install X Server requirements # Install X Server requirements
# TODO: Remove doubles ENV \
# TODO: Things that are not required XORG_SOCKET_DIR="/tmp/.X11-unix" \
XDG_RUNTIME_DIR="/tmp/.X11-unix/run" \
XDG_SESSION_TYPE="x11" \
FORCE_X11_DUMMY_CONFIG="false"
RUN \ RUN \
echo "**** Install X Server requirements ****" \ echo "**** Install X Server requirements ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
avahi \ avahi \
dbus \ dbus \
lib32-fontconfig \ lib32-fontconfig \
ttf-liberation \ fuse2 \
x11vnc \ x11vnc \
xorg \ xorg \
xorg-apps \ xorg-apps \
@@ -139,94 +182,115 @@ RUN \
xorg-xrandr \ xorg-xrandr \
xorg-xsetroot \ xorg-xsetroot \
xorg-xwininfo \ xorg-xwininfo \
xf86-input-evdev \
xterm \
gamescope \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# pacman -Syu --noconfirm --needed \
# xorg-server \
# xorg-server-xephyr \
# xorg-xwininfo \
# xorg-xhost \
# xorg-xinit \
# xorg-xinput \
# xorg-xrandr \
# xorg-xprop \
# xorg-xkill \
# xorg-xbacklight \
# xorg-xsetroot
# s
# pacman -Syu --noconfirm --needed autorandr xdg-desktop-portal xdg-desktop-portal-gtk wmctrl xbindkeys xdotool xautolock
#
#
# pacman -Syu --noconfirm --needed gestures
# pacman -Syu --noconfirm --needed numlockx
#
# echo 'Server = https://mirror.fsmg.org.nz/archlinux/$repo/os/$arch' >> /etc/pacman.d/mirrorlist
#
# Server = https://mirror.pkgbuild.com/$repo/os/$arch
# Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
# Server = https://mirror.leaseweb.net/archlinux/$repo/os/$arch
# Install audio requirements # Install audio requirements
ENV \
PULSE_SOCKET_DIR="/tmp/pulse" \
PULSE_SERVER="unix:/tmp/pulse/pulse-socket"
RUN \ RUN \
echo "**** Install X Server requirements ****" \ echo "**** Install X Server requirements ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
alsa-utils \
pavucontrol \
pulseaudio \ pulseaudio \
pulseaudio-alsa \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# Install openssh server # Install desktop environment
# TODO: Install equivelent of 'msttcorefonts' and 'fonts-vlgothic'
RUN \ RUN \
echo "**** Install openssh server ****" \ echo "**** Install desktop environment ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
openssh \ gedit \
&& echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config \ xfce4 \
xfce4-goodies \
xfce4-terminal \
ttf-liberation \
xdg-user-dirs \
xdg-utils \
imagemagick \
&& \
echo "**** Install WoL Manager requirements ****" \
&& pacman -Syu --noconfirm --needed \
tcpdump \
xprintidle \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# Install noVNC # Add support for flatpaks
# TODO: Add nginx ENV \
ARG NOVNC_VERSION=1.2.0 XDG_DATA_DIRS="/home/default/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/"
RUN \ RUN \
echo "**** Fetch noVNC ****" \ echo "**** Install flatpak support ****" \
&& cd /tmp \ && pacman -Syu --noconfirm --needed \
&& wget -O /tmp/novnc.tar.gz https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.tar.gz \ flatpak \
xdg-desktop-portal-gtk \
gnome-software \
&& \ && \
echo "**** Extract noVNC ****" \ echo "**** Configure flatpak ****" \
&& cd /tmp \ && chmod u-s /usr/bin/bwrap \
&& tar -xvf /tmp/novnc.tar.gz \ && 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 "**** Configure noVNC ****" \
&& cd /tmp/noVNC-${NOVNC_VERSION} \
&& sed -i 's/credentials: { password: password } });/credentials: { password: password },\n wsProtocols: ["'"binary"'"] });/g' app/ui.js \
&& mkdir -p /opt \
&& rm -rf /opt/noVNC \
&& cd /opt \
&& mv -f /tmp/noVNC-${NOVNC_VERSION} /opt/noVNC \
&& cd /opt/noVNC \
&& ln -s vnc.html index.html \
&& chmod -R 755 /opt/noVNC \
&& \
echo "**** Modify noVNC title ****" \
&& sed -i '/ document.title =/c\ document.title = "Steam Headless - noVNC";' \
/opt/noVNC/app/ui.js \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& rm -rf \ && pacman -Scc --noconfirm \
/tmp/noVNC* \ && rm -fr /var/lib/pacman/sync/* \
/tmp/novnc.tar.gz && rm -fr /var/cache/pacman/pkg/* \
&& \
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 FRONTEND_VERSION=a8eb92f
RUN \
echo "**** Fetch Web Frontend ****" \
&& mkdir -p /opt \
&& cd /opt \
&& rm -rf /opt/frontend \
&& git clone https://github.com/Steam-Headless/frontend.git --branch master /opt/frontend \
&& cd /opt/frontend \
&& git checkout ${FRONTEND_VERSION} 2> /dev/null \
&& git submodule init \
&& git submodule update --depth 1 --recursive \
&& rm -rf /opt/frontend/.git \
&& \
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 ****" \
&& rm -f /tmp/steam-headless.png
# Install Websockify # Install Websockify
ARG WEBSOCKETIFY_VERSION=0.10.0 ARG WEBSOCKETIFY_VERSION=0.11.0
RUN \ RUN \
echo "**** Fetch Websockify ****" \ echo "**** Fetch Websockify ****" \
&& cd /tmp \ && cd /tmp \
@@ -242,180 +306,201 @@ RUN \
&& \ && \
echo "**** Install Websockify to noVNC path ****" \ echo "**** Install Websockify to noVNC path ****" \
&& cd /tmp \ && cd /tmp \
&& mkdir -p /opt/noVNC/utils \
&& mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \ && mv -v /tmp/websockify-${WEBSOCKETIFY_VERSION} /opt/noVNC/utils/websockify \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& rm -rf \ && rm -rf \
/tmp/websockify-* \ /tmp/websockify-* \
/tmp/websockify.tar.gz /tmp/websockify.tar.gz \
&& \
echo
# Install firefox # Setup browser audio streaming deps
# TODO: MOve under de
RUN \ RUN \
echo "**** Install firefox ****" \ echo "**** Install audio streaming deps ****" \
&& pacman -Syu --noconfirm --needed \
bzip2 \
gst-libav \
gst-plugins-bad \
gst-plugins-base \
gst-plugins-good \
gst-plugins-ugly \
&& \
#echo "**** Fetch ucspi-tcp ****" \
# && mkdir -p /tmp/ucspi-tcp-0.88 \
# && cd /tmp \
# #&& wget -O /tmp/ucspi-tcp.tar.gz https://github.com/trafficgate/ucspi-tcp/archive/refs/heads/master.tar.gz \
# && wget -O /tmp/ucspi-tcp.tar.gz http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz \
# && cd /tmp/ucspi-tcp-0.88 \
# && tar -xvf /tmp/ucspi-tcp.tar.gz --strip-components=1 \
#&& \
#echo "**** Build and install ucspi-tcp ****" \
# && wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.errno.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.errno.patch \
# && wget -O /tmp/ucspi-tcp-0.88/ucspi-tcp-0.88.a_record.patch https://git.alpinelinux.org/aports/plain/testing/ucspi-tcp/ucspi-tcp-0.88.a_record.patch \
# && patch -p1 --input=ucspi-tcp-0.88.errno.patch \
# && patch -p1 --input=ucspi-tcp-0.88.a_record.patch \
# && sed -i 's|^/usr/local|/usr|' /tmp/ucspi-tcp-0.88/conf-home \
# && make \
# && for f in tcpserver tcprules tcprulescheck argv0 recordio tcpclient *\@ tcpcat mconnect mconnect-io addcr delcr fixcrio rblsmtpd; do \
# cp $f /usr/bin/$f; \
# done \
#&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \
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 -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 \ && pacman -Syu --noconfirm --needed \
firefox \ firefox \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# # Install Steam # Install Steam
# RUN \
# echo "**** Install steam ****" \
# && pacman -Syu --noconfirm --needed \
# lib32-vulkan-icd-loader
# steam \
# vulkan-icd-loader \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# Install desktop environment
RUN \ RUN \
echo "**** Install desktop environment ****" \ echo "**** Install Steam ****" \
&& pacman -Syu --noconfirm --needed \ && pacman -Syu --noconfirm --needed \
gedit \ steam \
xfce4 \
xfce4-terminal \
&& \ && \
echo "**** Section cleanup ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& \ && \
echo echo
# Various other tools
# Add support for flatpaks ARG DUMB_INIT_VERSION=1.2.5
ARG DUMB_UDEV_VERSION=64d1427
RUN \ RUN \
echo "**** Install flatpak support ****" \ echo "**** Install dumb-init ****" \
&& pacman -Syu --noconfirm --needed \ && wget --no-check-certificate --no-cookies --quiet \
flatpak \ -O /usr/bin/dumb-init \
xdg-desktop-portal-gtk \ 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 ****" \ echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \ && pacman -Scc --noconfirm \
&& rm -fr /home/default/.cache/yay \
&& rm -fr /var/lib/pacman/sync/* \
&& rm -fr /var/cache/pacman/pkg/* \
&& rm -rf /tmp/yay* \
&& \ && \
echo echo
# TODO Append to tools
RUN \
echo "**** Install flatpak support ****" \
&& pacman -Syu --noconfirm --needed \
patch \
&& \
echo "**** Section cleanup ****" \
&& pacman -Scc --noconfirm \
&& \
echo
# # Install desktop environment
# RUN \
# echo "**** Install desktop environment ****" \
# && pacman -Syu --noconfirm --needed \
# kde-system-meta \
# konsole \
# plasma-desktop \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# # Install desktop environment
# RUN \
# echo "**** Install desktop environment ****" \
# && pacman -Syu --noconfirm --needed \
# cinnamon \
# polkit-gnome \
# gnome-terminal \
# && \
# echo "**** Section cleanup ****" \
# && pacman -Scc --noconfirm \
# && \
# echo
# # Setup browser audio streaming deps
# RUN \
# echo "**** Update apt database ****" \
# && apt-get update \
# && \
# echo "**** Install audio streaming deps ****" \
# && apt-get install -y --no-install-recommends \
# bzip2 \
# gstreamer1.0-alsa \
# gstreamer1.0-gl \
# gstreamer1.0-gtk3 \
# gstreamer1.0-libav \
# gstreamer1.0-plugins-base \
# gstreamer1.0-plugins-good \
# gstreamer1.0-pulseaudio \
# gstreamer1.0-qt5 \
# gstreamer1.0-tools \
# gstreamer1.0-x \
# libgstreamer1.0-0 \
# libncursesw5 \
# libopenal1 \
# libsdl-image1.2 \
# libsdl-ttf2.0-0 \
# libsdl1.2debian \
# libsndfile1 \
# ucspi-tcp \
# && \
# echo "**** Section cleanup ****" \
# && apt-get clean autoclean -y \
# && apt-get autoremove -y \
# && rm -rf \
# /var/lib/apt/lists/* \
# /var/tmp/* \
# /tmp/* \
# && \
# echo
# Configure default user and set env
ENV \
USER="default" \
USER_PASSWORD="password" \
USER_HOME="/home/default" \
TZ="Pacific/Auckland" \
USER_LOCALES="en_US.UTF-8 UTF-8"
RUN \
echo "**** Configure default user '${USER}' ****" \
&& mkdir -p \
${USER_HOME} \
&& useradd -d ${USER_HOME} -s /bin/bash ${USER} \
&& chown -R ${USER} \
${USER_HOME} \
&& echo "${USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# Add FS overlay # Add FS overlay
COPY overlay / COPY overlay /
# Tweaks as flatpak issue isn't sorted
RUN \
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
# Set display environment variables # Set display environment variables
ENV \ ENV \
DISPLAY_CDEPTH="24" \ DISPLAY_CDEPTH="24" \
DISPLAY_REFRESH="60" \ DISPLAY_REFRESH="120" \
DISPLAY_SIZEH="900" \ DISPLAY_SIZEH="900" \
DISPLAY_SIZEW="1600" \ DISPLAY_SIZEW="1600" \
DISPLAY_VIDEO_PORT="DFP" \ DISPLAY_VIDEO_PORT="DFP" \
DISPLAY=":55" \ DISPLAY=":55"
ENV \
NVIDIA_DRIVER_CAPABILITIES="all" \ NVIDIA_DRIVER_CAPABILITIES="all" \
NVIDIA_VISIBLE_DEVICES="all" NVIDIA_VISIBLE_DEVICES="all"
# Set container configuration environment variables # Set container configuration environment variables
# APPIMAGE_EXTRACT_AND_RUN="0"
ENV \ ENV \
MODE="primary" \ MODE="primary" \
ENABLE_VNC_AUDIO="true" WEB_UI_MODE="vnc" \
ENABLE_VNC_AUDIO="true" \
NEKO_PASSWORD=neko \
NEKO_PASSWORD_ADMIN=admin \
ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \
ENABLE_SUNSHINE="true" \
ENABLE_EVDEV_INPUTS="true" \
ENABLE_WOL_POWER_MANAGER="false"
# Configure required ports # Configure required ports
ENV \ ENV \
PORT_SSH="" \ PORT_NOVNC_WEB="8083" \
PORT_NOVNC_WEB="8083" NEKO_NAT1TO1=""
# Expose the required ports # Expose the required ports
EXPOSE 8083 EXPOSE 8083

View File

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

View File

@@ -2,14 +2,22 @@
![](./images/banner.jpg) ![](./images/banner.jpg)
Play your games in the browser with audio. Connect another device and use it with Steam Remote Play. Easily deploy a Steam Docker instance in seconds. Remote Game Streaming Server.
Play your games either in the browser with audio or via Steam Link or Moonlight. Play from another Steam Client with Steam Remote Play.
Easily deploy a Steam Docker instance in seconds.
## Features: ## Features:
- NVIDIA GPU support - Steam Client configured for running on Linux with Proton
- AMD GPU support - Moonlight compatible server for easy remote desktop streaming
- Easy installation of EmeDeck, Heroic and Lutris via Flatpak
- Full video/audio noVNC web access to a Xfce4 Desktop - Full video/audio noVNC web access to a Xfce4 Desktop
- NVIDIA, AMD and Intel GPU support
- Full controller support
- Support for Flatpak and Appimage installation
- Root access - Root access
- Based on Debian Bookworm
--- ---
## Notes: ## Notes:
@@ -18,6 +26,8 @@ Play your games in the browser with audio. Connect another device and use it wit
If you wish to install additional applications, you can generate a script inside the `~/init.d` directory ending with ".sh". If you wish to install additional applications, you can generate a script inside the `~/init.d` directory ending with ".sh".
This will be executed on the container startup. This will be executed on the container startup.
Also, you can install applications using the WebUI under **Applications > System > Software**. There you can install other game launchers like Lutris, Heroic or EmuDeck.
### STORAGE PATHS: ### STORAGE PATHS:
Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified. Everything that you wish to save in this container should be stored in the home directory or a docker container mount that you have specified.
All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template. All files that are store outside your home directory are not persistent and will be wiped if there is an update of the container or you change something in the template.

View File

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

View File

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

View File

@@ -0,0 +1,76 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
## NOTE: This config uses privileged to access to host to be able to access the required devices
privileged: true
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
# NETWORK:
## NOTE: With this configuration, if we do not use the host network, then physical device input
## is not possible and your USB connected controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# ENVIRONMENT:
## Read all config variables from the .env file
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro

View File

@@ -0,0 +1,92 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
cap_add:
- NET_ADMIN
- SYS_ADMIN
- SYS_NICE
security_opt:
- seccomp:unconfined
- apparmor:unconfined
# NETWORK:
## NOTE: With this configuration, if we do not use the host network, then physical device input
## is not possible and your USB connected controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# ENVIRONMENT:
## Read all config variables from the .env file
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# DEVICES:
devices:
# Use the host fuse device [REQUIRED].
- /dev/fuse
# Add the host uinput device [REQUIRED].
- /dev/uinput
# Add AMD/Intel HW accelerated video encoding/decoding devices [REQUIRED].
# NOTE: See documentation for determining which devices to configure here if you have multiple GPUs
- /dev/dri/card1
- /dev/dri/renderD128
# Ensure container access to devices 13:*
device_cgroup_rules:
- 'c 13:* rmw'
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

View File

@@ -1,50 +0,0 @@
---
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
runtime: ${DOCKER_RUNTIME}
## NOTE: Requires privileged access to host to be able to access the required devices
privileged: true
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
# NETWORK:
## NOTE: Steam headless always requires the use of the host network.
## If we do not use the host network, then device input is not possible
## and your controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# 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
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro
# The Xorg socket. This will be shared with other containers so they can access the X server.
- /opt/container-data/steam-headless/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket. This will be shared with other containers so they can access the audio sink.
- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
# Store dind var files in a volume
- steam-headless-var-lib-docker:/var/lib/docker/:rw
# Store flatpak var files in a volume
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
volumes:
steam-headless-var-lib-docker:
steam-headless-var-lib-flatpak:

View File

@@ -0,0 +1,79 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
## NOTE: This config uses privileged to access to host to be able to access the required devices
privileged: true
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
# GPU PASSTHROUGH
runtime: nvidia
# NETWORK:
## NOTE: With this configuration, if we do not use the host network, then physical device input
## is not possible and your USB connected controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# ENVIRONMENT:
## Read all config variables from the .env file
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro

View File

@@ -0,0 +1,101 @@
---
version: "3.8"
services:
steam-headless:
image: josh5/steam-headless:latest
restart: unless-stopped
shm_size: ${SHM_SIZE}
ipc: host # Could also be set to 'shareable'
ulimits:
nofile:
soft: 1024
hard: 524288
cap_add:
- NET_ADMIN
- SYS_ADMIN
- SYS_NICE
security_opt:
- seccomp:unconfined
- apparmor:unconfined
# GPU PASSTHROUGH
runtime: nvidia
# NETWORK:
## NOTE: With this configuration, if we do not use the host network, then physical device input
## is not possible and your USB connected controllers will not work in steam games.
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
# ENVIRONMENT:
## Read all config variables from the .env file
environment:
# System
- TZ=${TZ}
- USER_LOCALES=${USER_LOCALES}
- DISPLAY=${DISPLAY}
# User
- PUID=${PUID}
- PGID=${PGID}
- UMASK=${UMASK}
- USER_PASSWORD=${USER_PASSWORD}
# Mode
- MODE=${MODE}
# Web UI
- WEB_UI_MODE=${WEB_UI_MODE}
- ENABLE_VNC_AUDIO=${ENABLE_VNC_AUDIO}
- PORT_NOVNC_WEB=${PORT_NOVNC_WEB}
- NEKO_NAT1TO1=${NEKO_NAT1TO1}
# Steam
- ENABLE_STEAM=${ENABLE_STEAM}
- STEAM_ARGS=${STEAM_ARGS}
# Sunshine
- ENABLE_SUNSHINE=${ENABLE_SUNSHINE}
- SUNSHINE_USER=${SUNSHINE_USER}
- SUNSHINE_PASS=${SUNSHINE_PASS}
# Xorg
- ENABLE_EVDEV_INPUTS=${ENABLE_EVDEV_INPUTS}
- FORCE_X11_DUMMY_CONFIG=${FORCE_X11_DUMMY_CONFIG}
# Nvidia specific config
- NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES}
- NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES}
- NVIDIA_DRIVER_VERSION=${NVIDIA_DRIVER_VERSION}
# DEVICES:
devices:
# Use the host fuse device [REQUIRED].
- /dev/fuse
# Add the host uinput device [REQUIRED].
- /dev/uinput
# Add NVIDIA HW accelerated devices [OPTIONAL].
# NOTE: If you use the nvidia container toolkit, this is not needed.
# Installing the nvidia container toolkit is the recommended method for running this container
#- /dev/nvidia0
#- /dev/nvidiactl
#- /dev/nvidia-modeset
#- /dev/nvidia-uvm
#- /dev/nvidia-uvm-tools
#- /dev/nvidia-caps/nvidia-cap1
#- /dev/nvidia-caps/nvidia-cap2
# Ensure container access to devices 13:*
device_cgroup_rules:
- 'c 13:* rmw'
# VOLUMES:
volumes:
# The location of your home directory.
- ${HOME_DIR}/:/home/default/:rw
# The location where all games should be installed.
# This path needs to be set as a library path in Steam after logging in.
# Otherwise, Steam will store games in the home directory above.
- ${GAMES_DIR}/:/mnt/games/:rw
# The Xorg socket.
- ${SHARED_SOCKETS_DIR}/.X11-unix/:/tmp/.X11-unix/:rw
# Pulse audio socket.
- ${SHARED_SOCKETS_DIR}/pulse/:/tmp/pulse/:rw

View File

@@ -9,7 +9,7 @@ Follow these instructions to configure a docker-compose.yml for your system.
> Depending on how you have installed this, the commands to execute docker compose may vary. > Depending on how you have installed this, the commands to execute docker compose may vary.
## PREPARE DIRECTORY: ## PREPARE DIRECTORIES:
> __Warning__ > __Warning__
> >
@@ -18,24 +18,78 @@ Follow these instructions to configure a docker-compose.yml for your system.
> If you do run these commands as root, you may need to manually fix the permissions and ownership after. > If you do run these commands as root, you may need to manually fix the permissions and ownership after.
Create a directory for your service: Create a directory for your service:
``` ```shell
sudo mkdir -p /opt/container-services/steam-headless sudo mkdir -p /opt/container-services/steam-headless
sudo chown -R $(id -u):$(id -g) /opt/container-services/steam-headless sudo chown -R $(id -u):$(id -g) /opt/container-services/steam-headless
``` ```
Create a directory for your service config data: Create a directory for your service config data:
``` ```shell
sudo mkdir -p /opt/container-data/steam-headless/{home,.X11-unix,pulse} sudo mkdir -p /opt/container-data/steam-headless/{home,.X11-unix,pulse}
sudo chown -R $(id -u):$(id -g) /opt/container-data/steam-headless sudo chown -R $(id -u):$(id -g) /opt/container-data/steam-headless
``` ```
(Optional) Create a directory for your game install location:
```shell
sudo mkdir /mnt/games
sudo chmod -R 777 /mnt/games
sudo chown -R $(id -u):$(id -g) /mnt/games
```
Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file. Create a Steam Headless `/opt/container-services/steam-headless/docker-compose.yml` file.
Populate this file with the contents of the default [Docker Compose File](./compose-files/docker-compose.default.yml). Populate this file with the contents of the default Docker Compose File
### AMD/Intel:
- [AMD and Intel GPUs](./compose-files/docker-compose.amd+intel.yml).
- [Privileged AMD and Intel GPUs Docker Compose Template](./compose-files/docker-compose.amd+intel.privileged.yml) (grants full access to host devices).
#### Multipl AMD or Intel GPUs
If you have multiple AMD or Intel GPUs and you wish to isolate them, then follow these steps to determine the card to passthrough in the docker compose file. This requires that you do not use the privileged compose template.
1) List the PCI devices and get their IDs `lspci | grep -E 'VGA|3D'`
```
00:02.0 VGA compatible controller: Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics] (rev 01)
06:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Cezanne [Radeon Vega Series / Radeon Vega Mobile Series] (rev c6)
```
In this example, the Intel GPU has an ID of `00:02.0` and the AMD GPU has an ID of `06:00.0`.
2) Discover which `/dev/dri/card*` and `/dev/dri/renderD12*` references the `00:02.0` Intel GPU (or whatever your output was). To do this, run the commands `ls -la /sys/class/drm/card*` and `ls -l /sys/class/drm/renderD*`.
```
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-1 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-1
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-2 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-2
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-3 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-3
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/card1-DP-4 -> ../../devices/pci0000:00/0000:00:02.0/drm/card1/card1-DP-4
```
```
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/renderD128 -> ../../devices/pci0000:00/0000:00:02.0/drm/renderD128
lrwxrwxrwx. 1 root root 0 May 8 15:44 /sys/class/drm/renderD129 -> ../../devices/pci0000:00/0000:06:00.0/drm/renderD129
```
From this example output we can see that the Intel GPU is `/dev/dri/card1` and `/dev/dri/renderD128`.
### NVIDIA:
- [NVIDIA GPUs Docker Compose Template](./compose-files/docker-compose.nvidia.yml).
- [Privileged NVIDIA GPUs Docker Compose Template](./compose-files/docker-compose.nvidia.yml) (grants full access to host devices).
## CONFIGURE ENV: ## CONFIGURE ENV:
Create a Steam Headless `/opt/container-services/steam-headless/.env` file with the contents found in this example [Environment File](./compose-files/.env). Create a Steam Headless `/opt/container-services/steam-headless/.env` file with the contents found in this example [Environment File](./compose-files/.env).
Edit these variables as required. Edit these variables as required.
## EXECUTE:
Navigate to your compose location and execute it.
```shell
cd /opt/container-services/steam-headless
sudo docker-compose up -d --force-recreate
```
After container executes successfully, navigate to your docker host URL in your browser on port 8083 and click connect.
`http://<host-ip>:8083/`
![img.png](./images/web_connect.png)
## Troubleshooting
[Troubleshooting Docs](./troubleshooting.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/images/web_connect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

25
docs/k8s-files/pvc.yaml Normal file
View File

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

View File

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

16
docs/k8s.md Normal file
View File

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

30
docs/troubleshooting.md Normal file
View File

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

View File

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

View File

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

View File

@@ -5,8 +5,8 @@
# File Created: Friday, 12th January 2022 8:54:01 am # File Created: Friday, 12th January 2022 8:54:01 am
# Author: Josh.5 (jsunnex@gmail.com) # Author: Josh.5 (jsunnex@gmail.com)
# ----- # -----
# Last Modified: Tuesday, 4th October 2022 11:27:10 am # Last Modified: Monday, 10th July 2023 5:56:17 pm
# Modified By: Josh.5 (jsunnex@gmail.com) # Modified By: Console and webGui login account (jsunnex@gmail.com)
### ###
PUID=${PUID:-99} PUID=${PUID:-99}
@@ -14,18 +14,21 @@ PGID=${PGID:-100}
UMASK=${UMASK:-000} UMASK=${UMASK:-000}
USER_PASSWORD=${USER_PASSWORD:-password} USER_PASSWORD=${USER_PASSWORD:-password}
echo "**** Configure default user ****" print_header "Configure default user"
echo "Setting default user uid=${PUID}(${USER}) gid=${PGID}(${USER})" print_step_header "Setting default user uid=${PUID}(${USER}) gid=${PGID}(${USER})"
usermod -o -u "${PUID}" ${USER} usermod -o -u "${PUID}" ${USER}
groupmod -o -g "${PGID}" ${USER} groupmod -o -g "${PGID}" ${USER}
echo "Adding default user to video, audio, input and pulse groups" print_step_header "Adding default user to any additional required device groups"
usermod -a -G video,audio,input,pulse ${USER} additional_groups=( video audio input pulse )
for group_name in "${additional_groups[@]}"; do
if [ $(getent group ${group_name:?}) ]; then
echo "Adding default user to any additional required device groups" print_step_header "Adding user '${USER}' to group: '${group_name}'"
usermod -aG ${group_name:?} ${USER}
fi
done
device_nodes=( /dev/uinput /dev/input/event* /dev/dri/* ) device_nodes=( /dev/uinput /dev/input/event* /dev/dri/* )
added_groups="" added_groups=""
for dev in "${device_nodes[@]}"; do for dev in "${device_nodes[@]}"; do
@@ -51,20 +54,20 @@ for dev in "${device_nodes[@]}"; do
# Add group to user # Add group to user
if [[ "${added_groups}" != *"${dev_group}"* ]]; then if [[ "${added_groups}" != *"${dev_group}"* ]]; then
echo "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}" print_step_header "Adding user '${USER}' to group: '${dev_group}' for device: ${dev}"
usermod -a -G ${dev_group} ${USER} usermod -aG ${dev_group} ${USER}
added_groups=" ${added_groups} ${dev_group} " added_groups=" ${added_groups} ${dev_group} "
fi fi
done done
echo "Setting umask to ${UMASK}"; print_step_header "Setting umask to ${UMASK}";
umask ${UMASK} umask ${UMASK}
# TODO: Move this to its own 'display' init script. It does not really belong here # TODO: Move this to its own 'display' init script. It does not really belong here
# Configure the 'XDG_RUNTIME_DIR' path # Configure the 'XDG_RUNTIME_DIR' path
echo "Create the user XDG_RUNTIME_DIR path '${XDG_RUNTIME_DIR}'" print_step_header "Create the user XDG_RUNTIME_DIR path '${XDG_RUNTIME_DIR}'"
mkdir -p ${XDG_RUNTIME_DIR} mkdir -p ${XDG_RUNTIME_DIR}
# Ensure it is owned by the 'default' user # Ensure it is owned by the 'default' user
chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR} chown -R ${PUID}:${PGID} ${XDG_RUNTIME_DIR}
@@ -76,27 +79,20 @@ ln -sf /usr/share/backgrounds/steam.jpg /etc/alternatives/desktop-background
chmod a+r /etc/alternatives/desktop-background chmod a+r /etc/alternatives/desktop-background
# Setup home directory and permissions
echo "Adding default home directory template"
mkdir -p ${USER_HOME}
chown -R ${PUID}:${PGID} /etc/home_directory_template
rsync -aq --ignore-existing /etc/home_directory_template/ ${USER_HOME}/
# Setup services log path # Setup services log path
echo "Setting ownership of all log files in '${USER_HOME}/.cache/log'" print_step_header "Setting ownership of all log files in '${USER_HOME}/.cache/log'"
mkdir -p "${USER_HOME}/.cache/log" mkdir -p "${USER_HOME}/.cache/log"
chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log" chown -R ${PUID}:${PGID} "${USER_HOME}/.cache/log"
# Set the root and user password # Set the root and user password
echo "Setting root password" print_step_header "Setting root password"
echo "root:${USER_PASSWORD}" | chpasswd echo "root:${USER_PASSWORD}" | chpasswd
echo "Setting user password" print_step_header "Setting user password"
echo "${USER}:${USER_PASSWORD}" | chpasswd echo "${USER}:${USER_PASSWORD}" | chpasswd
# Set root XDG_RUNTIME_DIR path # Set root XDG_RUNTIME_DIR path
mkdir -p /tmp/runtime-root mkdir -p /tmp/runtime-root
chown root:root /tmp/runtime-root chown root:root /tmp/runtime-root
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -0,0 +1,17 @@
# 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
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
print_warning "Unable to set vm.max_map_count on unprivileged container"
fi
else
print_step_header "The vm.max_map_count is already greater than '524288'"
fi
echo -e "\e[34mDONE\e[0m"

View File

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

View File

@@ -1,12 +1,14 @@
# Configure dbus # Configure dbus
echo "**** Configure container dbus ****"; print_header "Configure container dbus"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
if [[ "${HOST_DBUS}" == "true" ]]; then if [[ "${HOST_DBUS}" == "true" ]]; then
echo "Container configured to use the host dbus"; print_step_header "Container configured to use the host dbus";
# Disable supervisord script # Disable supervisord script
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/dbus.ini
else else
echo "Container configured to run its own dbus"; print_step_header "Container configured to run its own dbus";
# Enable supervisord script # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/dbus.ini
# Configure dbus to run as USER # Configure dbus to run as USER
@@ -22,5 +24,9 @@ else
# Remove old lockfiles # Remove old lockfiles
find /var/run/dbus -name "pid" -exec rm -f {} \; find /var/run/dbus -name "pid" -exec rm -f {} \;
fi fi
else
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"

View File

@@ -1,46 +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 # Configure dbus
# Source: https://github.com/balena-io-playground/balena-base-images/ print_header "Configure udevd"
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}"
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
if [[ "${is_privileged}" == "true" ]]; then run_dumb_udev="false"
echo "**** Configure container to run udev management ****"; if [ ! -w /sys ]; then
# Disable supervisord script since we are not able to write to sysfs
print_step_header "Disable udevd - /sys is mounted RO"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="true"
elif [ ! -d /run/udev ]; then
# Disable supervisord script since we are not able to write to udev/data path
print_step_header "Disable udevd - /run/udev does not exist"
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
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 # Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Make startup script executable
chmod +x /usr/bin/start-udev.sh
# Configure udev permissions # Configure udev permissions
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then 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 sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
fi fi
run_dumb_udev="false"
else else
# Disable supervisord script # 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 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 fi
if [[ -e /dev/uinput ]]; then if [[ -e /dev/uinput ]]; then
echo "**** Ensure the default user has permission to r/w on input devices ****"; print_step_header "Ensure the default user has permission to r/w on input devices"
chmod 0666 /dev/uinput chmod 0666 /dev/uinput
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

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

View File

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

View File

@@ -1,20 +1,22 @@
# Fech NVIDIA GPU device (if one exists) # Fech NVIDIA GPU device (if one exists)
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then if [ "${NVIDIA_VISIBLE_DEVICES:-}" = "all" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
elif [ -z "${NVIDIA_VISIBLE_DEVICES:-}" ]; then elif [ "${NVIDIA_VISIBLE_DEVICES:-}X" = "X" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
else else
export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --id=$(echo "$NVIDIA_VISIBLE_DEVICES" | cut -d ',' -f1) --query-gpu=uuid | sed -n 2p)
if [ -z "$gpu_select" ]; then if [ "${gpu_select:-}X" = "X" ]; then
export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p) export gpu_select=$(nvidia-smi --format=csv --query-gpu=uuid 2>/dev/null | sed -n 2p)
fi fi
fi fi
# NVIDIA Params # NVIDIA Params
export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select}" 2> /dev/null | sed -n 2p | cut -d ':' -f2,3)" if [ "X${gpu_select:-}" != "X" ]; then
export nvidia_gpu_name=$(nvidia-smi --format=csv --query-gpu=name --id="${gpu_select}" 2> /dev/null | sed -n 2p) export nvidia_pci_address="$(nvidia-smi --format=csv --query-gpu=pci.bus_id --id="${gpu_select:?}" 2>/dev/null | sed -n 2p | cut -d ':' -f2,3)"
export nvidia_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)" export nvidia_host_driver_version="$(nvidia-smi 2>/dev/null | grep NVIDIA-SMI | cut -d ' ' -f3)"
fi
# Intel params # Intel params
# This figures out if it's an intel CPU with integrated GPU # This figures out if it's an intel CPU with integrated GPU
@@ -27,41 +29,58 @@ export amd_cpu_model="$(lscpu | grep 'Model name:' | grep -i amd | cut -d':' -f2
export amd_gpu_model="$(lspci | grep -i vga | grep -i amd)" export amd_gpu_model="$(lspci | grep -i vga | grep -i amd)"
function download_driver { function download_driver {
mkdir -p ${USER_HOME}/Downloads local driver_url
chown -R ${USER} ${USER_HOME}/Downloads local stripped_version
if [[ ! -f "${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run" ]]; then mkdir -p "${USER_HOME:?}/Downloads"
echo "Downloading driver v${nvidia_host_driver_version}" chown -R ${USER:?} "${USER_HOME:?}/Downloads"
wget -q --show-progress --progress=bar:force:noscroll \
if [[ ! -f "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" ]]; then
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 \ -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 "${driver_url:?}"; then
[[ $? -gt 0 ]] && echo "Error downloading driver. Exit!" && return 1 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
mv /tmp/NVIDIA.run ${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run print_note "Visit https://download.nvidia.com/XFree86/Linux-x86_64/ in a browser and find the closest match to version '${nvidia_host_driver_version:?}', then set that version in the NVIDIA_DRIVER_VERSION environment variable."
print_error "Unable to download driver from any source. Exit!"
sleep 10
return 1
fi fi
} }
function install_nvidia_driver { function install_nvidia_driver {
# Check here if the currently installed version matches using nvidia-settings # Check here if the currently installed version matches using nvidia-settings
nvidia_settings_version=$(nvidia-settings --version 2>/dev/null | grep version | cut -d ' ' -f 4) nvidia_settings_version=$(nvidia-settings --version 2>/dev/null | grep version | cut -d ' ' -f 4)
[[ "${nvidia_settings_version}x" == "${nvidia_host_driver_version}x" ]] && return 0; if [ "${nvidia_settings_version:-}X" != "${nvidia_host_driver_version:-}X" ]; then
# Download the driver (if it does not yet exist locally) # Download the driver (if it does not yet exist locally)
download_driver download_driver
# if command -v pacman &> /dev/null; then if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) >= 550)); then
# echo "Install NVIDIA vulkan utils" \ sed -i 's/--no-multigpu//g' /etc/cont-init.d/70-configure_xorg.sh
# && pacman -Syu --noconfirm --needed \ fi
# lib32-nvidia-utils \
# lib32-vulkan-icd-loader
# nvidia-utils \
# vulkan-icd-loader \
# && echo
# fi
echo "Installing NVIDIA driver v${nvidia_host_driver_version} to match what is running on the host" if (($(echo $nvidia_host_driver_version | cut -d '.' -f 1) > 500)); then
chmod +x ${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run print_step_header "Installing NVIDIA driver v${nvidia_host_driver_version:?} to match what is running on the host"
${USER_HOME}/Downloads/NVIDIA_${nvidia_host_driver_version}.run \ chmod +x "${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run"
"${USER_HOME:?}/Downloads/NVIDIA_${nvidia_host_driver_version:?}.run" \
--silent \ --silent \
--accept-license \ --accept-license \
--skip-depmod \ --skip-depmod \
@@ -78,72 +97,163 @@ function install_nvidia_driver {
--no-check-for-alternate-installs \ --no-check-for-alternate-installs \
--no-libglx-indirect \ --no-libglx-indirect \
--no-install-libglvnd \ --no-install-libglvnd \
> ${USER_HOME}/Downloads/nvidia_gpu_install.log 2>&1 >"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
else
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 \
--accept-license \
--skip-depmod \
--skip-module-unload \
--no-kernel-module \
--no-kernel-module-source \
--install-compat32-libs \
--no-nouveau-check \
--no-nvidia-modprobe \
--no-systemd \
--no-distro-scripts \
--no-rpms \
--no-backup \
--no-check-for-alternate-installs \
--no-libglx-indirect \
--no-install-libglvnd \
>"${USER_HOME:?}/Downloads/nvidia_gpu_install.log" 2>&1
fi
else
print_step_header "NVIDIA driver version ${nvidia_settings_version:-} is already installed"
fi
}
function patch_nvidia_driver {
# REF: https://github.com/keylase/nvidia-patch#docker-support
if [ "${NVIDIA_PATCH_VERSION:-}X" != "X" ]; then
# Don't fail boot if something goes wrong here. Set +e
(
set +e
if [ ! -f "${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" ]; then
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
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"
fi
chmod +x \
"${USER_HOME:?}/Downloads/nvidia-patch.${NVIDIA_PATCH_VERSION:?}.sh" \
"${USER_HOME:?}/Downloads/nvidia-patch-fbc.${NVIDIA_PATCH_VERSION:?}.sh"
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 || {
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 || {
print_error "Failed to pop directory out of /patched-lib"
exit 1
}
)
else
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 { function install_amd_gpu_driver {
echo "Install AMD vulkan driver"
if command -v pacman &>/dev/null; then if command -v pacman &>/dev/null; then
print_step_header "Install AMD Mesa driver"
pacman -Syu --noconfirm --needed \ pacman -Syu --noconfirm --needed \
lib32-mesa \
lib32-vulkan-icd-loader \ lib32-vulkan-icd-loader \
lib32-vulkan-radeon \ lib32-vulkan-radeon \
vulkan-icd-loader \ vulkan-icd-loader \
vulkan-radeon vulkan-radeon
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required elif command -v apt-get &>/dev/null; then
# elif command -v apt-get &> /dev/null; then install_deb_mesa
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
# apt-get install -y \
# libvulkan1 \
# libvulkan1:i386 \
# mesa-vulkan-drivers \
# mesa-vulkan-drivers:i386
fi fi
} }
function install_intel_gpu_driver { function install_intel_gpu_driver {
echo "Install Intel vulkan driver"
if command -v pacman &>/dev/null; then if command -v pacman &>/dev/null; then
print_step_header "Install Intel Mesa driver"
pacman -Syu --noconfirm --needed \ pacman -Syu --noconfirm --needed \
lib32-mesa \
lib32-vulkan-icd-loader \ lib32-vulkan-icd-loader \
lib32-vulkan-intel \ lib32-vulkan-intel \
vulkan-icd-loader \ vulkan-icd-loader \
vulkan-intel vulkan-intel
# There is currently nothing to install inside the debian container. This already comes with the vulken drives that are required elif command -v apt-get &>/dev/null; then
# elif command -v apt-get &> /dev/null; then install_deb_mesa
# [[ "${APT_UPDATED:-false}" == 'false' ]] && apt-get update && export APT_UPDATED=true
# apt-get install -y \
# libvulkan1 \
# libvulkan1:i386 \
# mesa-vulkan-drivers \
# mesa-vulkan-drivers:i386
fi fi
} }
# NVIDIA GPU
if [[ ! -z ${nvidia_pci_address} ]]; then
echo "**** Found NVIDIA device '${nvidia_gpu_name}' ****";
install_nvidia_driver
else
echo "**** No NVIDIA device found ****";
fi
# Intel Arc GPU or Intel CPU with possible iGPU # Intel Arc GPU or Intel CPU with possible iGPU
if [[ ! -z ${intel_gpu_model} ]]; then if [ "${intel_gpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_gpu_model}' ****"; print_header "Found Intel device '${intel_gpu_model:?}'"
install_intel_gpu_driver install_intel_gpu_driver
elif [[ ! -z ${intel_cpu_model} ]]; then elif [ "${intel_cpu_model:-}X" != "X" ]; then
echo "**** Found Intel device '${intel_cpu_model}' ****"; print_header "Found Intel device '${intel_cpu_model:?}'"
install_intel_gpu_driver install_intel_gpu_driver
else else
echo "**** No Intel device found ****"; print_header "No Intel device found"
fi fi
# AMD GPU # AMD GPU
if [[ ! -z ${amd_gpu_model} ]]; then if [ "${amd_gpu_model:-}X" != "X" ]; then
echo "**** Found AMD device '${amd_gpu_model}' ****"; print_header "Found AMD device '${amd_gpu_model:?}'"
install_amd_gpu_driver install_amd_gpu_driver
else else
echo "**** No AMD device found ****"; print_header "No AMD device found"
fi
# NVIDIA GPU
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
print_header "No NVIDIA device found"
fi fi
echo "DONE" echo -e "\e[34mDONE\e[0m"

View File

@@ -0,0 +1,22 @@
print_header "Configure Desktop"
if ([ "${MODE}" != "s" ] && [ "${MODE}" != "secondary" ]); then
print_step_header "Enable Desktop service."
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/desktop.ini
else
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
print_step_header "Ensure home directory template is owned by the default user."
chown -R ${PUID}:${PGID} /templates/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 -e "\e[34mDONE\e[0m"

View File

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

View File

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

View File

@@ -0,0 +1,13 @@
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
print_step_header "Flatpak configured for running inside a Docker container"
else
print_step_header "Flatpak already configured for running inside a Docker container"
fi
echo -e "\e[34mDONE\e[0m"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,12 +3,36 @@
"PATH": "$(PATH):$(HOME)\/.local\/bin" "PATH": "$(PATH):$(HOME)\/.local\/bin"
}, },
"apps": [ "apps": [
{
"name": "Desktop",
"image-path": "desktop.png",
"exclude-global-prep-cmd": "true"
},
{ {
"name": "Steam Big Picture", "name": "Steam Big Picture",
"output": "steam.txt", "image-path": "steam.png",
"cmd": "", "exclude-global-prep-cmd": "true",
"detached": [ "detached": [
"\/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 5 && pkill -f -2 \/usr\/bin\/sunshine\""
},
{
"do": "",
"undo": "\/usr\/bin\/sunshine-stop"
},
{
"do": "",
"undo": "\/usr\/bin\/xfce4-close-all-windows"
},
{
"do": "",
"undo": "\/usr\/games\/steam steam:\/\/close\/bigpicture"
}
] ]
} }
] ]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,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"

View File

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

View File

@@ -19,7 +19,6 @@ trap _term SIGTERM SIGINT
# EXECUTE PROCESS: # EXECUTE PROCESS:
echo "PULSEAUDIO: Starting pulseaudio service" echo "PULSEAUDIO: Starting pulseaudio service"
sleep 5
#/usr/bin/pulseaudio --disallow-module-loading --disallow-exit --exit-idle-time=-1 & #/usr/bin/pulseaudio --disallow-module-loading --disallow-exit --exit-idle-time=-1 &
/usr/bin/pulseaudio --exit-idle-time=-1 & /usr/bin/pulseaudio --exit-idle-time=-1 &
pulseaudio_pid=$! pulseaudio_pid=$!

View File

@@ -5,50 +5,73 @@
# File Created: Tuesday, 4th October 2022 8:22:17 pm # File Created: Tuesday, 4th October 2022 8:22:17 pm
# Author: Josh.5 (jsunnex@gmail.com) # Author: Josh.5 (jsunnex@gmail.com)
# ----- # -----
# Last Modified: Tuesday, 4th October 2022 8:22:17 pm # Last Modified: Wednesday, 27th November 2024 3:54:19 pm
# Modified By: Josh.5 (jsunnex@gmail.com) # Modified By: Josh5 (jsunnex@gmail.com)
### ###
set -e set -e
source /usr/bin/common-functions.sh source /usr/bin/common-functions.sh
# CATCH TERM SIGNAL: # CATCH TERM SIGNAL:
_term() { _term() {
kill -INT "$sunshine_pid" 2>/dev/null
sleep 0.5
counter=0
while kill -0 "$sunshine_pid"; do
kill -TERM "$sunshine_pid" 2>/dev/null kill -TERM "$sunshine_pid" 2>/dev/null
counter=$((counter + 1))
[ "$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 4 ] && break
sleep 0.5
done
} }
trap _term SIGTERM SIGINT trap _term SIGTERM SIGINT
# CONFIGURE: # CONFIGURE:
# Install default configurations # Install default configurations
mkdir -p /home/${USER}/sunshine mkdir -p "${USER_HOME:?}/.config/sunshine"
if [[ ! -f /home/${USER}/sunshine/sunshine.conf ]]; then if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine.conf" ]; then
cp -vf /templates/sunshine/* /home/${USER}/sunshine/ cp -vf /templates/sunshine/sunshine.conf "${USER_HOME:?}/.config/sunshine/sunshine.conf"
# TODO: Set the default encoder '# encoder = nvenc' fi
# nvidia_gpu_id=$(get_nvidia_gpu_id) if [ ! -f "${USER_HOME:?}/.config/sunshine/apps.json" ]; then
# if [[ "X${nvidia_gpu_id:-}" != "X" ]]; then cp -vf /templates/sunshine/apps.json "${USER_HOME:?}/.config/sunshine/apps.json"
# if [[ "all video" == *"${NVIDIA_DRIVER_CAPABILITIES}"* ]]; then fi
# # Check if we have a nvidia GPU available if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine_state.json" ]; then
# sed -i 's|^# encoder.*=.*$|encoder = nvenc|' /home/${USER}/sunshine/sunshine.conf echo "{}" > "${USER_HOME:?}/.config/sunshine/sunshine_state.json"
# fi
# else
# # TODO: Enable the vaapi device if not using nvenc
# # vainfo --display drm --device /dev/dri/renderD128 2> /dev/null | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)"
# # Loop over any render devices
# echo
# fi
fi fi
# Reset the default username/password # Reset the default username/password
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
sunshine /home/${USER}/sunshine/sunshine.conf --creds ${SUNSHINE_USER:-} ${SUNSHINE_PASS:-} /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"
fi fi
# EXECUTE PROCESS: # EXECUTE PROCESS:
# Wait for the X server to start # Wait for the X server to start
wait_for_x wait_for_x
# Start a session bus instance of dbus-daemon
wait_for_desktop_dbus_session
export_desktop_dbus_session
# Wait for the desktop to start
wait_for_desktop
# Start the sunshine server # Start the sunshine server
sunshine /home/${USER}/sunshine/sunshine.conf & /usr/bin/dumb-init /usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" &
sunshine_pid=$! sunshine_pid=$!

View File

@@ -16,10 +16,7 @@ _term() {
} }
trap _term SIGTERM SIGINT trap _term SIGTERM SIGINT
# EXECUTE PROCESS: # EXECUTE PROCESS:
# Remove lockfile
rm -f /tmp/.udev-started
# Start udev # Start udev
if command -v udevd &>/dev/null; then if command -v udevd &>/dev/null; then
unshare --net udevd --daemon &>/dev/null unshare --net udevd --daemon &>/dev/null
@@ -29,11 +26,8 @@ fi
# Monitor kernel uevents # Monitor kernel uevents
udevadm monitor & udevadm monitor &
monitor_pid=$! monitor_pid=$!
# Touch lockfile # Wait for 5 seconds, then request device events from the kernel
sleep 1 sleep 5
touch /tmp/.udev-started
# Wait for 10 seconds, then request device events from the kernel
sleep 10
udevadm trigger udevadm trigger
# WAIT FOR CHILD PROCESS: # WAIT FOR CHILD PROCESS:

View File

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

View File

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

163
overlay/usr/bin/sunshine-run Executable file
View File

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

110
overlay/usr/bin/sunshine-stop Executable file
View File

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

View File

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

View File

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