Deployment guide

Wesnoth

Overview

wesnothd is the dedicated multiplayer server of The Battle for Wesnoth, the open source turn-based fantasy strategy game. It is the headless companion to the desktop game. Your players keep using their normal Wesnoth client and change the server address from the public one to your VM. They get their own lobby where they can chat, create games, join each other and play a full match relayed through your host. You get moderator control over that lobby.

This SecureAnyCloud image runs the Wesnoth 1.18 dedicated multiplayer game server on Ubuntu 24.04 on Azure. It ships the server, not the game. There is no desktop client, no graphical interface and no web interface on this VM. You do everything in this guide over SSH, plus the in-game admin commands you type from a connected Wesnoth client. Your players supply their own copy of the game.

Version compatibility is strict. Wesnoth's network protocol is version-gated. This server is built from the 1.18.7 upstream source release and accepts the 1.18.* client series only. A 1.16 client, or a 1.19 development build, is cleanly refused with the accepted version list rather than half connecting. Ubuntu 24.04's own repository carries only the older 1.16 line, which is why this image builds 1.18 from source.

What you get:

  • wesnothd 1.18.7, built from the official upstream source release with the server target only, and verified against a pinned SHA-256 checksum before extraction. It runs under systemd as wesnothd.service.
  • No game content redistributed. wesnothd is a WML relay and needs no campaigns, maps, artwork or music, so none are installed. The only Wesnoth bytes on this VM are the server binary and its GNU General Public License version 2 license text under /usr/share/doc/wesnothd/.
  • No administrator password in the image. The captured image contains no server configuration file at all. The moderator password is generated uniquely on your VM at first boot and written only to /etc/wesnothd/server.cfg and a root-only credentials file. Nothing is shared between customers.
  • A server that cannot start before first boot completes. wesnothd.service is enabled so it survives reboots, but it carries two start-up conditions: the first-boot ready marker and the server configuration. Neither exists in the shipped image, so a server with no moderator password cannot bind the game port.
  • One port, and nothing else. TCP 15000 is the only listener this product opens. The moderator control channel is a FIFO inside a directory readable only by root and the service account. The configuration file that holds the password is not world-readable.
  • An unprivileged server. It runs as the dedicated wesnothd system account under a hardened systemd unit.
  • wesnothd-selfcheck, a bundled command that proves the server end to end. It drives the real Wesnoth wire protocol as two independent clients, creates a game and relays a lobby message.
  • Ubuntu 24.04 LTS, patched at build time, with unattended security upgrades enabled.

Key facts:

  • Platform: Ubuntu 24.04 LTS on Azure
  • Default administrative user: azureuser
  • Game port: 15000/tcp
  • Accepted client versions: 1.18.*
  • Server binary: /usr/local/bin/wesnothd
  • Server configuration: /etc/wesnothd/server.cfg
  • Per-VM credentials: /root/wesnothd-credentials.txt

Prerequisites

  • An active Azure subscription, an SSH public key, and a VNet and subnet in the target region.
  • A subscription to this listing on Azure Marketplace.
  • A Network Security Group that allows TCP 22 for administration and TCP 15000 for the game itself. Your players connect to 15000, so it must be reachable from wherever they are. No other port needs to be opened.
  • A copy of Wesnoth 1.18.x on each player's machine. The server accepts that series only.

Recommended virtual machine size: Standard_B2s with 2 vCPU and 4 GB RAM comfortably hosts a community lobby with several concurrent games. wesnothd relays turns rather than simulating them, so it is light on CPU. For a large public server or a tournament with many simultaneous matches, choose Standard_D2s_v5 or above.

Deploy the virtual machine

Deploy from the Azure Portal. Select the image from Azure Marketplace, choose your VM size and supply your SSH public key for the azureuser account. Or deploy from the Azure CLI.

Run these commands on your own workstation, not on the VM:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:wesnoth-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-resource-group \
  --name my-wesnoth-vm \
  --image sac1647283583153:wesnoth-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group my-resource-group --name my-wesnoth-vm --port 15000

When the VM is running, connect over SSH:

ssh azureuser@<vm-ip>

Confirm the server is healthy

The server starts automatically once first boot has generated your moderator password. Check that it is running and confirm the version:

systemctl is-active wesnothd wesnothd --version

Expected output

active Battle for Wesnoth server 1.18.7

Next, confirm the network posture. Exactly one port belongs to this product, and it is the game port:

ss -tln | grep 15000

Expected output

LISTEN 0 4096 0.0.0.0:15000 0.0.0.0:* LISTEN 0 4096 [::]:15000 [::]:*

This is the output you want: 15000 reachable by your players, and nothing else added to the machine.

Retrieve your per-VM credentials

First boot generates the moderator password on this VM, and it exists nowhere else. Read it as root:

sudo cat /root/wesnothd-credentials.txt

Expected output

# Wesnoth 1.18.7 dedicated multiplayer server (wesnothd) — generated on
# first boot. The administrator password below is UNIQUE to this VM. Store it
# somewhere safe; it is shown in plain text only here and in the server config.
# --- The game server your players connect to --- WESNOTHD_URL=wesnoth://<vm-ip>:15000 wesnothd.host=<vm-ip> wesnothd.port=15000 wesnothd.versions_accepted=1.18.*
# --- Administrator credential ---
# In a connected Wesnoth 1.18 client, type this in the lobby chat:
# /query admin <WESNOTHD_ADMIN_PASSWORD>
# The server replies "You are now recognized as an administrator." and you can
# then use /query kick, /query ban, /query motd and the rest. wesnothd.admin_password=<WESNOTHD_ADMIN_PASSWORD>
# Players join with: Multiplayer -> Join Official Server -> change the address to
# <vm-ip>:15000
# Only Wesnoth 1.18.x clients are admitted; anything else is cleanly refused.
#
# Re-verify the whole server at any time (drives a real two-client session):
#
sudo wesnothd-selfcheck

wesnothd.admin_password is the moderator password for this server and this server only. Store it somewhere safe. Anyone who has it can moderate your lobby, so treat it like a root password.

The address recorded in WESNOTHD_URL and wesnothd.host is the address of the VM's own network interface, as the VM sees it. Azure's instance metadata service returns an empty body for Standard SKU public IP addresses. First boot therefore falls back to the interface address rather than writing an empty host.

Your players connect on the VM's public address. You can read it at any time with az vm show ... --query publicIps, shown further down this guide. The port is 15000 either way.

Prove the server really hosts games

A listening socket does not prove that a game server works. The bundled self-check drives the real Wesnoth wire protocol as two independent clients. It performs these checks:

  • Logs both clients into your lobby.
  • Confirms that a client on an unsupported version is refused.
  • Relays a lobby chat message from one client to the other.
  • Has the first client create a multiplayer game, and confirms that the second client sees it advertised live in the lobby game list.
  • Tests your moderator password against a wrong password and the real one.
  • Checks that other users on the VM cannot read the control channel or the configuration file.
sudo wesnothd-selfcheck

Expected output

[wesnothd-selfcheck] 1. wesnothd binary version OK: Battle for Wesnoth server 1.18.7 [wesnothd-selfcheck] 2. game port 15000 reachable on this VM's routable address <vm-ip> OK: TCP <vm-ip>:15000 accepts connections [wesnothd-selfcheck] 3. host client logs in and joins the lobby OK: cimg-host-f80d79 joined the lobby (handshake 42, version 1.18.7 accepted, [join_lobby] received) [wesnothd-selfcheck] 4. second, independent client logs in and joins the same lobby OK: cimg-obs-f80d79 joined the lobby alongside cimg-host-f80d79 [wesnothd-selfcheck] 5. client on an unsupported version is refused OK: server returned [reject] with its accepted_versions list [wesnothd-selfcheck] 6. lobby chat is relayed live from one client to the other OK: message relayed cimg-host-f80d79 -> cimg-obs-f80d79 through the server [wesnothd-selfcheck] 7. host creates a multiplayer game OK: [create_game] and its [scenario] accepted for 'sac selfcheck f80d79' [wesnothd-selfcheck] 8. the second client sees the new game advertised in the lobby game list OK: cimg-obs-f80d79 sees 'sac selfcheck f80d79' advertised by the server (broadcast live) [wesnothd-selfcheck] 9. per-VM administrator credential is accepted, a wrong one is refused OK: wrong password refused; the per-VM password granted administrator rights [wesnothd-selfcheck] 10. control FIFO and server configuration are not world-accessible OK: /run/wesnothd/socket mode 640 - not world-writable OK: /etc/wesnothd/server.cfg mode 640 - not world-readable WESNOTHD_SELFCHECK_OK

Run the self-check any time you want to confirm that the server is serving, for example after you change the configuration or resize the VM.

Point your players at the server

Each player needs Wesnoth 1.18.x installed. In the game, follow these steps:

  • Choose Multiplayer from the title screen.
  • Choose Join Official Server, then edit the server address. If your client offers it, use Connect to Server instead.
  • Enter your VM's public address and port, for example 20.0.0.1:15000.
  • Pick any username and connect. The server has no registration, so it accepts any name that is not already in use.

Players land in your lobby, where they can create a game, join one another and start playing. The WESNOTHD_URL line in the credentials file holds the same address in the wesnoth:// form that recent clients accept directly.

To find the public address of the VM at any time, run this on your own workstation:

az vm show --resource-group my-resource-group --name my-wesnoth-vm \
  --show-details --query publicIps --output tsv

Moderate the lobby from inside the game

Connect with any Wesnoth 1.18 client. Then type this in the lobby chat, substituting the password from your credentials file:

/query admin <WESNOTHD_ADMIN_PASSWORD>

The server replies You are now recognized as an administrator. and your client gains moderator rights. A wrong password is refused with Error: wrong password, and the attempt is logged on the server.

Once the server recognizes you, you can use these moderation commands from the lobby chat:

Command What it does

/query status Lists connected players and their addresses

/query games Lists the games currently running on the server

/query kick <nick> Disconnects a player

/query kban <nick> <time> <reason> Kicks and bans a player for a period

/query bans Shows the current ban list

/query unban <mask> Lifts a ban

/query motd <text> Sets the message of the day players see on joining

/query metrics Shows server traffic and performance counters

/query help Lists every command the server accepts

Moderate from the server shell

The same commands are available without a game client through the server's control FIFO. Use it for scripting, or in an emergency when you cannot connect a client. Run as root:

sudo timeout 5 sh -c 'echo "status" > /run/wesnothd/socket'
sudo journalctl -u wesnothd --since "1 minute ago" --no-pager | tail -20

The server executes the command and writes the answer to its journal. The FIFO lives in a directory owned by root and the wesnothd service account with mode 0750, so ordinary users on the VM cannot drive it.

Change the server settings

The configuration lives at /etc/wesnothd/server.cfg and is read at start-up. It is owned root:wesnothd with mode 0640, because it holds your moderator password.

sudo cat /etc/wesnothd/server.cfg

Useful keys:

Key Meaning

versions_accepted Which client series may connect. 1.18.* by default. Widening this to a series the binary does not speak will break games, not enable them

passwd The moderator password checked by /query admin

motd The message of the day shown when a player joins

max_messages and messages_time_period Chat flood control: how many messages a player may send in that many seconds

save_replays Whether finished games are written to disk. Off by default so the appliance does not grow its disk unattended

fifo_path The shell control channel described above

After editing, restart the server. Connected players are disconnected, so choose a quiet moment:

sudo systemctl restart wesnothd systemctl is-active wesnothd

Turn on replay saving

To keep finished games for later viewing, give the server a directory it can write to and enable the option:

sudo install -d -o wesnothd -g wesnothd -m 0750 /var/lib/wesnothd/replays
sudo sed -i 's|^save_replays=.*|save_replays="yes"|' /etc/wesnothd/server.cfg
sudo sh -c 'grep -q ^replay_save_path /etc/wesnothd/server.cfg || echo "replay_save_path=\"/var/lib/wesnothd/replays/\"" >> /etc/wesnothd/server.cfg'
sudo systemctl restart wesnothd

Replays accumulate indefinitely, so keep an eye on du -sh /var/lib/wesnothd/replays or prune them on a schedule.

Change the moderator password

Rotate the password whenever someone leaves your moderator group:

NEW_PASSWORD=$(openssl rand -hex 24)
sudo sed -i "s|^passwd=.*|passwd=\"${NEW_PASSWORD}\"|" /etc/wesnothd/server.cfg
sudo sed -i "s|^wesnothd.admin_password=.*|wesnothd.admin_password=${NEW_PASSWORD}|" /root/wesnothd-credentials.txt
sudo systemctl restart wesnothd
sudo wesnothd-selfcheck

The self-check at the end proves that the new password authenticates, so you never rotate into a server you cannot moderate.

Server components

Component Version Purpose

wesnothd 1.18.7 The dedicated multiplayer game server, built from the official upstream source release, server target only

Ubuntu Server 24.04 LTS Base operating system, patched at build time, with unattended security upgrades enabled

systemd unit wesnothd.service Runs the server unprivileged, gated so it cannot start before first boot has minted your password

systemd unit wesnothd-firstboot.service Runs once on your first boot to generate the per VM moderator password and configuration

Filesystem layout

Path Purpose

/usr/local/bin/wesnothd The server binary

/etc/wesnothd/server.cfg Server configuration, including the moderator password. 0640 root:wesnothd

/run/wesnothd/socket Moderator control FIFO, inside a 0750 directory

/root/wesnothd-credentials.txt Per VM credentials. 0600 root:root

/usr/share/doc/wesnothd/COPYING The upstream GNU General Public License version 2 text

/usr/local/sbin/wesnothd-selfcheck End to end server self check

/var/lib/sac/data/ First boot markers and sentinel

/var/lib/sac/config/sac-build-versions What was built into this image, and from which pinned source

Network ports

Port Bound to Purpose

15000/tcp All interfaces The Wesnoth game port. Your players connect here

22/tcp All interfaces SSH administration

Managing the service

sudo systemctl status wesnothd --no-pager sudo systemctl restart wesnothd
sudo systemctl stop wesnothd
sudo journalctl -u wesnothd --no-pager -n 50

Scripts and log files

Path Purpose

/usr/local/sbin/wesnothd-firstboot.sh Generates the per VM moderator password and configuration on first boot

/usr/local/sbin/wesnothd-selfcheck Drives a real two client protocol session against this server

/var/log/sac/sac-firstboot.log What first boot did on this VM

/stage/scripts/initial_boot_update.sh Applies operating system updates on first boot

/stage/scripts/initial_boot_update.log Output of that update run

On startup

On the very first boot, wesnothd-firstboot.service generates a moderator password unique to this VM and writes /etc/wesnothd/server.cfg. It releases the two start-up conditions on wesnothd.service, starts the server, waits for the game port to bind and writes your credentials file. It then disables itself, so it never runs again. Its log is /var/log/sac/sac-firstboot.log.

/stage/scripts/initial_boot_update.sh applies operating system updates on first boot from a root crontab entry. List it with:

sudo crontab -l

To disable it, edit the root crontab with sudo crontab -e, then remove the initial_boot_update.sh line.

Troubleshooting

Players get "The server responded with an unknown version" or are refused on connect

The client series does not match. This server accepts 1.18.* only. Check what the server thinks:

sudo grep versions_accepted /etc/wesnothd/server.cfg wesnothd --version

Ask the player to install Wesnoth 1.18.x. Do not widen versions_accepted to a series this binary does not speak. The handshake would succeed, and the game would then desynchronize.

Nothing answers on port 15000

First check the service and the two start up conditions:

systemctl is-active wesnothd
systemctl status wesnothd --no-pager | head -20 sudo ls -l /var/lib/sac/data/wesnothd-ready /etc/wesnothd/server.cfg

If systemctl status reports the unit was skipped because a condition failed, first boot did not complete. Look at what it did:

sudo cat /var/log/sac/sac-firstboot.log

If the service is active locally but players still cannot reach it, the port is not open in Azure. Open it from your workstation:

az vm open-port --resource-group my-resource-group --name my-wesnoth-vm --port 15000

/query admin says "Error: wrong password"

You are using a password from somewhere other than this VM. Every VM gets its own password. Read yours with:

sudo grep '^wesnothd.admin_password' /root/wesnothd-credentials.txt

If the credentials file and /etc/wesnothd/server.cfg differ, the server checks against server.cfg.

/query admin says "No password set"

server.cfg has no passwd key, usually because it was edited by hand. Restore it and restart:

sudo grep '^passwd' /etc/wesnothd/server.cfg || echo "no passwd key present"
sudo systemctl restart wesnothd

The self check reports an error

Read the step the self-check stopped on, then look at the server's own view:

sudo journalctl -u wesnothd --no-pager -n 60

A failure at the login step usually means the service is not running. A failure at the game creation step means the server is up but rejecting the session. The journal explains why.

Security recommendations

  • Restrict SSH. Limit TCP 22 in your Network Security Group to your own address range, and use SSH keys rather than passwords.
  • Open the game port only as wide as you need. TCP 15000 must be reachable by your players. If your community is on a known network, scope the rule to that network rather than the whole internet.
  • Guard the moderator password. It is the only privileged boundary on this server. Keep /root/wesnothd-credentials.txt root-only, rotate the password when someone leaves your moderator group, and never paste it into a public lobby.
  • Set a message of the day with /query motd so players can see they are on your server and know your rules.
  • Use the ban list. /query kban and /query bans are the tools for dealing with disruptive players. The server keeps bans across reconnects.
  • Keep the operating system patched. Unattended security upgrades are enabled. Check them with systemctl status unattended-upgrades --no-pager.
  • Watch disk if you enable replay saving. Replays are off by default for this reason.

Support

SecureAnyCloud provides 24/7 support for this image. Contact sales@secureanycloud.com with your VM's region, size and the output of sudo wesnothd-selfcheck.

Upstream project documentation for the multiplayer server is at wiki.wesnoth.org/MultiplayerServers. BATTLE FOR WESNOTH and WESNOTH are names and marks of The Battle for Wesnoth project and its contributors. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by that project. This image packages the project's dedicated server, which is licensed under the GNU General Public License version 2, unmodified.

Deploy on Azure

Launch Wesnoth 1.18 Compatible Dedicated Multiplayer Game Server on Ubuntu 24.04 on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure