An Arma Reforger dedicated server. Updates to the latest version every time it is restarted.
NOTE: Runs as root by design. SteamCMD requires root to install game files.
docker create \
--name=reforger-server \
-p 2001:2001/udp \
-v path/to/configs:/reforger/Configs \
-v path/to/profiles:/home/profile \
-v path/to/workshop:/reforger/workshop \
-e SERVER_PUBLIC_ADDRESS="public ip" \
-e GAME_NAME="My Docker Reforger Server" \
ghcr.io/acemod/arma-reforger:latestIf an admin password is not provided, one will be generated and printed to the console.
Copy the provided docker-compose.yml and adjust it to your needs.
It pulls ghcr.io/acemod/arma-reforger:latest unless REFORGER_IMAGE says otherwise. Put that in a .env next to the compose file to run a fork's package or a local build instead, so you never have to edit the image line.
By default the container regenerates Configs/docker_generated.json from a bundled template on every startup. The environment variables decide what ends up in it, including which optional sections get written at all: A2S, RCON, persistence, operating, and mission header overrides.
If you want to hand-edit a config file and keep those changes, point ARMA_CONFIG at your own file in the Configs volume, .json and all. That file is used as-is and is not modified by the container.
| Variable | Default | Description |
|---|---|---|
STEAM_USER |
(empty) | Steam username (anonymous login if empty) |
STEAM_PASSWORD |
(empty) | Steam password |
STEAM_APPID |
1874900 |
Steam app ID. Use 1890870 for the experimental server. That one needs a one-time Windows SteamCMD pass first, which the container handles for you |
STEAM_BRANCH |
public |
Steam branch to install from |
STEAM_BRANCH_PASSWORD |
(empty) | Password for the Steam branch |
SKIP_INSTALL |
false |
Skip the SteamCMD install/update step |
| Variable | Default | Description |
|---|---|---|
ARMA_CONFIG |
docker_generated |
Config to load. The default regenerates it from the environment variables. Any other value is a filename in the Configs volume, extension included, and is used as-is |
ARMA_PROFILE |
/home/profile |
Server profile directory |
ARMA_BINARY |
./ArmaReforgerServer |
Path to the server binary |
ARMA_PARAMS |
(empty) | Additional command-line parameters (e.g. -loadSessionSave to resume a previous session) |
ARMA_MAX_FPS |
120 |
Maximum server FPS |
ARMA_WORKSHOP_DIR |
/reforger/workshop |
Workshop / addons directory |
SERVER_BIND_ADDRESS |
0.0.0.0 |
Address the server binds to |
SERVER_BIND_PORT |
2001 |
Port the server binds to (UDP) |
SERVER_PUBLIC_ADDRESS |
(empty) | Public IP address for server browser |
SERVER_PUBLIC_PORT |
2001 |
Public port for server browser |
SERVER_A2S_ADDRESS |
0.0.0.0 |
A2S query address. Set both address and port to enable; leave either empty to disable |
SERVER_A2S_PORT |
17777 |
A2S query port (UDP) |
NOTE: The full list of Startup Parameters for ARMA_PARAMS can be found on the Arma Reforger wiki.
NOTE: The container health check uses the active A2S settings when A2S is enabled. If A2S is disabled, the health check is skipped.
RCON is activated by defining the RCON_PASSWORD variable.
| Variable | Default | Description |
|---|---|---|
RCON_ADDRESS |
0.0.0.0 |
RCON bind address |
RCON_PORT |
19999 |
RCON port (UDP) |
RCON_PASSWORD |
(empty) | RCON password. Required for RCON to start. Must be at least 3 characters, no spaces |
RCON_PERMISSION |
admin |
Permission level for all RCON clients |
RCON_MAX_CLIENTS |
(empty) | Maximum number of concurrent RCON connections (1–16). Server default is 16 |
RCON_BLACKLIST |
(empty) | Comma-separated list of commands excluded from execution. Cannot be used together with RCON_WHITELIST |
RCON_WHITELIST |
(empty) | Comma-separated list of allowed commands. Cannot be used together with RCON_BLACKLIST |
| Variable | Default | Description |
|---|---|---|
GAME_NAME |
Arma Reforger Docker Server |
Server name shown in the server browser |
GAME_PASSWORD |
(empty) | Password required to join the server |
GAME_PASSWORD_ADMIN |
(empty) | Admin password. If left empty, a random passphrase is generated and printed to the console |
GAME_ADMINS |
(empty) | Comma-delimited list of admin identityIds and/or steamIds |
GAME_SCENARIO_ID |
{ECC61978EDCC2B5A}Missions/23_Campaign.conf |
Scenario to load |
GAME_MAX_PLAYERS |
32 |
Maximum number of players |
GAME_VISIBLE |
true |
Whether the server is visible in the server browser |
GAME_SUPPORTED_PLATFORMS |
PLATFORM_PC,PLATFORM_XBL,PLATFORM_PSN |
Comma-separated list of supported platforms |
GAME_CROSS_PLATFORM |
(empty) | Accept all platforms if true. Recommended over GAME_SUPPORTED_PLATFORMS |
GAME_MODS_REQUIRED_BY_DEFAULT |
(empty) | Default required value for mods that do not explicitly set one. Server default is true |
GAME_MODS_AUTO_PRUNE |
false |
Remove downloaded mods that are not referenced by the active server config or one of its installed dependencies |
GAME_MISSION_HEADER_JSON_FILE_PATH |
(empty) | Path to a JSON file containing mission header overrides (see Mission Header) |
GAME_MODS_IDS_LIST |
(empty) | Comma-separated mod IDs with optional version (e.g. 5965770215E93269=1.0.6,5965550F24A0C152) |
GAME_MODS_JSON_FILE_PATH |
(empty) | Path to a JSON file containing an array of mod objects (see Mods) |
| Variable | Default | Description |
|---|---|---|
GAME_PROPS_BATTLEYE |
true |
Enable BattlEye anti-cheat |
GAME_PROPS_DISABLE_THIRD_PERSON |
false |
Disable third-person camera |
GAME_PROPS_FAST_VALIDATION |
true |
Enable fast addon validation |
GAME_PROPS_SERVER_MAX_VIEW_DISTANCE |
2500 |
Maximum view distance (meters) |
GAME_PROPS_SERVER_MIN_GRASS_DISTANCE |
50 |
Minimum grass render distance (meters) |
GAME_PROPS_NETWORK_VIEW_DISTANCE |
1000 |
Network view distance (meters) |
GAME_PROPS_VON_DISABLE_UI |
false |
Disable VON UI |
GAME_PROPS_VON_DISABLE_DIRECT_SPEECH_UI |
false |
Disable VON direct speech UI |
GAME_PROPS_VON_CAN_TRANSMIT_CROSS_FACTION |
false |
Allow cross-faction VON transmission |
Persistence is disabled by default. The game's own defaults are fine for most servers. Set any PERSISTENCE_* variable to enable the persistence config section.
NOTE: -loadSessionSave must be enabled in order to load session saves.
| Variable | Default | Description |
|---|---|---|
PERSISTENCE_AUTO_SAVE_INTERVAL |
(empty) | Minutes between auto-saves (0–60). 0 disables auto-save. Server default is 10 |
PERSISTENCE_SAVE_RETENTION |
(empty) | Number of save points to keep for the current mission (1–128). Server default is 10 |
PERSISTENCE_LOAD_SESSION_SAVE |
(empty) | Automatically load the latest save point on first startup. Server default is true |
PERSISTENCE_KEEP_SESSION_SAVE |
(empty) | Keep save points after the mission is finished. Server default is false |
PERSISTENCE_HIVE_ID |
(empty) | Hive identifier (0–16383). Used when multiple servers share a persistence database |
PERSISTENCE_JSON_FILE_PATH |
(empty) | Path to a JSON file containing databases and/or storages objects (see below) |
A default persistence template is bundled in the image at /persistence_default.json. To use it:
-e PERSISTENCE_JSON_FILE_PATH="/persistence_default.json"For advanced persistence setups (external databases, custom storages), create a JSON file with databases and/or storages objects and mount it into the container:
-v ${PWD}/persistence.json:/persistence.json
-e PERSISTENCE_JSON_FILE_PATH="/persistence.json"
-e PERSISTENCE_AUTO_SAVE_INTERVAL=15Example persistence.json:
{
"databases": {
"webapi": {
"preset": "{0123456789ABCDEF}Configs/Systems/Persistence/Database/JsonWebApi.conf",
"options": {
"url": "https://persistence-db.example.com:5539/api/v1",
"headers": {
"X-API-KEY": "your-api-key",
"Content-Type": "application/json"
}
}
}
},
"storages": {
"session": {
"database": "webapi"
}
}
}Documentation:
Operating settings are disabled by default. Set any OPERATING_* variable to enable the operating config section.
| Variable | Default | Description |
|---|---|---|
OPERATING_LOBBY_PLAYER_SYNCHRONISE |
(empty) | Sync player list to GameAPI with heartbeat. Server default is true |
OPERATING_DISABLE_CRASH_REPORTER |
(empty) | Disable automatic crash reporter. Server default is false |
OPERATING_DISABLE_NAVMESH_STREAMING |
(empty) | Disable navmesh streaming (loads entire navmesh into memory). Set to all to disable all navmesh streaming, or comma-separated navmesh names for specific ones |
OPERATING_DISABLE_SERVER_SHUTDOWN |
(empty) | Prevent server shutdown on backend connection loss. Server default is false |
OPERATING_DISABLE_AI |
(empty) | Completely disable AI functionality. Server default is false |
OPERATING_PLAYER_SAVE_TIME |
(empty) | Period in seconds for saving players. Server default is 120 |
OPERATING_AI_LIMIT |
(empty) | Maximum number of AIs. Negative value disables the limit. Server default is -1 |
OPERATING_SLOT_RESERVATION_TIMEOUT |
(empty) | Duration in seconds to reserve a slot for kicked players (5–300). Server default is 60 |
OPERATING_JOIN_QUEUE_MAX_SIZE |
(empty) | Maximum join queue size (0–50). 0 disables the queue. Server default is 0 |
The mission header allows overriding scenario properties such as the displayed name, starting time, and weather. Create a JSON file and mount it into the container:
-v ${PWD}/mission_header.json:/mission_header.json
-e GAME_MISSION_HEADER_JSON_FILE_PATH="/mission_header.json"Example mission_header.json:
{
"m_sName": "My Very Own Hosted Conflict",
"m_sDetails": "Custom server description",
"m_iStartingHours": 7,
"m_iStartingMinutes": 30,
"m_bRandomStartingWeather": true
}Workshop mods can be defined in two ways, GAME_MODS_IDS_LIST and
GAME_MODS_JSON_FILE_PATH. Use either one, or both.
Set GAME_MODS_AUTO_PRUNE=true to clear unused mods out of
ARMA_WORKSHOP_DIR before the server starts. It keeps the mods in the active
config plus their installed dependencies and removes the rest. Unrelated or
invalid directories are left alone. If a configured mod or one of its
dependencies has bad metadata, startup stops and nothing is pruned. An
interrupted prune finishes on the next start.
A comma separated list of IDs, with an optional version. Entries generated from this list inherit GAME_MODS_REQUIRED_BY_DEFAULT when it is set.
-e GAME_MODS_IDS_LIST="5965770215E93269=1.0.6,5965550F24A0C152"Path to a JSON file that contains an array of mod objects.
-v ${PWD}/mods_file.json:/mods_file.json
-e GAME_MODS_JSON_FILE_PATH="/mods_file.json"[
{
"modId": "597706449575D90B",
"version": "1.1.1",
"required": true
}
]The full Server Configuration can be found here.
The Dockerfile may not include every option that is currently available and may lag behind upstream for additional feature support.
App code lives in src/ and is copied to /app in the image. Tests live in
tests/. persistence_default.json stays at the repository root because it
ships to /persistence_default.json. Users point PERSISTENCE_JSON_FILE_PATH
at that file.
Pinned dev dependencies and tool config both live in pyproject.toml, as
PEP 735 groups. CI runs the same commands
against the same versions. Needs pip 25.1 or newer for --group.
pip install --group devThen run the checks.
black --check --diff .
isort --check-only --diff .
pylint --recursive=y .
pytest -qpre-commit runs all of that plus hadolint on the Dockerfile.
pip install pre-commit
pre-commit installscripts/build.sh builds the image locally and tags it arma-reforger-test. Set
REFORGER_IMAGE=arma-reforger-test to run that build through the compose file.