From fddbf726d7bd7bd408efc4a575d4c6a6df893093 Mon Sep 17 00:00:00 2001 From: Francesco Date: Mon, 20 Apr 2026 07:26:16 -0700 Subject: [PATCH] Distrobox install (#41) --- README.md | 14 + tools/distro/distrobox/install-distrobox.sh | 254 ++++++++++++++++++ tools/distro/distrobox/uninstall-distrobox.sh | 102 +++++++ 3 files changed, 370 insertions(+) create mode 100644 tools/distro/distrobox/install-distrobox.sh create mode 100644 tools/distro/distrobox/uninstall-distrobox.sh diff --git a/README.md b/README.md index bbbed7f..43410ef 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,20 @@ chmod +x install.sh ./install.sh ``` +### Installation on Immutable Distros (Bazzite, Silverblue, etc.) + +On immutable distributions where native package managers are unavailable, +monocoque can be installed inside a distrobox container: + +```bash +bash tools/distro/distrobox/install-distrobox.sh +``` + +This creates an Arch Linux container, installs all packages via AUR, and sets up +wrapper scripts (`start-simd`, `start-monocoque`, `test-monocoque`) in `~/.local/bin/`. + +To uninstall: `bash tools/distro/distrobox/uninstall-distrobox.sh` + **TUI Manager:** After installation, use the interactive manager: ```bash diff --git a/tools/distro/distrobox/install-distrobox.sh b/tools/distro/distrobox/install-distrobox.sh new file mode 100644 index 0000000..0ec8a91 --- /dev/null +++ b/tools/distro/distrobox/install-distrobox.sh @@ -0,0 +1,254 @@ +#!/bin/bash +# Monocoque Distrobox Installer +# For immutable Linux distributions (Bazzite, Silverblue, etc.) +# where native package managers are unavailable. +# +# Installs monocoque and dependencies inside an Arch Linux distrobox container, +# with wrapper scripts on the host for transparent access. + +set -euo pipefail + +SCRIPT_VERSION="1.0.0" +CONTAINER="simracing" +INSTALL_DIR="$HOME/.local/share/simracing" +BIN_DIR="$HOME/.local/bin" +CONFIG_DIR="$HOME/.config/monocoque" + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_header() { + echo "" + echo "╔══════════════════════════════════════════════════════════════════╗" + echo "║ Monocoque Distrobox Installer v${SCRIPT_VERSION} ║" + echo "╚══════════════════════════════════════════════════════════════════╝" + echo "" +} + +# --- Main --- + +print_header + +# Check ~/.local/bin is in PATH +if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then + log_error "$BIN_DIR is not in your PATH." + log_info "Add this to your shell config:" + echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" + exit 1 +fi + +# Check distrobox is available +if ! command -v distrobox &>/dev/null; then + log_error "distrobox is not installed." + log_info "Install distrobox first: https://distrobox.it/#installation" + exit 1 +fi + +# Ensure dialout group exists and user is a member +log_info "Checking serial device access (dialout group)..." +if ! grep -q '^dialout:' /etc/group 2>/dev/null; then + if grep -q '^dialout:' /usr/lib/group 2>/dev/null; then + log_info "Adding dialout group to /etc/group (Fedora Atomic fix)..." + grep -E '^dialout:' /usr/lib/group | sudo tee -a /etc/group >/dev/null + else + log_info "Creating dialout group..." + sudo groupadd dialout + fi +fi +if ! groups | grep -qw dialout; then + log_info "Adding $USER to the dialout group for serial device access..." + sudo usermod -aG dialout "$USER" + log_warn "You will need to REBOOT after setup completes for serial access to work." + echo "" +fi + +# Prevent ModemManager from grabbing Moza serial devices +UDEV_RULE="/etc/udev/rules.d/99-moza-serial.rules" +if [ ! -f "$UDEV_RULE" ]; then + if systemctl is-active --quiet ModemManager 2>/dev/null; then + echo "" + log_warn "ModemManager is running on your system." + echo " Moza wheel bases use USB serial devices that ModemManager may claim," + echo " preventing monocoque from communicating with the wheel." + echo "" + echo " A udev rule can tell ModemManager to ignore Moza devices (vendor 346e)." + echo " This only affects Moza USB devices — other modems will work normally." + echo "" + read -rp "Install udev rule to prevent ModemManager from grabbing Moza devices? [Y/n]: " mm_confirm + if [[ "$mm_confirm" =~ ^[Nn]$ ]]; then + echo "" + log_info "Skipped udev rule. If monocoque can't talk to your wheel, run:" + echo " sudo tee $UDEV_RULE <<< 'ACTION==\"add|change\", SUBSYSTEM==\"usb\", ATTR{idVendor}==\"346e\", ENV{ID_MM_DEVICE_IGNORE}=\"1\"'" + echo " sudo udevadm control --reload-rules && sudo udevadm trigger" + echo "" + else + log_info "Installing udev rule..." + echo 'ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="346e", ENV{ID_MM_DEVICE_IGNORE}="1"' | sudo tee "$UDEV_RULE" >/dev/null + sudo udevadm control --reload-rules + sudo udevadm trigger + log_success "ModemManager udev rule installed" + fi + else + # ModemManager not running — install the rule silently + echo 'ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="346e", ENV{ID_MM_DEVICE_IGNORE}="1"' | sudo tee "$UDEV_RULE" >/dev/null + sudo udevadm control --reload-rules + sudo udevadm trigger + fi +fi + +# Create the Arch Linux distrobox container +if ! distrobox list 2>/dev/null | grep -q "$CONTAINER"; then + log_info "Creating Arch Linux container '$CONTAINER'..." + distrobox create \ + --image docker.io/library/archlinux:latest \ + --name "$CONTAINER" \ + --pre-init-hooks "sed -i 's/^SigLevel.*/SigLevel = Never/' /etc/pacman.conf && pacman -Sy --noconfirm archlinux-keyring && pacman-key --init && pacman-key --populate archlinux && sed -i 's/^SigLevel.*/SigLevel = Required DatabaseOptional/' /etc/pacman.conf" + log_success "Container '$CONTAINER' created" +else + log_info "Container '$CONTAINER' already exists, skipping creation." +fi + +# Install packages inside the container +log_info "Installing packages inside container (this may take a few minutes)..." +distrobox enter "$CONTAINER" -- bash -c ' + set -euo pipefail + + # Install build dependencies + echo "Installing build dependencies..." + sudo pacman -Syu --needed --noconfirm base-devel git mingw-w64-gcc + + # Install yay (AUR helper) if not present + if ! command -v yay &>/dev/null; then + echo "Installing yay AUR helper..." + TMPDIR=$(mktemp -d) + git clone https://aur.archlinux.org/yay-bin.git "$TMPDIR/yay-bin" + cd "$TMPDIR/yay-bin" + makepkg -si --noconfirm + cd / + rm -rf "$TMPDIR" + fi + + # Install AUR packages sequentially (simd depends on simapi, monocoque depends on both) + echo "Installing AUR packages..." + yay -S --needed --noconfirm simapi-git + yay -S --needed --noconfirm simd-git + yay -S --needed --noconfirm monocoque-git + + # Build simshmbridge (not on AUR) + INSTALL_DIR="$HOME/.local/share/simracing" + mkdir -p "$INSTALL_DIR" + cd "$INSTALL_DIR" + if [ ! -d "simshmbridge" ]; then + echo "Cloning simshmbridge..." + git clone --recurse-submodules "https://github.com/Spacefreak18/simshmbridge.git" + else + echo "simshmbridge already cloned, pulling latest..." + cd simshmbridge && git pull && git submodule update --init --recursive && cd .. + fi + echo "Building simshmbridge..." + cd "$INSTALL_DIR/simshmbridge" + git submodule update --init --recursive + make clean 2>/dev/null || true + make -j$(nproc) + + echo "" + echo "All components built successfully inside container." +' + +# Install wrapper scripts to ~/.local/bin +log_info "Installing wrapper scripts..." +mkdir -p "$BIN_DIR" + +cat > "$BIN_DIR/start-simd" << 'EOF' +#!/usr/bin/env bash +exec distrobox enter simracing -- simd "$@" +EOF +chmod +x "$BIN_DIR/start-simd" + +cat > "$BIN_DIR/start-monocoque" << 'EOF' +#!/usr/bin/env bash +exec distrobox enter simracing -- monocoque play "$@" +EOF +chmod +x "$BIN_DIR/start-monocoque" + +cat > "$BIN_DIR/test-monocoque" << 'EOF' +#!/usr/bin/env bash +exec distrobox enter simracing -- monocoque test -vv "$@" +EOF +chmod +x "$BIN_DIR/test-monocoque" + +log_success "Wrapper scripts installed" + +# Setup monocoque config +mkdir -p "$CONFIG_DIR" +if [ ! -f "$CONFIG_DIR/monocoque.config" ]; then + log_info "Creating monocoque config template..." + cat > "$CONFIG_DIR/monocoque.config" << 'EOF' +configs = ( + { + sim = "default"; + car = "default"; + devices = ( + { + device = "Serial"; + type = "Wheel"; + subtype = "MozaNew"; + devpath = "/dev/serial/by-id/CHANGE_ME_TO_YOUR_MOZA_BASE"; + baud = 115200; + }); + } +); +EOF + log_success "Config created at $CONFIG_DIR/monocoque.config" +else + log_info "Config already exists, skipping" +fi + +# Done +echo "" +echo "╔══════════════════════════════════════════════════════════════════╗" +echo "║ Installation Complete! ║" +echo "╚══════════════════════════════════════════════════════════════════╝" +echo "" +log_success "Monocoque (distrobox) installed!" +echo "" +echo " Installed:" +echo " AUR packages: simapi-git, simd-git, monocoque-git (in '$CONTAINER' container)" +echo " Bridge: $INSTALL_DIR/simshmbridge/" +echo " Config: $CONFIG_DIR/monocoque.config" +echo " Commands: start-simd, start-monocoque, test-monocoque" +echo "" +echo " Next steps:" +echo " 1. Set your device path in $CONFIG_DIR/monocoque.config" +echo " (replace CHANGE_ME_TO_YOUR_MOZA_BASE with your device from /dev/serial/by-id/)" +echo " 2. Test with: test-monocoque" +echo " 3. Set Steam launch options for your games to start the telemetry stack automatically:" +echo " In Steam > Game Properties > Launch Options, add:" +echo " start-simd & start-monocoque & %command%" +echo " For example, for Assetto Corsa:" +echo " start-simd & start-monocoque & $INSTALL_DIR/simshmbridge/assets/acbridge.exe %command%" +echo "" +echo " For tools that automate steps 1 and 3 (Moza auto-detection, Steam launch" +echo " option configuration, unified game launcher), visit:" +echo " https://github.com/cescofry/simracing-utilities" +echo "" diff --git a/tools/distro/distrobox/uninstall-distrobox.sh b/tools/distro/distrobox/uninstall-distrobox.sh new file mode 100644 index 0000000..3605446 --- /dev/null +++ b/tools/distro/distrobox/uninstall-distrobox.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Monocoque Distrobox Uninstaller +# Removes the distrobox-based monocoque installation. + +set -euo pipefail + +CONTAINER="simracing" +BIN_DIR="$HOME/.local/bin" +INSTALL_DIR="$HOME/.local/share/simracing" +CONFIG_DIR="$HOME/.config/monocoque" +UDEV_RULE="/etc/udev/rules.d/99-moza-serial.rules" + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +print_header() { + echo "" + echo "╔══════════════════════════════════════════════════════════════════╗" + echo "║ Monocoque Distrobox Uninstaller ║" + echo "╚══════════════════════════════════════════════════════════════════╝" + echo "" +} + +print_header + +log_warn "This will remove:" +echo " - Distrobox container '$CONTAINER'" +echo " - Wrapper scripts ($BIN_DIR/start-simd, start-monocoque, test-monocoque)" +echo " - simshmbridge source ($INSTALL_DIR)" +echo "" +echo "This will NOT remove:" +echo " - Configuration files ($CONFIG_DIR)" +echo " - Convenience scripts (simracing-launch, configure-moza, etc.)" +echo "" + +read -rp "Continue with uninstallation? [y/N]: " confirm +if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + log_info "Uninstallation cancelled" + exit 0 +fi + +echo "" + +# Remove wrapper scripts +log_info "Removing wrapper scripts..." +rm -f "$BIN_DIR/start-simd" +rm -f "$BIN_DIR/start-monocoque" +rm -f "$BIN_DIR/test-monocoque" +log_success "Wrapper scripts removed" + +# Remove simshmbridge source +if [ -d "$INSTALL_DIR" ]; then + log_info "Removing simshmbridge source..." + rm -rf "$INSTALL_DIR" + log_success "simshmbridge source removed" +fi + +# Remove distrobox container +if distrobox list 2>/dev/null | grep -q "$CONTAINER"; then + log_info "Removing distrobox container '$CONTAINER'..." + distrobox rm --force "$CONTAINER" + log_success "Container '$CONTAINER' removed" +else + log_info "Container '$CONTAINER' not found, skipping" +fi + +# Optionally remove udev rule +if [ -f "$UDEV_RULE" ]; then + echo "" + read -rp "Remove ModemManager udev rule ($UDEV_RULE)? [y/N]: " remove_udev + if [[ "$remove_udev" =~ ^[Yy]$ ]]; then + sudo rm -f "$UDEV_RULE" + sudo udevadm control --reload-rules + sudo udevadm trigger + log_success "udev rule removed" + else + log_info "Keeping udev rule" + fi +fi + +echo "" +log_success "Uninstallation complete!" +echo "" +log_info "Config files preserved at $CONFIG_DIR" +echo " To remove those too: rm -rf $CONFIG_DIR" +echo ""