A Linux-focused, stock AzerothCore development environment.
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:
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.
This guide builds on the official documentation:
You are expected to already have:
This article links, rather than repeats, foundational steps.
This is an important distinction to make. In AC we focus on 3.3.5 blizzlike behavior, and anything that drifts makes it harder to reason about stock correctness.
It's best to avoid usage of:
.MPQ) and most addonsSeparating databases has proven valuable during development.
This approach avoids repeated DROP DATABASE + import cycles and works particularly well with Keira3, where you can diff and selectively restore entries.
Below is the init.sql file used by our Docker setup. It creates the stock AzerothCore databases plus a few optional tooling databases, such as acore_spells (used by WoW-Spell-Editor), acore_playerbots, acore_dbc (used by WDBXEditor), and acore_eluna.
This script ensures a clean and consistent setup for both core development and tooling needs.
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'@'%' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON `acore_characters`.* TO 'acore'@'%' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON `acore_auth`.* TO 'acore'@'%' WITH GRANT OPTION;
# optional
CREATE DATABASE IF NOT EXISTS `acore_spells` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `acore_spells`.* TO 'acore'@'%' WITH GRANT OPTION;
# optional
CREATE DATABASE IF NOT EXISTS `acore_playerbots` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `acore_playerbots`.* TO 'acore'@'%' WITH GRANT OPTION;
# optional
CREATE DATABASE IF NOT EXISTS `acore_dbc` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `acore_dbc`.* TO 'acore'@'%' WITH GRANT OPTION;
# optional
CREATE DATABASE IF NOT EXISTS `acore_eluna` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `acore_eluna`.* TO 'acore'@'%' WITH GRANT OPTION;
services:
database:
image: mysql:8.0
command: --secure-file-priv="" --local-infile=1 # required for WDBX_Editor export to SQL
ports:
- ${DOCKER_DB_EXTERNAL_PORT:-3311}:3306
environment:
- MYSQL_ROOT_PASSWORD=${DOCKER_DB_ROOT_PASSWORD:-password}
volumes:
- type: volume
source: database
target: /var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
restart: unless-stopped
healthcheck:
test: "/usr/bin/mysql --user=root --password=$$MYSQL_ROOT_PASSWORD --execute \"SHOW DATABASES;\""
interval: 30s
timeout: 10s
retries: 40
volumes:
database:
This database setup uses one generic compose file plus per-environment env files. For the stock development instance, I keep the values in a dedicated env file with the compose project name, external DB port, and root password.
That keeps the compose file reusable while still letting you run separate instances by pointing docker compose at a different env file with its own port and project name.
COMPOSE_PROJECT_NAME=ac-stock-3311
DOCKER_DB_EXTERNAL_PORT=3311
DOCKER_DB_ROOT_PASSWORD=password
docker compose --env-file env/stock-3311.env up -d
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
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"}
Debug for development purposes.You can find a config.sh file in this Github gist.
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\`;'"
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:
./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.
To run two stock AzerothCore instances side-by-side (AC1 and AC2) for triage, keep ports and realm entries distinct. The database port now comes from the environment file, so each instance can reuse the same compose file.
| Service | AC1 Port | AC2 Port |
|---|---|---|
| DB | 3311 | 3312 |
| World | 8085 | 8086 |
| Auth | 3724 | 3725 |
acore_auth.realmlist | 8085 | 8086 |
Client realmlist.wtf | 3724 | 3725 |
worldserver.conf, authserver.conf, and the acore_auth.realmlist table.realmlist.wtf points to the corresponding auth port (e.g., set realmlist 127.0.0.1:3725 for AC2).realmlist.wtf configurations.Example for a second instance with its own environment file and DB port (3312)
authserver.conf
RealmServerPort = 3725
LoginDatabaseInfo = "127.0.0.1;3312;acore;acore;acore_auth"
acore_auth.realmlist
| id | name | address | localAddress | localSubnetMask | port |
|---|---|---|---|---|---|
| 1 | AzerothCore 2 | 127.0.0.1 | 127.0.0.1 | 255.255.255.0 | 8086 |
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"
Use .clang-format for formatting and clang-tidy checks. Example configurations are available in this Github gist.
Also see AzerothCore - Discussions - .clang-format.
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.
The following tools are primarily Windows-based but can be run via Wine on Linux or within a Windows VM:
Also see wiki - Useful Tools