WARHOST
Docker app from suchamoneypit's Repository
Overview
Readme
View on GitHubWARHOST — WARNO Dedicated Server for Unraid
WARHOST runs Eugen Systems' official WARNO dedicated server on Unraid. The install form takes the login and dedicated key Eugen sends you and writes login.ini. The WebUI writes the lobby. The container then starts Eugen's server.
The first start is a 2v2 Conquest lobby on Hesse (_2x2_Hesse_2vs2_CONQ), named WARHOST - Default Server Name, with no workshop mods. Open the WebUI to change the name, map, player limits, and mods.
If you have hosted game servers before, the field descriptions on the Unraid form and a TCP and UDP port forward are likely all you need. Its like other game servers. Setup the server setups, and make sure the game port is port forwarded to the host. WARHOST is listed in Unraid Community Applications: Apps, search WARHOST, Install. The full walkthrough is docs/INSTALL-UNRAID.md. Workshop mods and scenario IDs are further down this page (but probably unnecessary with the WebUI).
What you need
- A dedicated-server login and key from Eugen. Email
eugsupport@eugensystems.comwith the email address of your EugNet account and ask for a dedicated-server key; Eugen replies with a login and key pair (Docker Hub). A dedicated key from another Eugen game also works. One pair can run up to five servers. - Your public WAN IP, and the game port forwarded on your router as both TCP and UDP to the Unraid server. Eugen recommends host networking and this container uses it, so Unraid shows no Docker port mapping.
- Outbound internet from the Unraid server, so the game server can reach Eugen's master server (no offline LAN play), and so each start can read a Workshop mod's
Versionfrom Steam.
Install
WARHOST is listed in Community Applications. In the Unraid Apps tab, search for WARHOST, choose Install, fill in the form fields, and Apply. That installs the main template, which runs ghcr.io/matthewariel/warhost:latest.
Without Community Applications
Use this route for the dev template, or to install a template change before Community Applications picks it up. Unraid 7 has no field for a template URL (Unraid 6.10 removed it), so copy the template to the flash drive and pick it from the Template dropdown.
In a checkout of this repository, sh scripts/print_template_fetch.sh prints the command in step 1. Paste that command in the Unraid terminal. Paste only the branch you are about to add. Applying a downloaded template still writes my-WARHOST.xml, because <Name> is WARHOST, and leaves a differently named download in the dropdown. A clean-slate command for contributors is in docs/AI-WORKFLOW.md.
Unraid web UI → terminal icon (
>_):mkdir -p /boot/config/plugins/dockerMan/templates-user curl -fsSL -o /boot/config/plugins/dockerMan/templates-user/my-WARHOST.xml \ https://raw.githubusercontent.com/matthewariel/WARHOST/main/templates/warhost.xmlDocker → Add Container → Template → User templates, choose WARHOST, fill in the fields below, Apply.
The dropdown label is the flash filename with my- removed, so my-WARHOST.xml shows WARHOST. On Apply, Unraid writes /boot/config/plugins/dockerMan/templates-user/my-<Name>.xml from the Name on the form. With Name left as WARHOST, that is this download. A different Name leaves this file in the dropdown as a second entry, still labeled WARHOST. Delete warno-dedicated-server.xml or my-WARNO-Dedicated-Server.xml if either is still in that folder. sh scripts/print_template_fetch.sh --private saves warhost.xml under /boot/config/plugins/community.applications/private/matthewariel/. The full command is in the install guide.
The template on main installs ghcr.io/matthewariel/warhost:latest. The template on dev installs ghcr.io/matthewariel/warhost:dev. A container whose repository is still ghcr.io/suchamoneypit/warhost cannot pull that path. Edit it to ghcr.io/matthewariel/warhost:latest, or :dev for the dev template, then Apply. If Apply cannot pull the image, use the pull check in the install guide's troubleshooting table. The first server's settings folder is /mnt/user/appdata/warno/10400/settings.
Form fields
| Field | What to enter |
|---|---|
| Settings Folder | /mnt/user/appdata/warno/10400/settings for the first server. The next container uses this path with the port number plus 1, for example /mnt/user/appdata/warno/10401/settings. The folder holds the ini files only. Set Advanced View WebUI to http://[IP]:[PORT:11401]/. |
| Eugen Login | The login from Eugen's reply, exactly as written, not your Steam name. This login and the key are a matching pair good for five containers. |
| Eugen Dedicated Key | The key from the same reply. Paste the whole key. The log shows only the last 4 characters. |
| Public WAN IP | The address Eugen's lobby should advertise to players. Look it up at https://www.whatismyip.com/ from a device on that network if you do not know it. |
| WebUI | true serves the lobby page on WebUI Port. Set the server name, map, and mods there. For the next container, set Advanced View WebUI to http://[IP]:[PORT:11401]/. false leaves the Docker button with nothing listening. |
| Game Port | 10400 for the first server. This port must be free on the Unraid host. The next container uses that number plus 1. Forward each number to this Unraid server as TCP and UDP. Set WebUI Port to this number plus 1000. Set Advanced View WebUI to http://[IP]:[PORT:11401]/. Players join by the server name set in the WebUI. |
| WebUI Port | Port the lobby page listens on: 11400 on the first server, then the next number. Set Advanced View WebUI to http://[IP]:[PORT:11401]/ or the Docker button still opens 11400. Do not forward it. |
| Write Config From Form (Show more settings) | true rewrites login.ini each start, fills in missing lobby files, and refreshes a bare Workshop id to id/Version. false leaves the file contents in place and sets login.ini to mode 600. |
Show more settings holds Write Config From Form. Two new containers both use WARHOST - Default Server Name until each is changed in its WebUI. Scenario IDs and named mods are in the tables below.
A container saved from an earlier template can still show Server Name, Map, player counts, combat rule, and the workshop fields. This entrypoint ignores those values and prints Lobby settings on the Docker template are ignored. Change the server in the WebUI.
Map
The WebUI map list uses a scenario ID from the lists below. Base-game maps need no workshop mod. A workshop map needs its pack checked under Steam Workshop Maps on that page, from the workshop mods table. When the startup log warns about the map or the mod list, the troubleshooting table in the install guide says what to change.
The size in the ID is the usual lobby. Eugen's variables.ini page does not tie player count to that size. The usual settings are Max Players 2 and Team Size 1 for 1v1, 4 and 2 for 2v2, 6 and 3 for 3v3, 8 and 4 for 4v4, and 20 and 10 for 10v10. Choosing a map in the WebUI fills Max players (NbMaxPlayer) and Team size (MaxTeamSize) from that map, and sets Minimum players (NbMinPlayer) to the same count as Max players. Eugen's variables.ini page says the server starts its launch countdown when that many players have joined, and that the minimum should not be higher than the maximum. A 10v10 therefore fills 20, 10, and 20. PvE hides those three; PvP keeps them editable, and a save writes what they show, so a 2v2 map can still be saved as 8 and 4 or as a 1v1 (max 2, team size 1, minimum 2). A count already in variables.ini is what the page shows until the map is changed.
Workshop mods
The WebUI checklist loads the mod that contains the maps. Check the Workshop id from the table. Save writes the bare id. The next start reads that mod's current Version and writes id/Version. Pick the map from that mod's scenario list below. Red Dragon is the first row: check 3811913066, which sets tags Maps-Scenarios, and choose RDPort_JungleLaw_2v2_CONQ for Jungle Law.
| Mod | Workshop Mod List | Example pin | Workshop Mod Tags |
|---|---|---|---|
| WARNO: Red Dragon - Map Pack | 3811913066 |
3811913066/27 |
Maps-Scenarios |
| WEST FULDA 1.0 | 3363584349 |
3363584349/1023 |
Maps-Scenarios |
| Highway to Oslo | 3474588989 |
3474588989/14 |
Maps-Scenarios |
| Ramstein Air Base | 3705706772 |
3705706772/9 |
Maps-Scenarios |
| Arsenal | 3415339374 |
3415339374/20 |
Maps-Scenarios |
| Helbe | 3762638679 |
3762638679/36 |
Maps-Scenarios |
| Galactic Divide | 3595948209 |
3595948209/16 |
Gameplay-Interface-Sound-Scenarios-Maps |
| A World in Flames | 3388575848 |
3388575848/7 |
Gameplay-Interface, or Gameplay-Interface-Maps-Scenarios with a map pack |
The example pin is that mod's Version from Config.ini at the time the table was written. A pin holds that number, so players are refused once the author increments Version. The WebUI writes the bare id. A pin already in variables.ini stays until that mod is saved again from the page. The dated reads are in docs/EVIDENCE.md.
Galactic Divide is a total conversion and A World in Flames is a modern-day overhaul. Neither has scenario IDs of its own, so the map comes from the base game or a map pack. Check a conversion and a map pack together. The page joins their ids with a hyphen, for example 3595948209-3811913066. Tags are the union of the checked mods. A World in Flames uses Gameplay-Interface alone, and Gameplay-Interface-Maps-Scenarios when a map pack is also checked.
Joining players subscribe to each Workshop item in the list and enable it in WARNO's Mod Center. Eugen's variables.ini page says a joining player who is missing a ModList mod is prompted to download and enable it. To read Version, the container downloads just the mod's Config.ini from Steam with DepotDownloader, on the first start and after each update the author publishes.
Scenario IDs
Map packs come first and the base game is last. Choose the value from the Scenario ID column in the WebUI. The SM_ names under some packs are Army General files; pick a scenario from the tables. For a mod not listed here, step 3 of the install guide shows how to find its IDs. An id already in variables.ini that is not in this list stays if you leave it checked.
Red Dragon map pack (28 scenario IDs)
Check 3811913066 in the WebUI checklist. Every map is Conquest, so leave combat rule as the page sets it.
| Map | Scenario ID | Size |
|---|---|---|
| Hell in a Very Small Place | RDPort_HellInAVerySmallPlace_1v1_CONQ |
1v1 |
| Mud Fight | RDPort_MudFight_1v1_CONQ |
1v1 |
| Paddy Field | RDPort_PaddyField_1v1_CONQ |
1v1 |
Strait to the Point (file name StraitSmall) |
RDPort_StraitSmall_1v1_CONQ |
1v1 |
| Tropic Thunder | RDPort_TropicThunder_1v1_CONQ |
1v1 |
Wonsan Harbour Land & Sea (file name WonsanLandSea) |
RDPort_WonsanLandSea_1v1_CONQ |
1v1 |
| Another D-Day | RDPort_AnotherDDay_2v2_CONQ |
2v2 |
| Apocalypse Imminent | RDPort_ApocalypseImminent_2v2_CONQ |
2v2 |
| Chosin Reservoir | RDPort_ChosinReservoir_2v2_CONQ |
2v2 |
| Gunboat Diplomacy | RDPort_GunboatDiplomacy_2v2_CONQ |
2v2 |
| Hop and Glory | RDPort_HopAndGlory_2v2_CONQ |
2v2 |
| Jungle Law | RDPort_JungleLaw_2v2_CONQ |
2v2 |
| Operation Chromite | RDPort_OperationChromite_2v2_CONQ |
2v2 |
| Paddy Field | RDPort_PaddyField_2v2_CONQ |
2v2 |
Strait to the Point Land & Sea (file name StraitSmallLandSea) |
RDPort_StraitSmallLandSea_2v2_CONQ |
2v2 |
Wonsan Harbour (file name WonsanNative) |
RDPort_WonsanNative_2v2_CONQ |
2v2 |
| 38th Perpendicular | RDPort_38thPerpendicular_3v3_CONQ |
3v3 |
| Another D-Day in Paradise Land & Sea | RDPort_AnotherDDayLandSea_3v3_CONQ |
3v3 |
| Back to Inchon | RDPort_BackToInchon_3v3_CONQ |
3v3 |
| Gunboat Diplomacy Land & Sea | RDPort_GunboatLandSea_3v3_CONQ |
3v3 |
| Strait to the Point | RDPort_StraitToThePoint_3v3_CONQ |
3v3 |
| 38th Parallel | RDPort_38thParallel_4v4_CONQ |
4v4 |
| Battle of Yuchalnok Pass | RDPort_BattleOfYuchalnokPass_4v4_CONQ |
4v4 |
| Final Meltdown | RDPort_FinalMeltdown_4v4_CONQ |
4v4 |
| Floods | RDPort_Floods_4v4_CONQ |
4v4 |
Strait to the Point Land & Sea (file name StraitLandSea) |
RDPort_StraitLandSea_4v4_CONQ |
4v4 |
| Sun of Juche | RDPort_SunOfJuche_4v4_CONQ |
4v4 |
| Asgard | RDPort_Asgard_10v10_CONQ |
10v10 |
WEST FULDA 1.0 (16 scenario IDs)
Workshop Mod List 3363584349.
| Map | Scenario ID | Size |
|---|---|---|
| West Fulda | _3x3_WFulda_4v4_CONQ |
4v4 Conquest |
| West Fulda | _3x3_WFulda_4v4_DEST |
4v4 Destruction |
| West Fulda | _3x3_WFulda_10v10_CONQ |
10v10 Conquest |
| West Fulda | _3x3_WFulda_10v10_DEST |
10v10 Destruction |
| Bimbach | _3x3_WFuldaBimbach_2v2_CONQ |
2v2 Conquest |
| Bimbach | _3x3_WFuldaBimbach_2v2_DEST |
2v2 Destruction |
| Grossenluder | _3x3_WFuldaGrossen_1v1_CONQ |
1v1 Conquest |
| Grossenluder | _3x3_WFuldaGrossen_2v2_DEST |
2v2 Destruction |
| Kammerzell | _3x3_WFuldaKammerzell_1v1_CONQ |
1v1 Conquest |
| Kammerzell | _3x3_WFuldaKammerzell_2v2_CONQ |
2v2 Conquest |
| Kammerzell | _3x3_WFuldaKammerzell_2v2_DEST |
2v2 Destruction |
| Malkes | _3x3_WFuldaMalkes_3v3_CONQ |
3v3 Conquest |
| Malkes | _3x3_WFuldaMalkes_3v3_DEST |
3v3 Destruction |
| Neuenberg | _3x3_WFuldaNeuen_1v1_CONQ |
1v1 Conquest |
| Neuenberg | _3x3_WFuldaNeuen_2v2_CONQ |
2v2 Conquest |
| Neuenberg | _3x3_WFuldaNeuen_2v2_DEST |
2v2 Destruction |
Army General file names:
SM_FO_3x3_WestFulda_01SM_FO_3x3_WestFulda_02SM_PL_3x3_WestFulda_01SM_PL_3x3_WestFulda_02SM_PL_3x3_WestFulda_03SM_PL_3x3_WestFulda_04SM_SU_3x3_WestFulda_01SM_SU_3x3_WestFulda_02SM_SU_3x3_WestFulda_03
Highway to Oslo (4 scenario IDs)
Workshop Mod List 3474588989. The Workshop page lists these as 1v1.
| Map | Scenario ID | Size |
|---|---|---|
| Highway to Oslo | _2x2_Oslo_Conquest |
1v1 Conquest |
| Highway to Oslo | _2x2_Oslo_Destruction |
1v1 Destruction |
| Highway to Oslo | _2x2_Oslo_ConquestNS |
1v1 Conquest, no sidespawn |
| Highway to Oslo | _2x2_Oslo_DestructionNS |
1v1 Destruction, no sidespawn |
Ramstein Air Base (2 scenario IDs)
Workshop Mod List 3705706772. The Workshop page lists these as 3v3.
| Map | Scenario ID | Size |
|---|---|---|
| Ramstein Air Base | _2x2_Ramstein_Conquest |
3v3 Conquest |
| Ramstein Air Base | _2x2_Ramstein_Destruction |
3v3 Destruction |
Arsenal (4 scenario IDs)
Workshop Mod List 3415339374. The Workshop page lists 2v2 and 3v3 layouts, each in Conquest and Destruction.
| Map | Scenario ID | Size |
|---|---|---|
| Two Hills | _2x3_TwoHills_Conquest |
2v2 Conquest |
| Two Hills | _2x3_TwoHills_Destruction |
2v2 Destruction |
| Two Hills | _2x3_TwoHills_Conquest_6P |
3v3 Conquest |
| Two Hills | _2x3_TwoHills_Destruction_6P |
3v3 Destruction |
Helbe (12 scenario IDs)
Workshop Mod List 3762638679. Norden's file is a 2v2. The Workshop page calls that layout 3v3; the WebUI fills the size in this table.
| Map | Scenario ID | Size |
|---|---|---|
| Helbe | _5x3_Helbe_4v4_CONQ |
4v4 Conquest |
| Helbe | _5x3_Helbe_10v10_CONQ |
10v10 Conquest |
| Hochland | _5x3_HelbeHochland_2v2_CONQ |
2v2 Conquest |
| Norden | _5x3_HelbeNorden_2v2_CONQ |
2v2 Conquest |
| Stream | _5x3_HelbeStream_2v2_CONQ |
2v2 Conquest |
| Stream | _5x3_HelbeStream_3v3_CONQ |
3v3 Conquest |
| Stream | _5x3_HelbeStream_10v10_CONQ |
10v10 Conquest |
| Suden | _5x3_HelbeSuden_1v1_CONQ_DUEL |
1v1 Conquest duel |
| Wide | _5x3_HelbeWide_4v4_CONQ |
4v4 Conquest |
| Wide | _5x3_HelbeWide_10v10_CONQ |
10v10 Conquest |
| Zentrum | _5x3_HelbeZentrum_3v3_CONQ |
3v3 Conquest |
| Zentrum | _5x3_HelbeZentrum_10v10_CONQ |
10v10 Conquest |
Army General file names:
SM_FO_5x3_Helbe_01SM_FO_5x3_Helbe_02SM_FO_5x3_Helbe_03SM_PL_5x3_Helbe_01SM_PL_5x3_Helbe_02SM_PL_5x3_Helbe_03SM_PL_5x3_Helbe_04SM_PL_5x3_Helbe_05
Base game (102 scenario IDs)
Leave the WebUI workshop checklist clear. These are the Map Base Id values from Eugen's Docker Hub page.
| Map | Scenario ID | Size |
|---|---|---|
| Airport (duel) | _3x3_Airport_1vs1_CONQ_DUEL |
1v1 Conquest |
| Black Forest Storm (duel) | _2x3_BlackForestStorm_1vs1_CONQ_DUEL |
1v1 Conquest |
| Chemical (duel) | _4x2_Chemical_1vs1_CONQ_DUEL |
1v1 Conquest |
| Death Row (training) | _2x3_Death_Row_1vs1_CONQ_TRAINING |
1v1 Conquest |
| Geisa (training) | _4x3_geisa_1vs1_CONQ_TRAINING |
1v1 Conquest |
| Hesse (duel) | _2x2_Hesse_1vs1_CONQ_DUEL |
1v1 Conquest |
| Kreide (duel) | _3x3_Kreide_1vs1_CONQ_DUEL |
1v1 Conquest |
| Mount River (duel) | _3x3_MountRiver_1vs1_CONQ_DUEL |
1v1 Conquest |
| Mount River (training) | _3x3_MountRiver_1vs1_CONQ_TRAINING |
1v1 Conquest |
| Ohmen (duel) | _2x3_Ohmen_1vs1_CONQ_DUEL |
1v1 Conquest |
| Two Lakes (duel) | _2x3_Two_lakes_1vs1_CONQ_DUEL |
1v1 Conquest |
| Urban Frontlines (duel) | _3x3_UrbanFrontlines_1vs1_CONQ_DUEL |
1v1 Conquest |
| Vertigo (duel) | _2x3_Vertigo_1vs1_CONQ_DUEL |
1v1 Conquest |
| Albion Military Base | _2x3_Albion_Military_Base_2vs2_CONQ |
2v2 Conquest |
| Black Forest Storm | _2x3_BlackForestStorm_2vs2_CONQ |
2v2 Conquest |
| Chemical (training) | _4x2_Chemical_2vs2_CONQ_TRAINING |
2v2 Conquest |
| Death Row | _2x3_Death_Row_2vs2_CONQ |
2v2 Conquest |
| Hesse | _2x2_Hesse_2vs2_CONQ |
2v2 Conquest |
| Loop | _5x2_Loop_2vs2_CONQ |
2v2 Conquest |
| Mount River (assault) | _3x3_MountRiver_2vs2_CONQ_ASSAULT |
2v2 Conquest |
| Ripple | _2x3_Ripple_2vs2_CONQ |
2v2 Conquest |
| Tension | _2x2_Tension_2vs2_CONQ |
2v2 Conquest |
| Teufelsmoor | _2x2_Teufelsmoor_2vs2_CONQ |
2v2 Conquest |
| Two Lakes | _2x3_Two_lakes_2vs2_CONQ |
2v2 Conquest |
| Two Ways | _2x3_TwoWays_2vs2_CONQ |
2v2 Conquest |
| Urban Frontlines | _3x3_UrbanFrontlines_2vs2_CONQ |
2v2 Conquest |
| Vertigo | _2x3_Vertigo_2vs2_CONQ |
2v2 Conquest |
| Death Row | _2x3_Death_Row_2vs2_DEST |
2v2 Destruction |
| Ripple | _2x3_Ripple_2vs2_DEST |
2v2 Destruction |
| Two Lakes | _2x3_Two_lakes_2vs2_DEST |
2v2 Destruction |
| Two Ways | _2x3_TwoWays_2vs2_DEST |
2v2 Destruction |
| Vertigo | _2x3_Vertigo_2vs2_DEST |
2v2 Destruction |
| Airport | _3x3_Airport_3vs3_CONQ |
3v3 Conquest |
| Cliff | _4x3_Cliff_3vs3_CONQ |
3v3 Conquest |
| Cyrus | _3x3_Cyrus_3vs3_CONQ |
3v3 Conquest |
| Danger Hills | _3x3_DangerHills_3vs3_CONQ |
3v3 Conquest |
| Eiche | _3x3_Eiche_3vs3_CONQ |
3v3 Conquest |
| Factory | _3x3_Factory_3vs3_CONQ |
3v3 Conquest |
| Kreide | _3x3_Kreide_3vs3_CONQ |
3v3 Conquest |
| Mount River | _3x3_MountRiver_3vs3_CONQ |
3v3 Conquest |
| Railway | _3x3_Railway_3vs3_CONQ |
3v3 Conquest |
| Rift | _3x3_Rift_3vs3_CONQ |
3v3 Conquest |
| Rocks | _3x3_Rocks_3vs3_CONQ |
3v3 Conquest |
| Rocks (assault) | _3x3_Rocks_3vs3_CONQ_ASSAULT |
3v3 Conquest |
| Stoneware | _3x3_Stoneware_3vs3_CONQ |
3v3 Conquest |
| Surrounded | _3x3_Surrounded_3vs3_CONQ |
3v3 Conquest |
| Triple Strike | _3x3_TripleStrike_3vs3_CONQ |
3v3 Conquest |
| Twin Cities | _3x3_TwinCities_3vs3_CONQ |
3v3 Conquest |
| Two Ways | _2x3_TwoWays_3vs3_CONQ |
3v3 Conquest |
| Urban Frontlines | _3x3_UrbanFrontlines_3vs3_CONQ |
3v3 Conquest |
| Valley | _3x3_Valley_3vs3_CONQ |
3v3 Conquest |
| Volcano | _3x3_Volcano_3vs3_CONQ |
3v3 Conquest |
| Airport | _3x3_Airport_3vs3_DEST |
3v3 Destruction |
| Cyrus | _3x3_Cyrus_3vs3_DEST |
3v3 Destruction |
| Danger Hills | _3x3_DangerHills_3vs3_DEST |
3v3 Destruction |
| Eiche | _3x3_Eiche_3vs3_DEST |
3v3 Destruction |
| Factory | _3x3_Factory_3vs3_DEST |
3v3 Destruction |
| Kreide | _3x3_Kreide_3vs3_DEST |
3v3 Destruction |
| Mount River | _3x3_MountRiver_3vs3_DEST |
3v3 Destruction |
| Railway | _3x3_Railway_3vs3_DEST |
3v3 Destruction |
| Rift | _3x3_Rift_3vs3_DEST |
3v3 Destruction |
| Rocks | _3x3_Rocks_3vs3_DEST |
3v3 Destruction |
| Stoneware | _3x3_Stoneware_3vs3_DEST |
3v3 Destruction |
| Surrounded | _3x3_Surrounded_3vs3_DEST |
3v3 Destruction |
| Triple Strike | _3x3_TripleStrike_3vs3_DEST |
3v3 Destruction |
| Twin Cities | _3x3_TwinCities_3vs3_DEST |
3v3 Destruction |
| Urban Frontlines | _3x3_UrbanFrontlines_3vs3_DEST |
3v3 Destruction |
| Valley | _3x3_Valley_3vs3_DEST |
3v3 Destruction |
| Volcano | _3x3_Volcano_3vs3_DEST |
3v3 Destruction |
| Chemical | _4x2_Chemical_4vs4_CONQ |
4v4 Conquest |
| Dark Stream | _4x2_DarkStream_4vs4_CONQ |
4v4 Conquest |
| Chemical | _4x2_Chemical_4vs4_DEST |
4v4 Destruction |
| Airport | _3x3_Airport_10vs10_CONQ |
10v10 Conquest |
| Crown | _5x2_crown_10vs10_CONQ |
10v10 Conquest |
| Cyrus | _3x3_Cyrus_10vs10_CONQ |
10v10 Conquest |
| Danger Hills | _3x3_DangerHills_10vs10_CONQ |
10v10 Conquest |
| Dark Stream | _4x2_DarkStream_10vs10_CONQ |
10v10 Conquest |
| Factory | _3x3_Factory_10vs10_CONQ |
10v10 Conquest |
| Geisa | _4x3_geisa_10vs10_CONQ |
10v10 Conquest |
| Iron Waters | _3x3_IronWaters_10vs10_CONQ |
10v10 Conquest |
| Kreide | _3x3_Kreide_10vs10_CONQ |
10v10 Conquest |
| Loop | _5x2_Loop_10vs10_CONQ |
10v10 Conquest |
| Railway | _3x3_Railway_10vs10_CONQ |
10v10 Conquest |
| Rift | _3x3_Rift_10vs10_CONQ |
10v10 Conquest |
| Rocks | _3x3_Rocks_10vs10_CONQ |
10v10 Conquest |
| Stoneware | _3x3_Stoneware_10vs10_CONQ |
10v10 Conquest |
| Surrounded | _3x3_Surrounded_10vs10_CONQ |
10v10 Conquest |
| Triple Strike | _3x3_TripleStrike_10vs10_CONQ |
10v10 Conquest |
| Twin Cities | _3x3_TwinCities_10vs10_CONQ |
10v10 Conquest |
| Urban Frontlines | _3x3_UrbanFrontlines_10vs10_CONQ |
10v10 Conquest |
| Valley | _3x3_Valley_10vs10_CONQ |
10v10 Conquest |
| Volcano | _3x3_Volcano_10vs10_CONQ |
10v10 Conquest |
| Airport | _3x3_Airport_10vs10_DEST |
10v10 Destruction |
| Crown | _5x2_crown_10vs10_DEST |
10v10 Destruction |
| Cyrus | _3x3_Cyrus_10vs10_DEST |
10v10 Destruction |
| Danger Hills | _3x3_DangerHills_10vs10_DEST |
10v10 Destruction |
| Geisa | _4x3_geisa_10vs10_DEST |
10v10 Destruction |
| Iron Waters | _3x3_IronWaters_10vs10_DEST |
10v10 Destruction |
| Kreide | _3x3_Kreide_10vs10_DEST |
10v10 Destruction |
| Loop | _5x2_Loop_10vs10_DEST |
10v10 Destruction |
| Rocks | _3x3_Rocks_10vs10_DEST |
10v10 Destruction |
| Volcano | _3x3_Volcano_10vs10_DEST |
10v10 Destruction |
A second server
Each server is its own container. Add another one from this same template. Do not use Unraid's reinstall action. Reinstall replaces the container you already have.
The container name, Game Port, WebUI Port, and Settings Folder are unique. The server name is set in that container's WebUI, and it has to differ from the other servers. The directory before /settings is that container's Game Port. The next container adds 1 to the Game Port and to the WebUI Port. In Advanced View, change 11400 in the WebUI box to that container's WebUI Port so the Docker button opens its page.
| Field | First server | Second server |
|---|---|---|
| Name | WARHOST |
WARHOST2 |
| Game Port | 10400 |
10401 |
| WebUI Port | 11400 |
11401 |
| Advanced View WebUI | http://[IP]:[PORT:11400]/ |
http://[IP]:[PORT:11401]/ |
| Settings Folder | /mnt/user/appdata/warno/10400/settings |
/mnt/user/appdata/warno/10401/settings |
| Server name in the WebUI | WARHOST - Default Server Name until you change it |
a different name |
The map and workshop mods also belong to each container, so one server can run the Red Dragon map pack while another runs a base-game map. Public WAN IP, Eugen login, and Eugen dedicated key stay the same for up to five servers. A sixth container needs another login and key pair. Forward each Game Port to this Unraid server as TCP and UDP. Players join from the WARNO server browser by server name. They are not given a port to type.
Every container uses the same image, stored once. The settings folder holds login.ini, variables.ini, and params_for_ai.json. The wrapper also creates warhost.lock there so two running containers cannot share the folder. Do not copy WARNO or a Workshop folder into it. If the folder is already in use, or the game port is already taken, the start stops and the log says what to change. One pair runs five servers.
Settings files
On each start, Write Config From Form (true) rewrites login.ini in the settings folder. It creates variables.ini only when that file is missing, using the Hesse preset, and creates params_for_ai.json only when that file is missing, as two empty deck lists. An existing variables.ini stays, except a bare Workshop id in ModList, which that start rewrites as id/Version. A symlink at params_for_ai.json is replaced; a regular file is kept.
When ModList holds a bare Workshop id, the start also writes warhost-workshop-versions.txt: one line per id with Steam's update time and the Version written. Delete it to make the next start read each Config.ini again, after a WebUI save has put the bare id back.
The wrapper writes those files in a private .warhost-stage.* folder first, then moves them into place. The next start that locks the settings folder removes one left by a crash or power loss, so do not keep anything under that name.
samples/ shows the shape of those files with placeholders only. Do not replace the placeholders in this repository.
The faction matchup is NATO vs PACT (GameType = 0). Teams must stay the same size (DeltaMaxTeamSize = 0) until a PvE setup save says otherwise. The first params_for_ai.json has no decks. RCON is not configured.
Set Write Config From Form to false only when you need to edit those files by hand. While it is true, the next start still rewrites login.ini, leaves an existing variables.ini and an existing params_for_ai.json in place, and refreshes bare Workshop ids in variables.ini. While it is false, the three files stay as edited, login.ini is set to mode 600, and no Workshop id is looked up on Steam. Any other file the server itself creates in that folder (for example admins.ini or banned_clients.ini, if it creates them) is left alone.
Logs
After the startup lines, the Docker log prints a status line when it changes, and repeats that line about every 5 minutes. status: dedicated server has not reported yet is normal until the server writes its first snapshot. A file left from the previous run is removed at start, so it is not reported as the current lobby. The count includes players and computer players, so a PvE lobby can look full before a human joins.
status: lobby, 1 player, including AI, minimum 2, maximum 4 is a lobby still short of its minimum. Once the count reaches that minimum, the line is status: lobby, 2 players, including AI, minimum 2 reached, maximum 4, warmup setting 60s. The warmup number is WarmupCountdown in variables.ini. It is the saved setting, not seconds remaining. status: GameState 3, 4 players, including AI, maximum 4 is any state other than the lobby. Eugen documents 0 as no game in progress and does not define the other numbers, so the log prints the number. warning: dedicated server status is stale. It has not updated for more than 30 seconds. means the status file stopped changing.
The same lines are appended to .warhost-status.log in the settings folder. That file stays when the container is recreated, rotates at 1 MB, and keeps one previous file. The server rewrites .warhost-status there with the raw snapshot. A quiet server adds about 1 KB an hour.
WebUI
The page listens on WebUI Port. The first server is http://<unraid>:11400/. The next server, with WebUI Port 11401, is http://<unraid>:11401/. Do not forward that port. A container from before this field still listens on the game port plus 1000. Under the heading, the page lists the game port and the WebUI port as a pair, and the game port says (must be port forwarded TCP/UDP). The browser tab names both ports, so several open pages stay distinct. When the page is up, the log says WebUI listening on http://10.0.1.50:11400/. That address is this server's, not the public WAN IP. It can differ from the host in the Docker button when the default route uses another interface. When WebUI Port is not 11400, the next line is If the Docker button opens another server, set Advanced View WebUI to http://[IP]:[PORT:11401]/.
The first server leaves WebUI Port and the Advanced View WebUI box at http://[IP]:[PORT:11400]/. The Docker button already opens that page. A later container's button opens its page only after that box uses the same number as WebUI Port. Changing WebUI Port does not change the box.
false leaves nothing listening. The log says WebUI is off. Nothing is listening on port 11400. If that port is already taken, it says WebUI is off. Port 11400 is already in use. With WebUI left on, a taken page port logs warning: WebUI port 11400 is already in use. The game server will still start. The Docker button still opens the port in the Advanced View box.
- Map and mods. Steam Workshop Maps lists the named map packs. Full conversions, such as Galactic Divide and A World in Flames, are a second checklist. Checking a pack shows its maps. An id already in
variables.inithat is not in either list stays as a checkbox labeled with that id. Search matches the map name and scenario ID. For a map in the list, the combat-rules menu offers only that scenario's rule. - PvP and PvE. PvP keeps Max players, Team size, and Minimum players, and does not write
params_for_ai.json. PvE hides those three. Humans play as one side and the AI count fills the other. A PvE save writesCoopVsAI(1or2), sets minimum players to the human count, max players to the two counts added together, and team size to the larger count. It also writes at least one AI deck: a name, a deck code, and a difficulty from 1 to 6. Switching back to PvP setsCoopVsAIto0and leaves the deck file. - Save. Save writes the server name, the map, the checked mods as bare ids, and the match dropdowns into
variables.ini. Tags come from the checked mods. A modded map whose pack is unchecked is rejected. Save keeps the previous copy asvariables.ini.bakand leaves the current match running. Save and restart writes the form when it differs from that file, then restarts the dedicated server. If the page cannot restart the container, restart it in Unraid.
If the page fails to start, the log warns and the game server still starts. A privilege drop that fails leaves the page running, and the log says it stayed root. The page does not show the Eugen login or dedicated key. Scenic view and tactical zones stay text until webui/previews is filled from a local WARNO install. That folder is not in the published image.
Keys
The dedicated key belongs in the Unraid form, which stores it for that container and writes login.ini on the server. The startup log names only the last 4 characters. The key does not belong in this git repository, in an example file, or in a GitHub issue. If a key is ever committed, treat it as compromised even after a later delete, because git history keeps it. .gitignore ignores login.ini and a local settings/ directory.
Updates
Eugen publishes game updates as eugensystems/warno:latest. This repo does not copy their listen, IP, or matchmaking arguments. The wrapper appends -statusfile so the log can report the lobby. entrypoint-unraid.sh writes the settings files and then runs /server/entrypoint2.sh from their image. It stays the container's main process. Save and restart runs that start again so the saved lobby and Workshop versions load.
.github/workflows/rebuild-image.yml checks Eugen's image once a day. The workflow also runs when the Dockerfile, entrypoint-unraid.sh, webui/, or .github/workflows/rebuild-image.yml changes, and a push of those paths publishes :latest from main or :dev from dev. In Unraid, update each server container. A failed build leaves the previous image in place. Fix the Action and run it again. Players on a new WARNO patch need that rebuild before the dedicated server will match the client.
Change the entrypoint only if Eugen renames entrypoint2.sh or the settings filenames. A normal game patch does not require an edit here.
Workshop mods update apart from the image. A WebUI save writes bare ids. The next start reads the current Version of each bare id in variables.ini and writes id/Version. After a mod author publishes, use Save and restart in the WebUI. Until that restart, players who have the update are refused. A pin already stored as id/Version keeps its number until that save.
License
Repository files are MIT (LICENSE). The image is built from Eugen's eugensystems/warno, which states no license, and includes DepotDownloader 3.4.0 under GPL-2.0. Publishing steps for maintainers are in docs/AI-WORKFLOW.md.
Documentation
| File | Contents |
|---|---|
| docs/INSTALL-UNRAID.md | First install, step by step, with verification and troubleshooting |
| docs/ARCHITECTURE.md | How the wrapper, WebUI, and image behave, with sources |
| docs/DECISIONS.md | Why things are the way they are |
| docs/ROADMAP.md | Goals and known issues |
| docs/UNRAID-TEMPLATE-GUIDE.md | Generic Unraid template guidance, reusable for other game servers |
| docs/AI-WORKFLOW.md | Working on this repository with Cursor and Claude Code |
Made with AI tools
This project was built with AI coding assistants (mainly Cursor). Humans directed the work, reviewed what shipped, and remain responsible for it. Treat the template like any other community Docker or Unraid project: verify on your own server, and post in the support thread if something is wrong. Notes for working on the agent setup in this repository are in docs/AI-WORKFLOW.md.
Support
Questions and problems go to the Unraid forum thread. Leave the Eugen key out of the post.
Requirements
Categories
Related apps
Explore more like this
Explore allDetails
ghcr.io/matthewariel/warhost:latestRuntime arguments
- Web UI
http://[IP]:[PORT:11400]/- Network
host- Shell
sh- Privileged
- false
Template configuration
Ini files for this container only. The next container uses this path with its own game port, for example /mnt/user/appdata/warno/10401/settings. Set Advanced View WebUI to http://[IP]:[PORT:11401]/.
- Target
- /server/settings
- Default
- /mnt/user/appdata/warno/10400/settings
- Value
- /mnt/user/appdata/warno/10400/settings
Login from Eugen's reply, exactly as written. Not your Steam name; this login and the key are a matching pair good for five containers.
- Target
- EUGEN_LOGIN
Key from the same reply. Paste the whole key. The log shows only the last 4 characters.
- Target
- EUGEN_DEDICATED_KEY
Public address players connect to. Not a hostname, and not this Unraid server's LAN address.
- Target
- EXPOSEDIP
true serves the lobby page on WebUI Port. Set the server name, map, and mods there. For the next container, set Advanced View WebUI to http://[IP]:[PORT:11401]/. false leaves the Docker button with nothing listening.
- Target
- WEB_UI
- Default
- true
- Value
- true
This port must be free on the Unraid host. Forward it as TCP and UDP. The next container uses this number plus 1. Set WebUI Port to this number plus 1000. Set Advanced View WebUI to http://[IP]:[PORT:11401]/.
- Target
- EXPOSEDPORT
- Default
- 10400
- Value
- 10400
Port the lobby page listens on: 11400 on the first server, then the next number. Set Advanced View WebUI to http://[IP]:[PORT:11401]/ or the Docker button still opens 11400. Do not forward it.
- Target
- WEB_PORT
- Default
- 11400
- Value
- 11400
true rewrites login.ini each start, fills in missing lobby files, and refreshes a bare Workshop id to id/Version. false leaves the file contents in place and sets login.ini to mode 600.
- Target
- WRITE_CONFIG
- Default
- true
- Value
- true