feat(runner): More runner improvements (#294)

## Description
Whew..

- Steam can now run without namespaces using live-patcher (because
Docker..)
- Improved NVIDIA GPU selection and handling
- Pipeline tests for GPU picking logic
- Optimizations and cleanup all around
- SSH (by default disabled) for easier instance debugging.
- CachyOS' Proton because that works without namespaces (couldn't figure
out how to enable automatically in Steam yet..)
- Package updates and partial removal of futures (libp2p is going to
switch to Tokio in next release hopefully)



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- SSH server can now be enabled within the container for remote access
when configured.
- Added persistent live patching for Steam runtime entrypoints to
improve compatibility with namespace-less applications.
- Enhanced GPU selection with multi-GPU support and PCI bus ID matching
for improved hardware compatibility.
- Improved encoder selection by runtime testing of video encoders for
better reliability.
  - Added WebSocket transport support in peer-to-peer networking.
- Added flexible compositor and application launching with configurable
commands and improved socket handling.

- **Bug Fixes**
- Addressed NVIDIA-specific GStreamer issues by setting new environment
variables.
  - Improved error handling and logging for GPU and encoder selection.
- Fixed process monitoring to handle patcher restarts and added cleanup
logic.
- Added GStreamer cache clearing workaround for Wayland socket failures.

- **Improvements**
- Real-time logging of container processes to standard output and error
for easier monitoring.
- Enhanced process management and reduced CPU usage in protocol handling
loops.
- Updated dependency versions for greater stability and feature support.
  - Improved audio capture defaults and expanded audio pipeline support.
- Enhanced video pipeline setup with conditional handling for different
encoder APIs and DMA-BUF support.
- Refined concurrency and lifecycle management in protocol messaging for
increased robustness.
- Consistent namespace usage and updated crate references across the
codebase.
- Enhanced SSH configuration with key management, port customization,
and startup verification.
  - Improved GPU and video encoder integration in pipeline construction.
- Simplified error handling and consolidated write operations in
protocol streams.
- Removed Ludusavi installation from container image and updated package
installations.

- **Other**
- Minor formatting and style changes for better code readability and
maintainability.
- Docker build context now ignores `.idea` directory to streamline
builds.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
This commit is contained in:
Kristian Ollikainen
2025-07-07 09:06:48 +03:00
committed by GitHub
parent 191c59d230
commit 41dca22d9d
21 changed files with 2049 additions and 641 deletions

View File

@@ -13,7 +13,7 @@ log() {
# Ensures user directory ownership
chown_user_directory() {
local user_group="${USER}:${GID}"
if ! chown -R -h --no-preserve-root "$user_group" "${HOME}" 2>/dev/null; then
if ! chown -h --no-preserve-root "$user_group" "${HOME}" 2>/dev/null; then
echo "Error: Failed to change ownership of ${HOME} to ${user_group}" >&2
return 1
fi
@@ -36,6 +36,12 @@ wait_for_socket() {
return 1
}
# Prepares environment for namespace-less applications (like Steam)
setup_namespaceless() {
rm -f /run/systemd/container || true
mkdir -p /run/pressure-vessel || true
}
# Ensures cache directory exists
setup_cache() {
log "Setting up NVIDIA driver cache directory at $CACHE_DIR..."
@@ -103,8 +109,10 @@ get_nvidia_installer() {
install_nvidia_driver() {
local filename="$1"
log "Installing NVIDIA driver components from $filename..."
sudo ./"$filename" \
bash ./"$filename" \
--silent \
--skip-depmod \
--skip-module-unload \
--no-kernel-module \
--install-compat32-libs \
--no-nouveau-check \
@@ -116,18 +124,102 @@ install_nvidia_driver() {
log "Error: NVIDIA driver installation failed."
return 1
}
# Install CUDA package
log "Checking if CUDA is already installed"
if ! pacman -Q cuda &>/dev/null; then
log "Installing CUDA package"
pacman -S --noconfirm cuda --assume-installed opencl-nvidia
else
log "CUDA package is already installed, skipping"
fi
log "NVIDIA driver installation completed."
return 0
}
function log_gpu_info {
log_gpu_info() {
if ! declare -p vendor_devices &>/dev/null; then
log "Warning: vendor_devices array is not defined"
return
fi
log "Detected GPUs:"
for vendor in "${!vendor_devices[@]}"; do
log "> $vendor: ${vendor_devices[$vendor]}"
done
}
configure_ssh() {
# Return early if SSH not enabled
if [ -z "${SSH_ENABLE_PORT+x}" ] || [ "${SSH_ENABLE_PORT:-0}" -eq 0 ]; then
return 0
fi
# Check if we have required key
if [ -z "${SSH_ALLOWED_KEY+x}" ] || [ -z "${SSH_ALLOWED_KEY}" ]; then
return 0
fi
log "Configuring SSH server on port ${SSH_ENABLE_PORT} with public key authentication"
# Ensure SSH host keys exist
ssh-keygen -A 2>/dev/null || {
log "Error: Failed to generate SSH host keys"
return 1
}
# Create .ssh directory and authorized_keys file for nestri user
mkdir -p /home/nestri/.ssh
echo "${SSH_ALLOWED_KEY}" > /home/nestri/.ssh/authorized_keys
chmod 700 /home/nestri/.ssh
chmod 600 /home/nestri/.ssh/authorized_keys
chown -R nestri:nestri /home/nestri/.ssh
# Update SSHD config
sed -i -E "s/^#?Port .*/Port ${SSH_ENABLE_PORT}/" /etc/ssh/sshd_config || {
log "Error: Failed to update SSH port configuration"
return 1
}
# Configure secure SSH settings
{
echo "PasswordAuthentication no"
echo "PermitRootLogin no"
echo "ChallengeResponseAuthentication no"
echo "UsePAM no"
echo "PubkeyAuthentication yes"
} | while read -r line; do
grep -qF "$line" /etc/ssh/sshd_config || echo "$line" >> /etc/ssh/sshd_config
done
# Start SSH server
log "Starting SSH server on port ${SSH_ENABLE_PORT}"
/usr/sbin/sshd -D -p "${SSH_ENABLE_PORT}" &
SSH_PID=$!
# Verify the process started
if ! ps -p $SSH_PID > /dev/null 2>&1; then
log "Error: SSH server failed to start"
return 1
fi
log "SSH server started with PID ${SSH_PID}"
return 0
}
main() {
# Configure SSH
if [ -n "${SSH_ENABLE_PORT+x}" ] && [ "${SSH_ENABLE_PORT:-0}" -ne 0 ] && \
[ -n "${SSH_ALLOWED_KEY+x}" ] && [ -n "${SSH_ALLOWED_KEY}" ]; then
if ! configure_ssh; then
log "Error: SSH configuration failed with given variables - exiting"
exit 1
fi
else
log "SSH not configured (missing SSH_ENABLE_PORT or SSH_ALLOWED_KEY)"
fi
# Wait for required sockets
wait_for_socket "/run/dbus/system_bus_socket" "DBus" || exit 1
wait_for_socket "/run/user/${UID}/pipewire-0" "PipeWire" || exit 1
@@ -215,6 +307,10 @@ main() {
log "Ensuring user directory permissions..."
chown_user_directory || exit 1
# Setup namespaceless env
log "Applying namespace-less configuration"
setup_namespaceless
# Switch to nestri user
log "Switching to nestri user for application startup..."
if [[ ! -x /etc/nestri/entrypoint_nestri.sh ]]; then