Client and server suite for Bazzite to allow wakeup and Steam account switching remotely
  • Go 77.1%
  • Shell 7%
  • Makefile 5.9%
  • JavaScript 5.5%
  • CSS 3%
  • Other 1.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-27 17:59:35 +02:00
cmd/bazinga strip binaries with -s -w and add nogui build tag for server-only builds 2026-07-26 21:29:26 +02:00
deploy/systemd rename: steambox -> bazinga (binary, service, module path) 2026-07-25 21:20:38 +02:00
docs/superpowers Downloadable clients now show a UI if launched without commands (#3) 2026-07-26 17:24:57 +02:00
internal feat(web): highlight recommended download based on detected OS/arch 2026-07-27 17:59:35 +02:00
.gitignore feat: sign macOS binaries with rcodesign self-signed certificate 2026-07-27 15:59:34 +02:00
AGENTS.md docs: update README and AGENTS.md for account registry, add handler and client tests 2026-07-26 21:14:42 +02:00
go.mod Downloadable clients now show a UI if launched without commands (#3) 2026-07-26 17:24:57 +02:00
go.sum Downloadable clients now show a UI if launched without commands (#3) 2026-07-26 17:24:57 +02:00
install.sh feat: add linux-arm64 cross-compile target 2026-07-27 16:38:45 +02:00
LICENSE.md docs: add CC0-1.0 license 2026-07-25 22:30:35 +02:00
Makefile feat: add linux-arm64 cross-compile target 2026-07-27 16:38:45 +02:00
rcodesign-cert.p12 feat: sign macOS binaries with rcodesign self-signed certificate 2026-07-27 15:59:34 +02:00
README.md docs: add security warning to README and account CRUD risks to SECURITY.md 2026-07-27 17:59:11 +02:00
screenshot.png Update web UI screenshot for v0.9 2026-07-26 17:59:38 +02:00
SECURITY.md docs: add security warning to README and account CRUD risks to SECURITY.md 2026-07-27 17:59:11 +02:00
VERSION v0.9.3 2026-07-27 16:02:35 +02:00

bazinga

A remote Steam account switcher for Linux gaming boxes using gamescope-session. Tested on Bazzite — should work on SteamOS too (eager for someone to try it). Lets family members switch the active Steam account remotely via CLI, GUI, or web UI, but only when no game is running.

Security warning: The HTTP API has no authentication and must not be exposed to the Internet. Forwarding port 8089 through a firewall or NAT lets anyone control your Steam session, add or remove accounts, and read your Steam usernames and Steam64 IDs. bazinga is designed for a trusted LAN only. See SECURITY.md for a full risk assessment.

How it works

A Go binary runs as a systemd user service on the Bazzite box, serving a REST API and embedded web UI. Switching an account uses Steam's CEF remote debugging interface (port 8080) to click the target user's tile on the login screen — this works in ~3-5 seconds without restarting Steam. Falls back to restarting the gamescope session if no login screen is visible.

Quick start

curl -fsSL https://git.sync.wtf/troed/bazinga/raw/branch/main/install.sh | bash

This downloads the latest binary, sets up the systemd user service, enables linger (if sudo is available), and starts the server. The service listens on :8089 (all interfaces).

To upgrade, just run the same command — it stops the old service, downloads the new binary, and restarts.

Build from source

make build          # native binary
make build-all      # cross-compile all platforms
make deploy HOST=<host>   # dev deploy via SSH

Client setup

Open the web UI at http://<hostname>:8089/ and download the binary for your platform. Put it on your PATH.

  • GUI mode: run bazinga (no arguments) — shows a window with connection status, account switching, pairing, and Wake-on-LAN.
  • CLI mode: run bazinga <subcommand> — works headless for scripts.

The downloaded binary is pre-configured with the server's address and MAC. No environment variables needed — just run it.

macOS: first run

macOS Gatekeeper will block binaries from unidentified developers. After downloading the darwin binary:

xattr -d com.apple.quarantine bazinga-darwin-arm64

Or right-click the binary in Finder and select Open. This only needs to be done once per download — the binary is properly code-signed (self-signed certificate) and will not get silently killed by the kernel.

Usage

bazinga                    Launch the GUI (window with status, accounts, pair, WOL)
bazinga serve              Start the HTTP server (run on Bazzite box)
bazinga status             Show current user and game status
bazinga switch <account>   Wake + wait + switch to account
bazinga pair <pin>         Send a 4-digit Remote Play pairing PIN to Steam
bazinga wake               Send wake-on-LAN magic packet
bazinga accounts           List available Steam accounts
bazinga accounts add <steam_id> <account_name> <persona_name>
                           Add an account to the registry
bazinga accounts remove <account_name>
                           Remove an account from the registry

Run with no arguments for the GUI — otherwise CLI subcommands behave as before. bazinga switch <account> is the all-in-one flow: it sends a WOL packet, polls until the server comes online, checks no game is running, verifies you're not already on the target account, issues the switch, and waits for Steam to restart with the new user.

bazinga pair <pin> is used for initial Steam Remote Play pairing. When you click "Connect" on your Remote Play client, it shows a 4-digit code. Run bazinga pair 4821 with that code, and bazinga enters it into the host's pairing dialog via CEF.

Web UI

Open http://<hostname>:8089/ in a browser. Shows the current user, game status, and available accounts with switch buttons. Also has download links for the client binary for each platform (served from /download/). Polls /api/status every 10 seconds.

Bazinga web UI

Configuration

Variable Default Description
STEAMBOX_HOST steambox.local:8089 Server address
STEAMBOX_MAC MAC address for WOL (auto-discovered via SSH/ARP)
STEAMBOX_SSH_USER bazzite SSH user for MAC discovery
BAZINGA_BINARIES_DIR ~/.local/share/bazinga/binaries Client binary downloads
BAZINGA_STEAM_SESSION_SERVICE gamescope-session-plus@steam.service systemd user service for Steam session restart

Game-running guard

The server rejects switch requests if a game process is detected. Detection scans /proc for wineserver, proton, or .exe processes, excluding known Steam helpers (steamwebhelper, steamservice.exe, steam.exe).

Native Linux games are detected by walking Steam's process tree for any process not in the known helper list.

Account registry

Bazinga maintains its own account list in ~/.config/bazinga/users.json because Steam's native user switching can drop accounts from loginusers.vdf. This file is the source of truth. Two-way sync with VDF:

  • VDF → users.json: On every status poll, auto-detect new accounts and update persona_name
  • users.json → VDF: Before each switch, inject any missing accounts so tiles appear on the login screen

First run bootstraps users.json from loginusers.vdf automatically.

Use bazinga accounts add and bazinga accounts remove to manage accounts from the CLI, or the REST API (POST /api/accounts, DELETE /api/accounts/{name}).

SteamOS compatibility

Nearly everything works on SteamOS as well. The only difference is the session service name used for the restart fallback. Set BAZINGA_STEAM_SESSION_SERVICE to the SteamOS service name if needed.

Development

go test ./internal/...   # run unit tests (VDF parser, no external deps)

Built for Go 1.26+. GUI uses gogpu/ui (WebGPU, CGO-free).

Creating a release

# Bump the version
echo "0.2.0" > VERSION

# Build + publish to the forge
make release FORGEJO_TOKEN=<api-token>

This cross-compiles all four platforms, creates a release on git.sync.wtf, and uploads the binaries as release artifacts. The token needs write:repository scope on the repo.

macOS binaries are signed with rcodesign using a self-signed certificate (rcodesign-cert.p12). The rcodesign binary is expected at tools/rcodesign — download it from the apple-platform-rs releases (x86_64-unknown-linux-musl).

License

This project is dedicated to the public domain under CC0 1.0 Universal. No attribution required — use it freely for any purpose.