# My Wife’s Steam Deck Is a Server Now. She Doesn’t Know Yet. 🫠

> Source: <https://dev.to/pmdroid/my-wifes-steam-deck-is-a-server-now-she-doesnt-know-yet-288c>
> Published: 2026-09-07 22:45:01+00:00

Hey tech adventurers! 👋

What if the hardware you already own could become part of your homelab?

That spare Linux box. An old Mac. A mini PC sitting under the TV.

Or, in my case, my wife’s Steam Deck. 😅

She can’t play 24/7, so when the Deck is idle, I figured its CPU might as well do something useful.

So I installed BarkVisor on SteamOS and turned it into another Device in my Home. It can run VMs, join my other Mac and Linux machines, and even run small local AI models with Ollama.

And yes, it still plays games. I’m not that terrible of a husband.

This post is the “I actually did it on a Steam Deck” walkthrough: practical, step-by-step, and no kernel seminar.

The bigger idea, though, is simple:

You probably already have a machine that could run BarkVisor.

| Role | Machine | Listens | 
|---|---|---|
| **Home** (UI + control) | Mac/Linux on the LAN | `:7777` HTTP,`:7778` mTLS | 
| **Device** (this tutorial) | Steam Deck (or similar SteamOS / handheld Linux) | `:7777` API only,`:7778` agent, Ollama`:11434` | 

Example LAN: Home `192.168.10.10`, Deck `192.168.8.133`.

You **never** open the Deck’s `:7777` in a browser. Pair once. Then lives in BarkVisor.

Same class of machine: Steam Deck and Lenovo Legion Go–style handhelds running SteamOS / Arch-ish Linux. The unlock + `pacman` bits below are **SteamOS / Deck-specific**. Adjust paths (`/home/deck`) if your user isn’t `deck`.

Switch to **Desktop Mode**. Set a sudo password if you haven’t (`passwd`).

SteamOS root is tiny (~5GB). BarkVisor, models, and VM disks go under **`/home`**. Do not fill the root partition. Future-you will thank present-you.

Unlock the OS and trust SteamOS package keys (once — when `pacman` complains about unknown trust / GitLab CI Package Builder):

```
sudo steamos-readonly disable
sudo pacman-key --init
sudo pacman-key --populate archlinux
sudo pacman-key --populate holo
sudo pacman-key --lsign-key 889B5EBDDD505A683621900DAF1D2199EF0A3CCF
```

Install the VM stack. Arch/SteamOS splits QEMU — `qemu-base` alone is **not** enough for BarkVisor’s `virtio-gpu-pci`, and cloud-init needs `mkisofs` from `cdrtools`:

```
sudo pacman -S qemu-base edk2-ovmf \
  qemu-hw-display-virtio-gpu qemu-hw-display-virtio-gpu-pci \
  cdrtools swtpm
```

Sanity check (you want a line with `virtio-gpu-pci` and a writable `/dev/kvm`):

```
command -v qemu-system-x86_64 qemu-img mkisofs
qemu-system-x86_64 -device help | grep virtio-gpu-pci
ls /usr/share/edk2/x64/OVMF_CODE.4m.fd
ls -l /dev/kvm
```

**Do not** pipe `install.sh` into `sudo` on SteamOS. Use the Linux tarball under home. Agent mode = no SPA on the Deck. The Deck is a worker, not a kiosk.

Current release at time of writing: **`1.0.0-alpha.3`** (check [GitHub releases](https://github.com/pmdroid/barkvisor/releases) if you’re reading this from the future).

```
VER=1.0.0-alpha.3   # or whatever current release is
PREFIX="$HOME/.local/opt/barkvisor"
mkdir -p "$PREFIX" "$HOME/.local/share/barkvisor" "$HOME/.local/bin" \
  "$HOME/.config/barkvisor" "$HOME/.config/systemd/user"

cd /tmp
curl -fL -O "https://github.com/pmdroid/barkvisor/releases/download/v${VER}/barkvisor-${VER}-linux-x86_64.tar.gz"
curl -fL -O "https://github.com/pmdroid/barkvisor/releases/download/v${VER}/barkvisor-${VER}-linux-x86_64.tar.gz.sha256"
sha256sum -c "barkvisor-${VER}-linux-x86_64.tar.gz.sha256"

tar -xzf "barkvisor-${VER}-linux-x86_64.tar.gz"
SRC="barkvisor-${VER}-linux-x86_64/root/usr/local"
install -m 0755 "$SRC/bin/barkvisor" "$PREFIX/bin/barkvisor"
ln -sfn barkvisor "$PREFIX/bin/barkvisor-agent"
cp -a "$SRC/lib/barkvisor" "$PREFIX/lib/"
# skip share/barkvisor/frontend — agent mode, no SPA
```

CLI wrapper (sets the bundled Swift `LD_LIBRARY_PATH` — yes, Swift on a Steam Deck, we’re living deliciously):

``` bash
cat > "$HOME/.local/bin/barkvisor" << 'EOF'
#!/usr/bin/env bash
PREFIX="${HOME}/.local/opt/barkvisor"
export LD_LIBRARY_PATH="${PREFIX}/lib/barkvisor/swift:${PREFIX}/lib/barkvisor/compat${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec -a "$(basename "$0")" "${PREFIX}/bin/barkvisor" "$@"
EOF
chmod +x "$HOME/.local/bin/barkvisor"
ln -sfn barkvisor "$HOME/.local/bin/barkvisor-agent"

grep -q '.local/bin' ~/.bashrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"
```

Env + user systemd service (data on home, no frontend dir):

Click to expand: barkvisor.env + barkvisor-agent.service

```
cat > "$HOME/.config/barkvisor/barkvisor.env" << EOF
BARKVISOR_PORT=7777
BARKVISOR_DATA_DIR=$HOME/.local/share/barkvisor
BARKVISOR_SOCKET_DIR=$XDG_RUNTIME_DIR/barkvisor
HOME=$HOME
LD_LIBRARY_PATH=$HOME/.local/opt/barkvisor/lib/barkvisor/swift:$HOME/.local/opt/barkvisor/lib/barkvisor/compat
EOF

cat > "$HOME/.config/systemd/user/barkvisor-agent.service" << EOF
[Unit]
Description=BarkVisor API-only Device daemon
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=$HOME/.local/share/barkvisor
EnvironmentFile=-$HOME/.config/barkvisor/barkvisor.env
ExecStart=$HOME/.local/opt/barkvisor/bin/barkvisor-agent
Restart=on-failure
RestartSec=3
TimeoutStopSec=8
KillMode=mixed
RuntimeDirectory=barkvisor
LimitNOFILE=65536

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user enable --now barkvisor-agent.service
curl -sS http://127.0.0.1:7777/api/health
barkvisor-agent doctor
```

Health should be `"status":"ok"`. `GET http://127.0.0.1:7777/` returning JSON **404** is correct for agent-only. You’re not broken. You’re disciplined.

**SteamOS / Desktop Mode note:** Desktop Mode already has a user session, so the service starts with that session. It will **not** start in Game Mode unless you enable lingering (`loginctl enable-linger deck`, needs root).

On **Home** (the machine that already finished BarkVisor setup):

`http://<home-ip>:7777`
`192.168.10.10`)` barkvisor://pair/v1?code=…&host=…&port=7777&agentPort=7778&hostId=…&fp=…`
The short printed code is **not** enough. Ask me how I know. 😅

On the Deck, with the agent already up:

Click to expand: join with full barkvisor:// offer

```
barkvisor-agent join --code 'barkvisor://pair/v1?code=…&host=192.168.10.10&port=7777&agentPort=7778&hostId=…&fp=…'
```

Or set `BARKVISOR_JOIN_CODE` in `barkvisor.env` **before first start only**.

With a current build, Home should hop immediately. Refresh Home: the Deck appears reachable, workload counts populate. Join talks HTTP to Home `:7777`; ongoing control is mTLS to the Deck `:7778`.

Confirm on the Deck:

Click to expand: confirm 7777 + 7778 listening

```
ss -ltn | grep -E '7777|7778'
# LISTEN 0.0.0.0:7777 and 0.0.0.0:7778
```

Want Home’s **Models** UI to point at the handheld? Keep Ollama under `~/.local` too — not `/usr/local`.

```
mkdir -p ~/.local ~/.ollama/models
curl -fsSL https://ollama.com/download/ollama-linux-amd64.tar.zst \
  | tar --zstd -xf - -C ~/.local
```

Listen on **all interfaces** so Home and guest VMs can reach it. Example user unit knobs:

```
# ~/.config/systemd/user/ollama.service
# Environment=OLLAMA_HOST=0.0.0.0:11434
# Environment=OLLAMA_MODELS=/home/deck/.ollama/models
# Environment=OLLAMA_IGPU_ENABLE=1
# ExecStart=/home/deck/.local/bin/ollama serve

systemctl --user enable --now ollama.service
curl -sS http://127.0.0.1:11434/api/version
curl -sS http://192.168.8.133:11434/api/version   # use your Deck LAN IP
ollama pull llama3.2   # example
```

Steam Deck iGPU is ignored unless `OLLAMA_IGPU_ENABLE=1`. Then from Home: Settings / Models pointed at `http://<deck-ip>:11434`. Guest VMs on NAT see the Deck as `10.0.2.2:11434`.

On Home, with the Deck selected (or **Create VM → this Device**):

NAT SSH: add a port forward (e.g. host `2222` → guest `22`) on that VM, then from your laptop:

```
ssh -p 2222 ubuntu@192.168.8.133
```

(Guest default user is `ubuntu` if you used the Ubuntu template. Swap in your Deck’s LAN IP.)

```
systemctl --user status barkvisor-agent ollama
journalctl --user -u barkvisor-agent -f
barkvisor-agent doctor

# disks / images live here
du -sh ~/.local/share/barkvisor/{disks,images,efivars}
```

Home is the UI: VMs, VNC, serial, images, pairing. The Deck just works (or complains in `journalctl`).

**Good:** extra QEMU capacity on the LAN. Ollama on the Deck iGPU (~16GB visible VRAM on a Z2 Go-class machine). Agent-only so you’re not burning cycles on a SPA nobody will open.

| Symptom | Check | 
|---|---|
| Home: TLS handshake failed | `:7778` up; join completed; restart`barkvisor-agent` once if you’re on an older build | 
| `virtio-gpu-pci` is not a valid device | `pacman -S qemu-hw-display-virtio-gpu qemu-hw-display-virtio-gpu-pci` | 
| `mkisofs` /`genisoimage` not found | `pacman -S cdrtools` | 
| BdsDxe no bootable option | Cloud clone must leave GPT EFI PART at LBA 1; never run `sgdisk` on a`.qcow2` file | 
| pacman “unknown trust” | `pacman-key --lsign-key 889B5EBDDD505A683621900DAF1D2199EF0A3CCF` | 
| Ollama only on localhost | `OLLAMA_HOST=0.0.0.0:11434` and restart the user unit | 

Closing / pizza 🍕

Steam Deck as a headless BarkVisor Device: agent tarball in $HOME, SteamOS QEMU plus virtio-gpu and cdrtools, pair with a full barkvisor:// offer, optional Ollama on 0.0.0.0:11434. Control everything from Home on the LAN. The Deck just runs VMs and models.

Was this a responsible use of a gaming handheld? Debatable. Does it make my LAN slightly more overbuilt? Absolutely. Built with ❤️ and questionable infrastructure decisions.

P.S. Don’t want to click through every step yourself? Paste this post to your agent. They’ll have no problem doing it. 🤖

More: barkvisor.dev · github.com/pmdroid/barkvisor
