Unofficial Project Ebonhold updater and Proton launcher for Linux
  • Shell 62.4%
  • Python 37.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-19 20:51:25 +02:00
tests fix(updater): avoid redundant client downloads 2026-08-17 19:15:38 +02:00
.gitignore Initial Ebonhold Linux launcher 2026-08-12 13:35:10 +02:00
addons.json Use official Ebonhold ElvUI package 2026-08-12 18:26:29 +02:00
ebonhold-base-client.py fix(updater): avoid redundant client downloads 2026-08-17 19:15:38 +02:00
ebonhold-update fix(updater): avoid redundant client downloads 2026-08-17 19:15:38 +02:00
project-ebonhold.desktop.in Initial Ebonhold Linux launcher 2026-08-12 13:35:10 +02:00
README.md fix(updater): avoid redundant client downloads 2026-08-17 19:15:38 +02:00
start-ebonhold-linux.sh feat: support local ClientExt workaround guard 2026-08-19 20:51:25 +02:00

Ebonhold Linux launcher

An unofficial Linux updater and launcher for Project Ebonhold. It downloads the official client files through Ebonhold's launcher API and runs the game with GE-Proton. Downloads are resumable and installed atomically. The updater can verify the installed base client against the official remote ZIP and download only missing or damaged files.

This repository contains no game files, Project Ebonhold code, authentication tokens, or account credentials.

Requirements

  • Bash, Python 3, curl, jq, unzip, coreutils, and util-linux (flock). On NixOS, the updater falls back to nix shell nixpkgs#python3 when Python is not in PATH.
  • Steam with a recent GE-Proton installed
  • steam-run (on NixOS)
  • Kitty or another xterm -e compatible terminal for update progress
  • Optional: notify-send

The launcher defaults to this layout:

/games/Ebonhold/
├── ebonhold-update
├── start-ebonhold-linux.sh
├── compatdata/
└── ebonhold/
    └── Wow.exe

Clone the repository into /games/Ebonhold, or set EBONHOLD_ROOT to another directory. The game directory can be overridden separately with EBONHOLD_GAME_DIR.

Authentication

For most users, just run the interactive login:

./ebonhold-update login
./ebonhold-update verify-login

The password is used only for that request and is not saved. The resulting launcher token is stored with mode 0600 at $XDG_STATE_HOME/ebonhold/token (normally ~/.local/state/ebonhold/token). Nothing is written into the repository or game directory.

For unattended use, credentials can instead come from files or environment variables. File references are preferable because values do not enter the process environment:

EBONHOLD_USERNAME_FILE=/run/secrets/ebonhold-user \
EBONHOLD_PASSWORD_FILE=/run/secrets/ebonhold-password \
./ebonhold-update login

EBONHOLD_USERNAME and EBONHOLD_PASSWORD are also supported. An existing token can be supplied through EBONHOLD_TOKEN_FILE or EBONHOLD_TOKEN.

Optional agent-secret backend

If agent-secret is installed and these entries exist, the updater automatically uses them instead of its token file:

ebonhold.credentials.username
ebonhold.credentials.password
ebonhold.token

Set EBONHOLD_AUTH_BACKEND=agent-secret or file to force a backend instead of automatic detection. agent-secret remains the preferred local setup for NixOS configurations that already manage credentials with SOPS, but it is not required by the launcher.

Optional rbw credentials provider

The updater can read the login username and password from a Bitwarden entry through rbw. The API token remains in the selected agent-secret or private token-file backend because rbw does not support non-interactive entry updates.

EBONHOLD_CREDENTIALS_PROVIDER=rbw \
EBONHOLD_RBW_ENTRY='Project Ebonhold' \
./ebonhold-update login

The entry's standard username and password fields are used. Set EBONHOLD_RBW_USER and/or EBONHOLD_RBW_FOLDER when the entry name is ambiguous. In auto mode, complete agent-secret credentials take precedence, followed by the configured rbw entry, then interactive prompting.

Usage

./ebonhold-update check
./ebonhold-update update
./start-ebonhold-linux.sh

check periodically performs a complete CRC audit of the base installation and otherwise validates the cached audit against file sizes and modification times. update reuses a current audit; when the audit is stale, it verifies the base client and repairs only files that fail. The remote ZIP itself is not downloaded. Required-file content hashes are preferred when available; for timestamp-only entries, the updater reconciles unchanged object-storage ETags without downloading the file again. Manual commands are also available:

./ebonhold-update base-check
./ebonhold-update base-verify
./ebonhold-update base-repair

Interrupted repairs resume from a *.ebonhold-download.part file beside the destination. Files maintained by Ebonhold's required or optional update manifests are excluded because they intentionally replace the original client.

To download the official base-client archive initially:

./ebonhold-update download-base

See ./ebonhold-update --help for the remaining commands.

Addon updates

The checked-in addons.json manifest tracks the Ebonhold-specific addons that have a stable upstream release channel. Official launcher-catalog packages, including Project Ebonhold's ElvUI fork, use the same authenticated download API as the client files. The launcher checks this manifest on normal startup and installs pending addon releases in the same progress window as official client updates. The commands can also be run manually:

./ebonhold-update addons-check
./ebonhold-update addons-update
./ebonhold-update addons-update pe-elvui

Each replaced addon directory is moved to addon-backups/managed/<timestamp>-<addon-id>/ first. Addon updates never edit SavedVariables, so profiles and character settings remain intact. Locally created addons are intentionally absent from the manifest and are not overwritten.

Configuration

The launcher recognizes:

  • EBONHOLD_ROOT
  • EBONHOLD_GAME_DIR
  • EBONHOLD_PROTON
  • EBONHOLD_STEAM_RUN
  • EBONHOLD_TERMINAL
  • STEAM_COMPAT_CLIENT_INSTALL_PATH

Before each launch, the updater normalizes only the display-related entries in WTF/Config.wtf: borderless/maximized mode, the current physical monitor size, 60 Hz, and disabled hardware redetection. A conflicting gxApi override is removed so Proton can use the client's default Direct3D renderer. All unrelated CVars are retained. Use EBONHOLD_RESOLUTION=WIDTHxHEIGHT when automatic detection via Hyprland or XRandR is not appropriate.

On Wayland sessions the launcher automatically enables GE-Proton's native winewayland driver when the selected Proton build supports it. This avoids fractional XWayland scaling and its associated presentation stalls. Set EBONHOLD_WAYLAND=false to force the compatibility XWayland path, or true to require the Wayland path. The default is auto.

The updater additionally recognizes:

  • EBONHOLD_GAME_DIR
  • EBONHOLD_AUTH_BACKEND (auto, file, or agent-secret)
  • EBONHOLD_CREDENTIALS_PROVIDER (auto, prompt, agent-secret, or rbw)
  • EBONHOLD_RBW_ENTRY / EBONHOLD_RBW_USER / EBONHOLD_RBW_FOLDER
  • EBONHOLD_TOKEN_FILE / EBONHOLD_TOKEN
  • EBONHOLD_USERNAME_FILE / EBONHOLD_USERNAME
  • EBONHOLD_PASSWORD_FILE / EBONHOLD_PASSWORD
  • EBONHOLD_ADDON_MANIFEST
  • EBONHOLD_ADDON_BACKUP_DIR
  • EBONHOLD_BASE_VERIFY_INTERVAL
  • EBONHOLD_RESOLUTION
  • EBONHOLD_WAYLAND (auto, true, or false)

Disclaimer

This is an unofficial community launcher. Project Ebonhold and World of Warcraft belong to their respective owners. Review third-party proprietary client extensions according to your own security requirements.