Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save vocino/f110c84e5829e64c1bcff48bdb9a4763 to your computer and use it in GitHub Desktop.

Select an option

Save vocino/f110c84e5829e64c1bcff48bdb9a4763 to your computer and use it in GitHub Desktop.
Battle.net on Linux - CachyOS RTX 3090 simple robust setup (One Prefix, One Manager, One Shortcut)

Battle.net on Linux: My CachyOS RTX 3090 Setup (One Prefix, One Manager, One Shortcut)

I run WoW retail, Diablo IV, Hearthstone, Heroes of the Storm, and Overwatch 2 native on CachyOS, RTX 3090 24GB, Wayland KDE. This is the setup that works right now. One prefix, one manager, one shortcut.

Five launchers and three Proton versions break. I ran that.

TL;DR: The Opinionated Version

  • One shared Battle.net prefix: ~/Games/battlenet
  • One manager: Lutris 0.5.22
  • One runner: proton-cachyos-native (system package, updates with paru -Syu) + fallback GE-Proton11-3
  • One desktop file: Battle.netExec=/usr/bin/lutris lutris:rungame/battlenet
  • 4 env vars total, GameMode on, MangoHud off by default

That's it. Everything else is extra.

Problem

Battle.net Agent expects one location for friends, chat, and updates. Separate prefixes duplicate 50GB of runtime and run five Agents against each other. Layering launch scripts with umu-run, mangohud --dlsym, and manual PROTONPATH adds .build.info age checks that force the launcher.

This guide is one prefix, one Lutris entry, one desktop file. System packages update with the system.

My System (So You Know Where I'm Coming From)

  • CachyOS rolling, linux-cachyos 7.1.5-1-cachyos primary, linux-cachyos-lts fallback always installed
  • i9-10900KF 10c/20t, 32GB RAM, RTX 3090 24GB, driver 610.43.03 nvidia-open
  • Wayland KDE, not X11
  • Disk: single NVMe, LUKS2 → btrfs @ @home @cache @log @tmp. Snapshots via snapper + limine-snapper-sync. Rollback is "reboot into snapshot in Limine menu"
  • Perf stack: ananicy-cpp active, scx_lavd (sched-ext), gamemode 1.8.2, mangohud 0.8.4 installed
  • Kernel has ntsync/dev/ntsync present, lsmod | grep ntsync

I keep @home on btrfs with snapshots, @cache mounted at /var/cache excluded from snapshots. Game shaders should not be snapshotted or your snapshots balloon.

Free space right now: 2.8TiB on /home. WoW retail ~150GB, D4 ~120GB, OW2 ~60GB, HS ~5GB, HotS ~20GB. You need ~355GB for all 5.

How to Install

paru -S lutris proton-cachyos-native gamemode mangohud lib32-gamemode lib32-mangohud umu-launcher

proton-cachyos-native is the native build in cachyos repo, not the AUR alias. It is wine-11.0 (CachyOS) with NTSync default and perf patches for this kernel. GE-Proton11-3 lives in ~/.local/share/Steam/compatibilitytools.d/ as fallback via protonup-qt, but I don't pin to it.

Check:

nvidia-smi
vulkaninfo --summary | grep "RTX 3090"
lsmod | grep ntsync; ls -l /dev/ntsync
systemctl is-active ananicy-cpp
systemctl --user is-active gamemoded

All should be active.

How to Use

One command:

lutris:rungame/battlenet

Or click Battle.net in the app launcher, pin to taskbar. Details for a reliable pin are in One Shortcut below.

The Prefix: Single Shared

Mine:

~/Games/battlenet/                  # STEAM_COMPAT_DATA_PATH + Lutris prefix
  drive_c/Program Files (x86)/Battle.net/
  drive_c/Program Files (x86)/World of Warcraft/_retail_/Wow.exe
  drive_c/Program Files (x86)/Diablo IV/
  drive_c/Program Files (x86)/Overwatch/
  pfx -> .                          # umu tracking self-ref
  GLCache -> ~/.cache/wow-shaders/nv
  config_info, version, tracked_files

config_info and tracked_files are umu-launcher tracking. Harmless if you keep Lutris as sole manager. I deleted the duplicate empty prefix ~/Games/umu/umu-default/ (859M) that umu created on first run.

Lutris YAML: The Only Config That Matters

File: ~/.config/lutris/games/battlenet-standard-*.yml

Current minimal version:

game:
  arch: win64
  exe: drive_c/Program Files (x86)/Battle.net/Battle.net Launcher.exe
  prefix: /home/vocino/Games/battlenet
  slug: battlenet-standard

system:
  env:
    DXVK_STATE_CACHE_PATH: /home/vocino/.cache/wow-shaders/dxvk
    VKD3D_SHADER_CACHE_PATH: /home/vocino/.cache/wow-shaders/vkd3d
    __GL_SHADER_DISK_CACHE_PATH: /home/vocino/.cache/wow-shaders/nv
    PROTON_USE_NTSYNC: '1'
    PROTON_ENABLE_NVAPI: '1'
    PROTON_ENABLE_NGX_UPDATER: '1'
    VKD3D_CONFIG: 'dxr'
  gamemode: true
  mangohud: false
  exclude_processes: Agent.exe "Battle.net Helper.exe"

wine:
  version: proton-cachyos-native
  battleye: false
  eac: false
  fsr: false
  overrides:
    locationapi: d

Four real Proton vars. I removed:

  • WINEESYNC=1, WINEFSYNC=1 — redundant with PROTON_USE_NTSYNC=1 and /dev/ntsync
  • WINE_LARGE_ADDRESS_AWARE=0 — broke Heroes 32-bit (OOM past 2GB), leave default LAA enabled
  • __GL_SHADER_DISK_CACHE_SIZE=1073741824 + __GL_THREADED_OPTIMIZATIONS=1 — 1GB cap caused D4 stutter, threaded optim deprecated on 610.xx
  • MANGOHUD=0 env — use Lutris boolean mangohud:false instead, cleaner

Why VKD3D_CONFIG=dxr globally? Only WoW/D4/OW2 are D3D12 and use vkd3d. HotS/Hearthstone are DX11, ignore it. No harm, simpler than per-game profiles.

locationapi:d disables geolocation — stops Wine polling location.

Shader Cache: Keep It Out Of Snapshots But Keep It Simple

Before: 31M in ~/.cache/wow-shaders/nv plus nested duplicate nv/GLCache/.

Now:

~/.cache/wow-shaders/
  dxvk/  # DXVK state cache, grows with DX11 titles
  nv/    # NVIDIA GLCache, 13M after cleanup
  vkd3d/ # vkd3d-proton cache, will fill with D4/WoW

And in prefix:

~/Games/battlenet/GLCache -> ~/.cache/wow-shaders/nv

I kept it in ~/.cache rather than moving to /var/cache/battlenet-shaders that needs root and bind mount. This stays simple, still avoids snapper bloat because it's a symlink outside drive_c.

Ensure writable:

mkdir -p ~/.cache/wow-shaders/{dxvk,nv,vkd3d}

Dosdevices: Security and File Picker Speed

Lutris default creates:

s: -> /home
w: -> /mnt
x: -> /home/vocino
z: -> /

Any Windows exe (including Chromium Battle.net Helper.exe) can read /, ~/.ssh, /mnt. Wine file dialogs crawl the host FS, slow.

I deleted them:

rm ~/Games/battlenet/dosdevices/s: ~/Games/battlenet/dosdevices/w: ~/Games/battlenet/dosdevices/x: ~/Games/battlenet/dosdevices/z:
ls -l ~/Games/battlenet/dosdevices/
# only c: -> ../drive_c and d:: -> /dev/sr0 remain + com ports

Faster dialogs, no anti-cheat false positive from FS scan.

Battle.net Client Config

File: drive_c/users/steamuser/AppData/Roaming/Battle.net/Battle.net.config

Important:

"HardwareAcceleration": "false",
"Sound": { "Enabled": "false" }

HardwareAcceleration false avoids CEF GPU crashes on Wine — white or black window. I keep it false intentionally.

Also cleaned bloat:

  • Battle.net.17350/ old build — deleted, kept only Battle.net.17651 latest
  • .../AppData/Local/Battle.net/BrowserCaches/ — 71M → 1.4M, safe to delete (not login cookies)
  • Login stays in CachedData.db

One Shortcut: Pinnable to Taskbar (CachyOS KDE)

I had 5 .desktop files plus 3 launch scripts doing umu-run + mangohud --dlsym with manual PROTONPATH. All had .build.info age logic that forced Battle.net unexpectedly.

Now one: ~/.local/share/applications/Battle.net.desktop

[Desktop Entry]
Name=Battle.net
GenericName=Blizzard Battle.net
Comment=Blizzard Battle.net - CachyOS Optimized (proton-cachyos-native, NTSync, NVAPI, GameMode)
Exec=/usr/bin/lutris lutris:rungame/battlenet
Icon=lutris_battlenet
Type=Application
Categories=Game;
StartupWMClass=battle.net.exe
MimeType=x-scheme-handler/battlenet;
Keywords=battlenet;blizzard;wow;diablo;overwatch;hearthstone;heroes;
Terminal=false
StartupNotify=false
PrefersNonDefaultGPU=false

Why this works for pinning:

  • Exec=/usr/bin/lutris lutris:rungame/battlenet — explicit binary, KDE icontasks needs full path
  • Icon=lutris_battlenet — actual file ~/.local/share/icons/hicolor/128x128/apps/lutris_battlenet.png
  • StartupWMClass=battle.net.exe — matches Wine window class, no duplicate icon

Pin: Meta → type Battle.net → right-click → Add to Task Manager, or run it then right-click running icon → Pin.

Validate:

desktop-file-validate ~/.local/share/applications/Battle.net.desktop
update-desktop-database ~/.local/share/applications/
kbuildsycoca6

Per-Game Peak Quality (RTX 3090)

World of Warcraft Retail

WTF/Config.wtf:

SET gxApi "D3D12"
SET GxAllowRTShadows "1"
SET shadowRt "3"
SET GxLowLatencyMode "2"
SET GxAllowLowLatency "1"
SET GxRefresh "120"
SET GxMaximize "1"
SET vsync "0"
SET graphicsQuality "9"

D3D12 is best on Linux via vkd3d-proton now. RT shadows on 3090 fine. Keep VKD3D_CONFIG=dxr.

Diablo IV

  • Enable DLSS Quality in-game, NGX updater will auto-update DLSS dlls
  • First launch stutter is shader cache building in ~/.cache/wow-shaders/vkd3d, second launch smooth
  • Needs >100GB, ensure space: df -h ~/Games/battlenet

Overwatch 2

  • No EAC/BattEye, uses Defense Matrix — no Proton EasyAntiCheat runtime needed
  • Best: borderless, Reflex ON+Boost via NVAPI (PROTON_ENABLE_NVAPI=1)
  • Keep MangoHud OFF for comp — Defense Matrix sometimes flags overlays. YAML has mangohud:false. Toggle when benchmarking: MANGOHUD=1 lutris:rungame/battlenet

Hearthstone and Heroes of the Storm

  • No RT, VKD3D_CONFIG=dxr ignored
  • Hearthstone benefits from locationapi:d override
  • Heroes is 32-bit — needs Large Address Aware (fixed by removing WINE_LARGE_ADDRESS_AWARE=0)

Verification: battlenet-doctor

Tiny checker ~/.local/bin/battlenet-doctor:

#!/usr/bin/env bash
nvidia-smi
vulkaninfo --summary | grep RTX
lsmod | grep ntsync; ls -l /dev/ntsync
systemctl is-active ananicy-cpp
systemctl --user is-active gamemoded
ls -l ~/Games/battlenet/dosdevices/ | grep -E "c:|d::"
cat ~/.config/lutris/games/battlenet-standard-*.yml
du -sh ~/.cache/wow-shaders/*
ls -l ~/.local/share/lutris/runners/wine/
sudo snapper -c root list | tail

Current output all green:

  • RTX 3090 610.43.03 5% idle, Vulkan 1.4.341
  • ntsync module 20480 + /dev/ntsync
  • ananicy-cpp active (topology 20 CPUs, 1 LLC, SMT on)
  • gamemoded active
  • dosdevices only c: d::
  • YAML minimal + gamemode true
  • shader caches writable (nv 13M)
  • runners: proton-cachyos-native + GE-Proton11-3 fallback
  • snapper #442 pre-bnet + #443-444 proton-cachyos install

Update Flow: One Command, Easy Rollback

paru -Syu

Updates proton-cachyos-native, nvidia-open, linux-cachyos, ananicy-cpp, lutris. protonup-qt updates GE-Proton11-3 optional.

Battle.net client self-updates inside prefix (single Battle.net.17651 folder).

Breakage? Rollback:

sudo snapper -c root list
# Reboot → Limine menu → snapshot #442

Maintenance Script

~/.local/bin/battlenet-maintenance clears safe caches, not login tokens:

PREFIX=~/Games/battlenet
rm -rf $PREFIX/drive_c/ProgramData/Battle.net/Agent/Cache/*
rm -rf $PREFIX/drive_c/ProgramData/Blizzard\ Entertainment/Battle.net/Cache/*
rm -rf $PREFIX/drive_c/Program\ Files\ \(x86\)/World\ of\ Warcraft/_retail_/Cache/*
rm -rf ~/Games/battlenet/drive_c/users/steamuser/AppData/Local/Battle.net/Cache/*

Do NOT delete BrowserCaches/ entirely — I only cleared it once during cleanup.

Troubleshooting

  • Battle.net white/blank: Check Battle.net.config HardwareAcceleration false. Already set.
  • OW2 kicks for overlay: Launch with MANGOHUD=0, mangohud:false in YAML.
  • HotS crashes after 2GB: Fixed by removing WINE_LARGE_ADDRESS_AWARE=0
  • Stutter D4 first run: Shader cache building in ~/.cache/wow-shaders/vkd3d
  • NTSync missing after kernel update: lsmod | grep ntsync, check linux-cachyos-lts fallback still bootable

What I Tried and Abandoned (Brittle)

  • Per-game direct launchers: wow-launch, hearthstone-launch with umu-run + mangohud --dlsym, manual PROTONPATH, .build.info age check that forced BNet after 24h. Deleted.
  • GE-Proton-current symlink dance: Atomic swap via script — more moving parts than system package.
  • bnetctl associative array: Per-game VKD3D_CONFIG profiles — over-engineered, global dxr works anyway.
  • Steam Hub Non-Steam shortcuts: Needs Steam running, double Agent notifications, overlay conflicts.
  • Moving shaders to /var/cache: Needs root, bind mount, brittle for single user.

Simple wins.

What's Inside

~/Games/battlenet/                               # single prefix
~/.config/lutris/games/battlenet-standard-*.yml  # 4 env vars minimal
~/.local/share/applications/Battle.net.desktop   # one pinnable shortcut
~/.cache/wow-shaders/{dxvk,nv,vkd3d}             # shader caches
~/.local/bin/battlenet-doctor                    # verify
~/.local/bin/battlenet-maintenance               # safe cleaner

Run:

lutris:rungame/battlenet
# or click Battle.net in launcher, pin to taskbar

That is it. No five launchers, no symlink maze. One hub, updates with system, peak quality on 3090.


System: CachyOS rolling, 7.1.5-1-cachyos, RTX 3090 24GB 610.43.03, Wayland KDE, ntsync. Prefix: ~/Games/battlenet 2.8TiB free. Runner: proton-cachyos-native 1:11.0.20260703-1 (wine-11.0 CachyOS), fallback GE-Proton11-3. Last verified: battlenet-doctor all green, dosdevices only c: d::, GLCache 13M.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment