Last active
October 21, 2025 16:50
-
-
Save raghavauppuluri13/62eb0db4c162e6fa77a654fcce17609b to your computer and use it in GitHub Desktop.
BracketBot Flashing Tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Jetson Orin Nano setup script | |
| # - Repairs NVIDIA local repo hash mismatches or disables broken file: repos | |
| # - Installs CUDA keyring, cuDSS (best-effort), cuDNN 9.3.0.75-1 (best-effort) | |
| # - Installs dev tools (git, git-lfs, ninja, venv, ffmpeg, etc.) | |
| # - Adds user to hardware groups | |
| # - Enables passwordless sudo | |
| # - Clones BracketBot repos | |
| # - Adds and runs ALSA setup script for ReSpeaker Lite | |
| # - Ends with su -l $USER | |
| set -euo pipefail | |
| export DEBIAN_FRONTEND=noninteractive | |
| # --- ensure root -------------------------------------------------------------- | |
| if [[ $EUID -ne 0 ]]; then | |
| echo "[i] Re-running with sudo..." | |
| exec sudo -E bash "$0" "$@" | |
| fi | |
| U=${SUDO_USER:-$(logname 2>/dev/null || echo "$USER")} | |
| UH=$(eval echo ~"$U") | |
| echo "[i] Starting setup for user: $U ($UH)" | |
| # --- helpers ------------------------------------------------------------------ | |
| repair_local_repo_dir() { | |
| local d="$1" | |
| [[ -d "$d" ]] || return 0 | |
| if [[ -f "$d/Packages.gz" && ! -s "$d/Packages" ]]; then | |
| echo "[i] Repair: creating $d/Packages from Packages.gz" | |
| gunzip -c "$d/Packages.gz" > "$d/Packages" || true | |
| fi | |
| } | |
| disable_local_file_repos() { | |
| echo "[!] Disabling broken local NVIDIA repos..." | |
| for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do | |
| [[ -f "$f" ]] || continue | |
| sed -i -E 's|^(\s*deb\s+.*file:/var/(cudnn|l4t-cuda|nv-tensorrt)-local)|# \1|g' "$f" | |
| done | |
| } | |
| apt_update_safe() { | |
| set +e | |
| apt-get clean | |
| rm -rf /var/lib/apt/lists/* | |
| apt-get update | |
| local rc=$? | |
| if [[ $rc -ne 0 ]]; then | |
| echo "[!] apt-get update failed, repairing local NVIDIA repos..." | |
| repair_local_repo_dir /var/cudnn-local-tegra-repo-ubuntu2204-9.3.0 | |
| repair_local_repo_dir /var/l4t-cuda-tegra-repo-ubuntu2204-12-6-local | |
| repair_local_repo_dir /var/nv-tensorrt-local-tegra-repo-ubuntu2204-10.3.0-cuda-12.5 | |
| apt-get clean | |
| rm -rf /var/lib/apt/lists/* | |
| apt-get update | |
| rc=$? | |
| if [[ $rc -ne 0 ]]; then | |
| disable_local_file_repos | |
| apt-get clean | |
| rm -rf /var/lib/apt/lists/* | |
| apt-get update | |
| rc=$? | |
| fi | |
| fi | |
| set -e | |
| return $rc | |
| } | |
| # --- system update ------------------------------------------------------------ | |
| echo "[i] Running apt repair/update..." | |
| apt_update_safe | |
| echo "[i] Installing developer packages..." | |
| apt-get install -y --no-install-recommends \ | |
| ca-certificates wget curl gnupg gzip \ | |
| git git-lfs \ | |
| python3.10-venv python3-pip \ | |
| htop ncdu ffmpeg \ | |
| ninja-build || true | |
| apt-get install -y ninja || true | |
| # --- CUDA keyring ------------------------------------------------------------- | |
| if ! dpkg -s cuda-keyring >/dev/null 2>&1; then | |
| echo "[i] Adding CUDA APT keyring..." | |
| wget -qO /tmp/cuda-keyring_1.1-1_all.deb \ | |
| https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/arm64/cuda-keyring_1.1-1_all.deb | |
| dpkg -i /tmp/cuda-keyring_1.1-1_all.deb | |
| rm -f /tmp/cuda-keyring_1.1-1_all.deb | |
| fi | |
| apt_update_safe | |
| echo "[i] Installing cuDSS (best effort)..." | |
| apt-get install -y cudss || true | |
| echo "[i] Installing cuDNN 9.3.0.75-1 (best effort)..." | |
| apt-get install -y \ | |
| libcudnn9-cuda-12=9.3.0.75-1 \ | |
| libcudnn9-dev-cuda-12=9.3.0.75-1 \ | |
| libcudnn9-samples=9.3.0.75-1 || true | |
| apt-mark hold libcudnn9-cuda-12 libcudnn9-dev-cuda-12 libcudnn9-samples || true | |
| # --- Python setup ------------------------------------------------------------- | |
| echo "[i] Upgrading pip/build tools..." | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install --upgrade build setuptools | |
| # --- Groups ------------------------------------------------------------------- | |
| echo "[i] Ensuring group memberships for ${U}..." | |
| for g in sudo dialout video audio spi render i2c; do | |
| getent group "$g" >/dev/null || groupadd "$g" | |
| if ! id -nG "$U" | tr ' ' '\n' | grep -qx "$g"; then | |
| usermod -aG "$g" "$U" | |
| echo " - added $U to $g" | |
| fi | |
| done | |
| # --- Passwordless sudo -------------------------------------------------------- | |
| SUDO_FILE="/etc/sudoers.d/99-${U}-nopasswd" | |
| echo "[i] Enabling passwordless sudo for ${U}..." | |
| echo "${U} ALL=(ALL) NOPASSWD:ALL" > "$SUDO_FILE" | |
| chmod 440 "$SUDO_FILE" | |
| # --- Clone/Update Repos ------------------------------------------------------- | |
| as_user() { sudo -u "$U" -H bash -lc "$*"; } | |
| clone_or_update_repo() { | |
| local url="$1" | |
| local branch="${2:-}" | |
| local name="${3:-$(basename "$url" .git)}" | |
| as_user "mkdir -p '$UH'" | |
| if [[ -d "$UH/$name/.git" ]]; then | |
| echo "[i] Updating $name ..." | |
| as_user " | |
| set -e | |
| cd '$UH/$name' | |
| git fetch --all --prune | |
| [[ -n '$branch' ]] && git checkout '$branch' || true | |
| git pull --ff-only || true | |
| git submodule update --init --recursive | |
| " | |
| else | |
| echo "[i] Cloning $name ..." | |
| if [[ -n "$branch" ]]; then | |
| as_user "cd '$UH' && git clone --recursive -b '$branch' '$url' '$name'" | |
| else | |
| as_user "cd '$UH' && git clone --recursive '$url' '$name'" | |
| fi | |
| fi | |
| chown -R "$U":"$U" "$UH/$name" || true | |
| } | |
| clone_or_update_repo "https://github.com/Bracket-Bot-Inc/BracketBotOS.git" "jetson" "BracketBotOS" | |
| clone_or_update_repo "https://github.com/Bracket-Bot-Inc/BracketBotApps.git" "jetson" "BracketBotApps" | |
| printf 'dashboard\nhey_bracketbot\n' > BracketBotApps/.autostart | |
| printf 'OPENAI_API_KEY=' > BracketBotApps/.env | |
| as_user "git lfs install --skip-repo || true" | |
| # --- ALSA setup (adds your install_alsa.sh and runs it) ----------------------- | |
| echo "[i] Writing ALSA installer to $UH/install_alsa.sh ..." | |
| cat > "$UH/install_alsa.sh" <<'EOS_ALSA' | |
| #!/usr/bin/env bash | |
| # Configure ALSA for ReSpeaker Lite on Jetson Orin Nano | |
| # Makes ReSpeaker Lite (USB card 0) the default audio device | |
| set -euo pipefail | |
| # Re-run with sudo if not root | |
| if [[ $EUID -ne 0 ]]; then | |
| echo "[i] Re-running with sudo..." | |
| exec sudo -E bash "$0" "$@" | |
| fi | |
| U=${SUDO_USER:-$(logname 2>/dev/null || echo "$USER")} | |
| UH=$(eval echo ~"$U") | |
| echo "[i] Configuring ALSA for ReSpeaker Lite..." | |
| # Create user .asoundrc for ReSpeaker device alias | |
| cat > "$UH/.asoundrc" <<'EOF' | |
| # BracketBot ALSA Configuration | |
| # Forces ReSpeaker Lite (USB card 0) as default device | |
| pcm.!default { | |
| type hw | |
| card 0 | |
| device 0 | |
| } | |
| ctl.!default { | |
| type hw | |
| card 0 | |
| } | |
| # Named device alias for explicit access | |
| pcm.respeaker { | |
| type hw | |
| card 0 | |
| device 0 | |
| } | |
| ctl.respeaker { | |
| type hw | |
| card 0 | |
| } | |
| EOF | |
| chown "$U":"$U" "$UH/.asoundrc" | |
| chmod 644 "$UH/.asoundrc" | |
| echo " ✓ Created $UH/.asoundrc" | |
| # Update system /etc/asound.conf to point to ReSpeaker (card 0) instead of APE | |
| if [[ -f /etc/asound.conf ]]; then | |
| cp /etc/asound.conf /etc/asound.conf.backup | |
| sed -i 's|pcm "hw:APE,0"|pcm "hw:0,0"|g' /etc/asound.conf | |
| echo " ✓ Updated /etc/asound.conf to use card 0 (ReSpeaker)" | |
| echo " ✓ Backup saved to /etc/asound.conf.backup" | |
| fi | |
| echo | |
| echo "[✓] ALSA configuration complete!" | |
| echo " • Default device: ReSpeaker Lite (card 0)" | |
| echo " • Named alias: 'respeaker' available" | |
| echo " • User config: $UH/.asoundrc" | |
| echo " • System config: /etc/asound.conf" | |
| echo | |
| echo "You may need to restart audio applications or run 'restart speakerphone'" | |
| EOS_ALSA | |
| chown "$U":"$U" "$UH/install_alsa.sh" | |
| chmod +x "$UH/install_alsa.sh" | |
| # Run it targeting the correct user (ensure SUDO_USER is set) | |
| SUDO_USER="$U" bash "$UH/install_alsa.sh" | |
| # --- Avahi (mDNS) configuration ---------------------------------------------- | |
| # Get hostname strictly from the `hostname` command | |
| HN=$(hostname -s) | |
| awk -v hn="$HN" 'BEGIN{sec=0;done=0} /^\[server\]/{sec=1} /^\[/{if($0!~/^\[server\]/)sec=0} sec && sub(/^[#[:space:]]*host-name[[:space:]]*=.*/,"host-name="hn){done=1} {print} END{if(!done){print ""; print "[server]"; print "host-name="hn}}' \ | |
| /etc/avahi/avahi-daemon.conf | sudo tee /etc/avahi/avahi-daemon.conf >/dev/null | |
| systemctl restart avahi-daemon 2>/dev/null || true | |
| # --- Final -------------------------------------------------------------------- | |
| echo | |
| echo "[✓] Setup complete." | |
| echo " • Passwordless sudo ENABLED for ${U}" | |
| echo " • Repos cloned under: $UH/{BracketBotOS,BracketBotAI,BracketBotApps}" | |
| echo " • ALSA configured for ReSpeaker Lite (card 0)" | |
| echo " • Switching to a fresh login shell for ${U}..." | |
| echo | |
| exec su -l "$U" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment