Distrobox install (#41)
This commit is contained in:
parent
e3487b3652
commit
fddbf726d7
14
README.md
14
README.md
|
|
@ -41,6 +41,20 @@ chmod +x install.sh
|
||||||
./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:**
|
**TUI Manager:**
|
||||||
After installation, use the interactive manager:
|
After installation, use the interactive manager:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
|
|
@ -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 & <bridge_path> %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 ""
|
||||||
|
|
@ -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 ""
|
||||||
Loading…
Reference in New Issue