Container-based AzerothCore WoW server with module support. Uses Podman.
This project provides a single acm command that manages the full lifecycle of an AzerothCore server stack: setup, start/stop, backups, restores, module management, and Paragon Anniversary support.
- Features
- Requirements
- Quick Start
- Commands
- Configuration
- Backups & Retention
- Restore
- Creating an Account
- Modules
- Project Structure
- Environment Variables
- Examples
- Development & Testing
- Design Notes
- One-command setup, start, stop, backup, and restore
- Podman-based container stack with Podman Compose overrides
- Per-config project isolation via
NAME(containers, networks, volumes, and backups are separated) - Automated MySQL database and config backups with gzip compression
- Built-in backup retention / cleanup policy (keeps all backups from today, one per day for 7 days, one per week for 4 weeks, one per month for 12 months)
- Module support: clone/update modules from Git and remove stale modules automatically
- Optional game launch after the server is healthy
- Paragon Anniversary install/uninstall helpers
- Worldserver console attachment and account creation via
expect
- Podman and
podman-compose(or Docker with Compose v2, viaCONTAINER_CMD) - Bash 4.2+
expect(foracm create-account)git,tar,gzip,mysqldump/mysqlclient utilities (run inside containers, but the host needs the wrapper scripts)
./acm setupClones the main AzerothCore repository, installs module dependencies, and rebuilds the full container stack.
./acm startStarts the server and waits for the authserver to be ready.
./acm restore ./backups/db_backup_playerbots_YYYYMMDD_HHMMSS.sql.gzStops the full stack, removes the database container and volume, restores from a compressed backup, then shuts down. Use ./acm start to start the full stack afterward.
All commands accept an optional config file path (defaults to ./conf/wowserver.conf).
| Command | Purpose |
|---|---|
acm setup |
Clone/update repos, rebuild all container images. Flags: --clean (remove old images), --no-cache (skip build cache), --skip-update (skip git pull), --skip-build (skip compose build), --prune (clean dangling and external images), --skip-stale (skip stale module removal). |
acm start |
Ensure old containers are stopped, start server, wait for authserver to be ready. |
acm run |
Start stack, optionally launch game, wait for game exit, wait for keypress, backup, cleanup old backups, shutdown. --skip-game to skip game launch. |
acm stop |
Stop the running stack. |
acm backup |
Backup databases and configs, stopping worldserver/authserver first. --skip-stop to leave them running. |
acm restore |
Restore a database backup, then shut down. |
acm bundle paragon install |
Install Paragon Anniversary SQL schema and sync lua scripts. --skip-git to skip clone, --database to set custom DB name. |
acm bundle paragon uninstall |
Drop Paragon databases and remove synced lua scripts. --database to set custom DB name. |
acm create-account |
Create a new WoW account with GM level 3 on the running worldserver (requires expect). |
acm console |
Attach to the running worldserver console (Ctrl+P then Ctrl+Q to detach). |
Run ./acm <command> --help for command-specific help.
Edit conf/wowserver.conf to set:
| Setting | Description |
|---|---|
NAME |
Container image tag and Compose project name (e.g. playerbots). |
MAIN_REPO |
Base AzerothCore fork to clone. Append @branch for a specific branch. |
MODULE_REPO |
One module Git URL per line. Use @branch for branches and #path for subfolders. |
LAUNCH_GAME |
Command to run 5 seconds after the worldserver is healthy (backgrounded, output discarded). |
Multiple configs can be used to run separate server instances. For example, conf/wowserver-solo.conf uses NAME=solo so containers, volumes, and backups are kept separate from the main config.
Two files are created on every backup:
./backups/db_backup_<CONFIG_NAME>_YYYYMMDD_HHMMSS.sql.gz # MySQL dump of all databases
./backups/config_backup_<CONFIG_NAME>_YYYYMMDD_HHMMSS.tar.gz # env/dist/etc/ and lua_scripts/
- The database backup uses
mysqldump --all-databases --single-transaction --routines --events --triggersand compresses withgzip -9. - The config backup archives the server config files and any custom Lua scripts.
- Backups are scoped by
CONFIG_NAME. Multiple server configs sharing the sameBACKUP_DIRwill not delete each other's files.
acm backup— Stops the worldserver and authserver, dumps and compresses all databases, archives configs, applies the retention policy, then restarts the services. Use--skip-stopto avoid the stop/restart cycle (useful for quick online backups).acm run— Starts the full stack, optionally launches the game, waits for a keypress, then performs the same backup and cleanup sequence before shutting everything down.
After every backup, old files are automatically pruned according to the following policy:
| Window | Kept backups |
|---|---|
| Today | All backups created today are kept. |
| Last 7 days | The latest backup from each day is kept. |
| Next 4 weeks | The latest backup from each week is kept. |
| Next 12 months | The latest backup from each month is kept. |
Anything not selected by the rules above is deleted. Both database and config backups are cleaned up independently using the same retention rules. Each deletion is logged, and a summary count is printed at the end of cleanup.
For example, if today is August 10th and you have multiple backups per day, the policy will keep:
- Every backup made on August 10th
- The newest backup from August 9th, 8th, 7th, 6th, 5th, 4th, and 3rd
- The newest backup from each of the four previous weeks (July 13th, July 6th, June 29th, June 22nd, etc.)
- The newest backup from each of the previous 12 months (July 2026, June 2026, May 2026, ...)
Important: only backups matching the naming pattern db_backup_<CONFIG_NAME>_*.sql.gz and config_backup_<CONFIG_NAME>_*.tar.gz in the configured backup directory are evaluated. Backups with non-matching names or in other directories are ignored and never deleted.
The default backup directory is ./backups (relative to the project root). You can change it by setting the BACKUP_DIR environment variable or by adding it to your config file / shell environment:
BACKUP_DIR=/mnt/backups/wow ./acm backupRelative paths are resolved relative to the project root.
Restore a compressed database backup into a fresh database volume:
./acm restore ./backups/db_backup_playerbots_YYYYMMDD_HHMMSS.sql.gzWhat happens during restore:
- The full stack is stopped and the database container is removed.
- The existing database volume is deleted so the restore is clean.
- Only the
ac-databasecontainer is started and waited for. - The backup is decompressed to a temporary file and restored via
mysql. - The database container is shut down.
After restore completes, start the full stack with:
./acm startTo restore a backup for a different config, pass the config file first:
./acm restore ./conf/wowserver-solo.conf ./backups/db_backup_solo_YYYYMMDD_HHMMSS.sql.gzMake sure the server is running, then:
./acm create-account testuser mypasswordTo open the worldserver console manually:
./acm consolePress Ctrl+P then Ctrl+Q to detach. Do not press Ctrl+C — that stops the server.
Modules are configured by adding one MODULE_REPO=<url> line per module in your config file. For example, in conf/wowserver.conf:
MODULE_REPO=https://github.com/azerothcore/mod-playerbots.git
MODULE_REPO=https://github.com/azerothcore/mod-autobalance.git@master
MODULE_REPO=https://github.com/dr1s/lua-paragon-anniversary.git@main#serverside/mod-paragon-loot| Format | Purpose |
|---|---|
https://github.com/user/repo.git |
Clone the default branch. |
https://github.com/user/repo.git@branch |
Clone a specific branch or tag. |
https://github.com/user/repo.git@branch#path/to/subfolder |
Clone a specific branch and use only a subfolder as the module. |
- Clone or update: Each
MODULE_REPOis cloned into./server/<CONFIG_NAME>/modules/<repo-name>/. If it already exists,git pullupdates it to the configured branch. - Stale module cleanup: Any directory in
./server/<CONFIG_NAME>/modules/that is a git repo but is not listed in the config is removed automatically. To protect a directory, create a.stale-keepfile inside it. - Skip stale cleanup: Use
--skip-staleto keep modules that are not in the config. - Module config initialization: After images are built,
acm setupcopies each module's*.conf.distfiles from./modules/<name>/conf/to./env/dist/etc/modules/with the.distsuffix removed.
# Add MODULE_REPO lines to conf/wowserver.conf, then:
./acm setup├── acm # Main command entry point
├── conf/
│ ├── wowserver.conf
│ └── wowserver-solo.conf
├── compose/
│ ├── podman-compose.override.yml
│ └── patch/ # Compose patches
├── lib/
│ ├── utils/
│ │ ├── init.sh # Environment initialization
│ │ ├── logging.sh # Logging helpers
│ │ ├── config.sh # Config file parsing
│ │ ├── args.sh # Argument parsing helpers
│ │ ├── git.sh # Git/repo helpers
│ │ ├── container.sh # Container/compose helpers
│ │ ├── database.sh # Database helpers
│ │ ├── backup.sh # Backup and retention helpers
│ │ ├── run.sh # Shared start/stop/runtime helpers
│ ├── bundles/
│ │ └── paragon.sh # Paragon Anniversary helpers
│ └── commands/
│ ├── bundle.sh
│ ├── setup.sh
│ ├── start.sh
│ ├── run.sh
│ ├── stop.sh
│ ├── backup.sh
│ ├── restore.sh
│ ├── paragon.sh
│ ├── create-account.sh
│ └── console.sh
├── scripts/
│ └── check.sh # Shell syntax checker
├── tests/
│ ├── run-tests.sh
│ └── lib/
│ ├── config_test.sh
│ ├── args_test.sh
│ └── git_test.sh
├── backups/ # Database and config backups
│ └── db_backup_<CONFIG_NAME>_*.sql.gz
└── server/
└── <CONFIG_NAME>/ # Working directory for compose files and modules
├── docker-compose.yml
├── docker-compose.override.yml
└── modules/
| Variable | Default | Description |
|---|---|---|
BACKUP_DIR |
./backups |
Where backup files are stored. |
DOCKER_DB_ROOT_PASSWORD |
password |
MySQL root password for dump/restore. |
DOCKER_VOL_DB |
ac-database |
Name of the database volume. |
DOCKER_IMAGE_TAG |
master |
Container image tag (set from NAME in config). |
CONFIG_NAME |
server |
Project name prefix for backups and compose project (set from NAME in config). |
COMPOSE_PROJECT |
CONFIG_NAME |
Compose project name for isolation. |
CONTAINER_CMD |
podman |
The container command to use (set to docker if needed). |
LAUNCH_GAME |
(empty) | Command to launch 5s after worldserver is healthy. |
./acm start ./conf/wowserver-solo.conf./acm run./acm run --skip-game./acm backup --skip-stop./acm setup --clean --no-cache --prune./acm setup --skip-build./acm restore ./backups/db_backup_playerbots_20260810_120000.sql.gz
./acm startRun the shell syntax checker:
./scripts/check.shRun the unit tests:
./tests/run-tests.sh