#!/usr/bin/env bash # install-server.sh - install and setup all server related apps and environments set -euo pipefail ORIG_USER=${SUDO_USER:-$(id -un)} echo "==> 1a. Base packages" sudo pacman -Syq --needed --noconfirm git rustup protobuf gcc pipewire pipewire-pulse tailscale base-devel if ! command -v yay >/dev/null 2>&1; then echo "==> 1b. installing yay from AUR ..." sudo -u "$ORIG_USER" bash -c ' cd /tmp && git clone --depth 1 https://aur.archlinux.org/yay.git && cd yay && makepkg -si --noconfirm' fi echo "==> 2a. GC311 kernel‑driver tweaks" cat <<'EOF' | sudo tee /etc/modprobe.d/gc311-stream.conf >/dev/null options uvcvideo quirks=0x200 timeout=10000 EOF echo "==> 2b. Predictable /dev names for each capture card" sudo tee /etc/udev/rules.d/85-gc311.rules >/dev/null <<'RULES' # RIGHT eye (video index 0) SUBSYSTEM=="video4linux", ATTRS{idVendor}=="07ca", ATTRS{idProduct}=="3311", \ ATTRS{serial}=="5313550401897", ATTR{index}=="0", \ SYMLINK+="lesavka_r_eye" # LEFT eye (video index 0) SUBSYSTEM=="video4linux", ATTRS{idVendor}=="07ca", ATTRS{idProduct}=="3311", \ ATTRS{serial}=="1200655409098", ATTR{index}=="0", \ SYMLINK+="lesavka_l_eye" RULES sudo udevadm control --reload sudo udevadm trigger --subsystem-match=video4linux udevadm settle echo "==> 3. Rust toolchain" sudo rustup default stable sudo -u "$ORIG_USER" rustup default stable echo "==> 4a. Source checkout" SRC_DIR=/var/src/lesavka REPO_URL=ssh://git@scm.bstein.dev:2242/brad_stein/lesavka.git if [[ ! -d $SRC_DIR ]]; then sudo mkdir -p /var/src sudo chown "$ORIG_USER":"$ORIG_USER" /var/src fi if [[ -d $SRC_DIR/.git ]]; then sudo -u "$ORIG_USER" git -C "$SRC_DIR" pull --ff-only else sudo -u "$ORIG_USER" git clone "$REPO_URL" "$SRC_DIR" fi echo "==> 4b. Source build" sudo -u "$ORIG_USER" bash -c "cd '$SRC_DIR/server' && cargo clean && cargo build --release" echo "==> 5. Install binaries" sudo install -Dm755 "$SRC_DIR/server/target/release/lesavka-server" /usr/local/bin/lesavka-server sudo install -Dm755 "$SRC_DIR/scripts/lesavka-core.sh" /usr/local/bin/lesavka-core.sh echo "==> 6a. Systemd units - lesavka-core" cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-core.service >/dev/null [Unit] Description=lesavka USB gadget bring-up After=sys-kernel-config.mount Requires=sys-kernel-config.mount [Service] Type=oneshot ExecStart=/usr/local/bin/lesavka-core.sh RemainAfterExit=yes CapabilityBoundingSet=CAP_SYS_ADMIN MountFlags=slave [Install] WantedBy=multi-user.target UNIT echo "==> 6b. Systemd units - lesavka-server" cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-server.service >/dev/null [Unit] Description=lesavka gRPC relay After=network.target lesavka-core.service [Service] ExecStart=/usr/local/bin/lesavka-server Restart=always Environment="RUST_LOG=lesavka_server=trace" User=root [Install] WantedBy=multi-user.target UNIT echo "==> 6c. Systemd units - initialization" sudo systemctl daemon-reload sudo systemctl enable --now lesavka-core sudo systemctl restart lesavka-core echo "✅ lesavka-core installed and restarted..." sudo systemctl enable --now lesavka-server sudo systemctl restart lesavka-server echo "✅ lesavka-server installed and restarted..."