7 Commits
0.1.0 ... 0.2.0

Author SHA1 Message Date
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
15 changed files with 87 additions and 138 deletions

View File

@@ -532,6 +532,7 @@ RUN \
# Various other tools
ARG DUMB_INIT_VERSION=1.2.5
ARG DUMB_UDEV_VERSION=64d1427
RUN \
echo "**** Install dumb-init ****" \
&& wget --no-check-certificate --no-cookies --quiet \
@@ -539,6 +540,14 @@ RUN \
https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
&& chmod +x /usr/bin/dumb-init \
&& \
echo "**** Install dumb-udev ****" \
&& python3 -m pip install \
--break-system-packages \
--pre \
--upgrade \
--no-cache-dir \
git+https://github.com/Steam-Headless/dumb-udev.git@${DUMB_UDEV_VERSION} \
&& \
echo
# Add FS overlay
@@ -566,7 +575,7 @@ ENV \
ENABLE_STEAM="true" \
STEAM_ARGS="-silent" \
ENABLE_SUNSHINE="true" \
ENABLE_EVDEV_INPUTS="false" \
ENABLE_EVDEV_INPUTS="true" \
ENABLE_WOL_POWER_MANAGER="false"
# Configure required ports

View File

@@ -19,12 +19,10 @@ services:
- apparmor:unconfined
# NETWORK:
network_mode: host
hostname: ${NAME}
extra_hosts:
- "${NAME}:127.0.0.1"
networks:
external-macvlan:
ipv4_address: ${CONTAINER_IP_ADDRESS}
# ENVIRONMENT:
## Read all config variables from the .env file
@@ -63,18 +61,4 @@ services:
# Leave commented out to not share the pulse socket with any other Docker containers.
#- /opt/container-data/steam-headless/pulse/:/tmp/pulse/:rw
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro
# Host udev data required for input devices
- /run/udev/data/:/run/udev/data/:ro
# Store flatpak var files in a volume.
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
volumes:
steam-headless-var-lib-flatpak:
networks:
external-macvlan:
external: true
name: ${NETWORK_NAME}

View File

@@ -14,8 +14,8 @@ services:
hard: 524288
# NETWORK:
## NOTE: If we do not use the host network, then physical device input is not possible
## and your USB connected controllers will not work in steam games.
## 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:
@@ -49,8 +49,3 @@ services:
# Input devices used for mouse and joypad support inside the container.
- /dev/input/:/dev/input/:ro
# Store flatpak var files in a volume.
- steam-headless-var-lib-flatpak:/var/lib/flatpak/:rw
volumes:
steam-headless-var-lib-flatpak:

View File

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

View File

Before

Width:  |  Height:  |  Size: 30 KiB

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

View File

@@ -11,7 +11,7 @@ Once your Flatpak refresh is complete, everything should work correctly and your
## An error occurred while installing <game>: "disk write error"
![img.png](../images/disk_write_error.png)
![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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -9,46 +9,44 @@
# Modified By: Josh.5 (jsunnex@gmail.com)
###
# Running udev only works in privileged container
# Source: https://github.com/balena-io-playground/balena-base-images/
tmp_mount='/tmp/privileged_test'
mkdir -p "${tmp_mount}"
if mount -t devtmpfs none "${tmp_mount}" &> /dev/null; then
is_privileged=true
umount "${tmp_mount}"
else
is_privileged=false
fi
rm -rf "${tmp_mount}"
if [[ "${is_privileged}" == "true" ]]; then
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
if [ ! -w /sys ]; then
# Disable supervisord script since we are not able to write to sysfs
echo "**** Disable udev - /sys is mounted RO ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
elif [ ! -w /run/udev ]; then
# Disable supervisord script since we are not able to write to udev/data path
echo "**** Disable udev - /run/udev is mounted RO ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
elif udevadm trigger &> /dev/null; then
echo "**** Configure container to run udev management ****";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Configure udev permissions
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
fi
else
# Disable supervisord script since we are not able to execute "udevadm trigger"
echo "**** Disable udev service due to privilege restrictions ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
fi
else
# Disable supervisord script
echo "**** Disable udev service ****";
# Since this container may also be run with CAP_SYS_ADMIN, ensure we can actually execute "udevadm trigger"
run_dumb_udev="false"
if [ ! -w /sys ]; then
# Disable supervisord script since we are not able to write to sysfs
echo "**** Disable 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
echo "**** 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
echo "**** 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
echo "**** Configure container to run udev management ****";
# Enable supervisord script
sed -i 's|^autostart.*=.*$|autostart=true|' /etc/supervisor.d/udev.ini
# Configure udev permissions
if [[ -f /lib/udev/rules.d/60-steam-input.rules ]]; then
sed -i 's/MODE="0660"/MODE="0666"/' /lib/udev/rules.d/60-steam-input.rules
fi
run_dumb_udev="false"
else
# Disable supervisord script since we are not able to execute "udevadm trigger"
echo "**** Disable udev service due to privilege restrictions ****";
sed -i 's|^autostart.*=.*$|autostart=false|' /etc/supervisor.d/udev.ini
run_dumb_udev="true"
fi
if [ "${run_dumb_udev}" = "true" ]; then
# Enable dumb-udev instead of udevd
echo "**** 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

View File

@@ -9,7 +9,7 @@ if [ "${current_local}" != "${USER_LOCALES}" ]; then
export LANGUAGE="${user_local}"
export LANG="${user_local}"
export LC_ALL="${user_local}" 2> /dev/null
sleep 2
sleep 0.5
locale-gen
update-locale LC_ALL="${user_local}"
else

View File

@@ -28,7 +28,7 @@ wait_for_x() {
wait_for_udev() {
MAX=10
CT=0
while [ ! -f /tmp/.started-udev ]; do
while [ ! -e /run/udev/control ]; do
sleep 1
CT=$(( CT + 1 ))
if [ "$CT" -ge "$MAX" ]; then

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

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

View File

@@ -19,15 +19,15 @@ _term() {
while kill -0 "$sunshine_pid"; do
kill -TERM "$sunshine_pid" 2>/dev/null
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 2
[ "$counter" -gt 8 ] && break
sleep 0.5
done
counter=0
while kill -0 "$sunshine_pid"; do
kill -KILL "$sunshine_pid" 2>/dev/null
counter=$((counter + 1))
[ "$counter" -gt 2 ] && break
sleep 1
[ "$counter" -gt 4 ] && break
sleep 0.5
done
}
trap _term SIGTERM SIGINT

View File

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