Back to articles

AzerothCore Development Setup (Linux)

A Linux-focused, stock AzerothCore development environment.

cppdockerguideazerothcorewow-emulationlinuxmysql

AzerothCore Development Setup

This article documents a Linux-focused AzerothCore development setup aimed at contributors working on stock 3.3.5 (WotLK) behavior.

The goal is not merely to "run AzerothCore", but to create a development environment that supports:

  • Efficient Triage: Quickly validate before-and-after behavior when developing, debugging, or testing pull requests
  • Context Switching: Easy switching between stock and custom development workflows
  • Rapid Environment Setup: Spin up new environments for testing modules or specific features without disrupting the primary setup
  • Cross-Reference Development: Identify and leverage already-solved systems from other cores, reducing redundant work

I focus on high-level concepts and workflows rather than exhaustive step-by-step instructions; some commands or details may be incorrect, missing, or out of date.

Scope and Assumptions

Assumed Knowledge

This guide builds on the official documentation:

You are expected to already have:

  • A working AzerothCore checkout
  • Maps, DBCs, and vmaps extracted
  • Basic familiarity with MySQL and Linux tooling

This article links, rather than repeats, foundational steps.

Platform Focus

  • Primary target: Linux
  • Tested on: Fedora 42
  • Some steps may apply to other distros or macOS, but are not guaranteed

Stock vs Modding

This is important distinction to make. In AC we focus on 335 blizzlike, anything that drifts makes it harder to reason about stock correctness

It's best to avoid usage of:

  • Client modifications, like patches (.MPQ) and most addons
  • Modules that alter behavior, like progression modules

Dual Database Setup

Separating databases has proven valuable during development.

  • Dev DB
    • Frequent changes
    • SmartAI edits
    • Safe to break
  • Source DB
    • Treated as read-only
    • Represents a known-good reference state

This approach avoids repeated DROP DATABASE + import cycles and works particularly well with Keira3, where you can diff and selectively restore entries.

MySQL Initialization

Wiki Database Installation

Below is a modified create_mysql.sql file tailored for use in our Docker environment. This script also sets up additional databases for tooling, such as acore_spells (used by WoW-Spell-Editor) and acore_dbc (used by WDBXEditor).

This script ensures a clean and consistent setup for both core development and tooling needs.

-- MySQL 8.0.x
DROP USER IF EXISTS 'acore'@'%';
CREATE USER 'acore'@'%' IDENTIFIED WITH mysql_native_password BY 'acore'
WITH MAX_QUERIES_PER_HOUR 0
     MAX_CONNECTIONS_PER_HOUR 0
     MAX_UPDATES_PER_HOUR 0;

CREATE DATABASE IF NOT EXISTS `acore_world` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `acore_characters` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `acore_auth` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;

GRANT ALL PRIVILEGES ON `acore_world`.* TO 'acore'@'%';
GRANT ALL PRIVILEGES ON `acore_characters`.* TO 'acore'@'%';
GRANT ALL PRIVILEGES ON `acore_auth`.* TO 'acore'@'%';

-- Optional tooling databases
CREATE DATABASE IF NOT EXISTS `acore_spells`;
CREATE DATABASE IF NOT EXISTS `acore_dbc`;

GRANT ALL PRIVILEGES ON `acore_spells`.* TO 'acore'@'%';
GRANT ALL PRIVILEGES ON `acore_dbc`.* TO 'acore'@'%';

Docker Compose

services:
  ac-database:
    image: mysql:8.0
    container_name: ac-database
    command: --secure-file-priv="" --local-infile=1 # required for WDBXEditor export
    ports:
      - 3311:3306
    environment:
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - ac-database:/var/lib/mysql-ac
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro # modify path for init.sql as needed
    restart: unless-stopped

  ac-database-2:
    image: mysql:8.0
    container_name: ac-database-2
    command: --secure-file-priv="" --local-infile=1
    ports:
      - 3312:3306
    environment:
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - ac-database-2:/var/lib/mysql-ac-2
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    restart: unless-stopped

volumes:
  ac-database:
  ac-database-2:

This database setup allows running multiple cores simultaneously while using tools like Keira3. By separating the development database (port 3311) and the reference database (port 3312), you can easily compare and validate changes.

If you need to work on additional modules, playerbots, or other features, it's straightforward to add more containers. Simply replicate the existing Docker Compose service definitions, adjusting ports, volumes and config values as needed to avoid port conflicts.

Core Setup

We don't need additional dependencies beyond those listed in the official wiki.

While this approach is unofficially unsupported, it should work fine for AzerothCore. When in doubt, refer to the official instructions for Ubuntu LTS, either in a Distrobox or VM.

Fedora 43 Setup:

dnf group install c-development
# Additional packages (some may already be included in the group)
dnf install boost cmake openssl-devel readline-devel bzip2 clang lldb lld clang-format clang-tidy boost-devel

Build and Compilation

For convenience, we can use the acore.sh utility and conf/config.sh to manage the build configuration.

Below is part of conf/config.sh:

CDEBUG=ON
CTYPE=Debug
CCUSTOMOPTIONS=' -DCMAKE_C_FLAGS="-fsanitize=address" -DCMAKE_CXX_FLAGS="-fsanitize=address" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"'
export ASAN_OPTIONS=${ASAN_OPTIONS:-"detect_leaks=1:halt_on_error=1:allocator_release_delay=1:verbosity=1:print_stats=1:fast_unwind_on_malloc=0"}
export ASAN_SYMBOLIZER_PATH=${ASAN_SYMBOLIZER_PATH:-"/usr/bin/llvm-symbolizer"}
  • CDEBUG: Enables debug symbols for easier debugging.
  • CTYPE: Sets the build type to Debug for development purposes.
  • CCUSTOMOPTIONS: Adds custom compiler options, such as enabling Address Sanitizer (ASAN) for detecting memory issues.
  • ASAN_OPTIONS: Configures AddressSanitizer runtime options, such as enabling leak detection and providing detailed error messages.
  • ASAN_SYMBOLIZER_PATH: Specifies the path to the symbolizer tool for better stack traces.

You can find a config.sh file in this Github gist.

Populate the DB

* authserver needs to be launched to populate the acore_auth.realmlist, updated then restarted.

worldserver with ./worldserver -d. This peforms a dry run to populate the DB, and automaticly shut down.

I always run the worlserver directly to populate the DB, as running it through GDB (or LLDB) takes much longer.

You may find this alias useful to quickly drop the DB

alias drop="mysql --protocol=TCP -h 127.0.0.1 -P 3311 -u acore -p'acore' -e 'DROP SCHEMA \`acore_world\`;'"

Using Git Worktree

Instead of duplicating the entire repository for each core setup, you can use Git worktree to manage multiple working directories from a single Git repository. This approach allows you to work on different configurations or branches simultaneously.

Not all files are shared between worktrees. For example, modules, configuration files (worldserver.conf, authserver.conf), and build directories need to be set up separately for each worktree. Assign a new set of ports in the configuration files to avoid conflicts.

Build the core and populate the databases as usual:

./acore.sh compiler build
./worldserver -d
./authserver -d

For more details, refer to the Git worktree documentation.

By using Git worktree, you can efficiently manage multiple core setups while avoiding unnecessary duplication.

Port and Realm Isolation Strategy

To run two stock AzerothCore instances side-by-side (AC1 and AC2) for triage with a dual database setup, keep ports and realm entries distinct:

ServiceAC1 PortAC2 Port
DB33113312
World80858086
Auth37243725
acore_auth.realmlist80858086
Client realmlist.wtf37243725
  • Set matching values in worldserver.conf, authserver.conf, and the acore_auth.realmlist table.
  • Ensure the client realmlist.wtf points to the corresponding auth port (e.g., set realmlist 127.0.0.1:3725 for AC2).
  • Use the rs-realmctl to automatically launch clients with different realmlist.wtf configurations.

Server Config Exaxmple

Example for our Source DB (3312)

authserver.conf

RealmServerPort = 3725
LoginDatabaseInfo = "127.0.0.1;3312;acore;acore;acore_auth"

acore_auth.realmlist

idnameaddresslocalAddresslocalSubnetMaskport
1AzerothCore 2127.0.0.1127.0.0.1255.255.255.08086

worldserver.conf

WorldServerPort = 8086
LoginDatabaseInfo     = "127.0.0.1;3312;acore;acore;acore_auth"
WorldDatabaseInfo     = "127.0.0.1;3312;acore;acore_world"
CharacterDatabaseInfo = "127.0.0.1;3312;acore;acore_characters"

IDE Configuration

Use .clang-format for formatting and clang-tidy checks. Example configurations are available in this Github gist.

Also see AzerothCore - Discussions - .clang-format.

VS Code Debugging

For debugging, use the launch.json file to attach to worldserver. Find an example in this Github gist.

Recommended Extension: Use clangd extension instead of the default Microsoft C++ extension.

Tools

The following tools are primarily Windows-based but can be run via Wine on Linux or within a Windows VM:

wiki - Useful Tools