Freeciv Dedicated Multiplayer Server on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and use of the Freeciv 3.2 dedicated multiplayer game server on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images.
freeciv-server is the dedicated multiplayer server of Freeciv, the free and open source turn based empire building strategy game. It is the headless companion to the desktop game: your players keep using their normal Freeciv client, connect to your VM's address instead of a public server, and get their own lobby where they can chat, take a player slot, set up the ruleset and play a full game whose entire rules engine runs on your host. The server holds the world, resolves every turn and relays state to the clients.
This image ships the SERVER, not the game. There is no desktop client and no graphical interface on this VM, and there is no web interface either. Everything in this guide is done over SSH, plus the in game lobby chat your players use from a connected Freeciv client. Your players supply their own copy of the game.
Only the server half of Freeciv's data is redistributed. Freeciv's own build system splits its data tree into server data and client data. This image is a server only build, so it installs the rulesets, nation definitions and scenarios the rules engine genuinely needs, and installs none of the tilesets, sound sets, music sets, themes or national flag artwork, which belong to the client. Everything on this VM is covered by Freeciv's GNU General Public License version 2, whose text ships at /usr/share/doc/freeciv-server/COPYING alongside a manifest at /usr/share/doc/freeciv-server/LICENCE-MANIFEST.txt naming every data directory installed.
Version compatibility matters, and it is not optional. Freeciv's network protocol is capability gated. This server is built from the 3.2.5 upstream source release and admits the 3.2.x client series only. A 3.1 client, or an older one, is cleanly refused with the server's own explanation rather than half connecting. Ubuntu 24.04's own repository only carries the older 3.1 line, which is exactly why this image builds 3.2 from source instead.
Security by design. A public game port is the whole point of a game server, so everything else is locked down:
-
There is no network administrator password, by design, so there is nothing to leak. Freeciv has no password protected remote console. Its only remote privilege path is the
hackaccess level, which is granted solely to a client that can read a challenge file the server writes inside its own state directory, unreadable both to remote clients and to other local users. -
No connection can escalate itself. The configuration this VM generates on first boot sets
cmdlevel basic firstandcmdlevel basic new, so every network connection, including the very first to arrive, is capped at thebasiccommand access level.basicis normal play: chat, taking a player, voting. It cannot run privileged server commands. -
Administration is local only. You drive the server console with
sudo freecivctl, which writes to a FIFO inside a runtime directory reachable only by root and the service account. Nothing on the network can reach it. -
The server physically cannot start before first boot has configured it.
freeciv-server.serviceis 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 the game port cannot be bound by a server carrying configuration written on somebody else's machine. -
One port, and nothing else. TCP
5556is the only listener this product opens. LAN announcement is disabled and the server does not advertise itself to the public Freeciv metaserver, so your appliance is never listed publicly unless you choose to change that. -
The server runs unprivileged as the dedicated
freecivsystem account under a hardened systemd unit.
What is included:
-
freeciv-server 3.2.5, built from the official upstream source release with the server target only, verified against a pinned SHA 256 checksum before extraction, running under systemd as
freeciv-server.service -
The full set of server rulesets, including
civ2civ3,classic,multiplayer,civ1,civ2,sandboxandalien, plus the nation definitions and the bundled map scenarios -
freecivctl, a root only wrapper that drives the server console -
freeciv-selfcheck, a bundled command that proves the server end to end by driving Freeciv's real wire protocol as independent clients and creating and starting a real game -
Ubuntu 24.04 LTS, fully patched, with unattended security upgrades enabled
Key facts
| Item | Value |
|---|---|
| Platform | Ubuntu 24.04 LTS on Azure |
| Default administrative user | azureuser |
| Game port | 5556/tcp |
| Accepted client versions | 3.2.x |
| Server binary | /usr/local/bin/freeciv-server |
| Server configuration | /etc/freeciv/cloudimg.serv |
| Server data | /usr/local/share/freeciv/ |
| Connection details | /root/freeciv-credentials.txt |
Prerequisites
-
Active Azure subscription, an SSH public key, and a VNet and subnet in the target region
-
Subscription to this listing on Azure Marketplace
-
A Network Security Group allowing TCP 22 for administration and TCP 5556 for the game itself. Your players connect to
5556, so it must be reachable from wherever they are. No other port needs to be opened. -
A copy of Freeciv 3.2.x on each player's machine. The server admits that series only.
Recommended virtual machine size: Standard_B2s with 2 vCPU and 4 GB RAM comfortably hosts a community lobby and a full game. Unlike a pure relay, a Freeciv server simulates the whole world and resolves every turn, and the artificial intelligence players are the heaviest part of that, so for a large map with many AI players, or for several concurrent games, choose Standard_D2s_v5 or above.
Deploy the virtual machine
Deploy from the Azure Portal by selecting the image from Azure Marketplace, choosing your VM size, and supplying your SSH public key for the azureuser account. Or deploy from the Azure CLI.
These commands run on your own workstation, not on the VM:
az vm create \
--resource-group my-resource-group \
--name my-freeciv-vm \
--image <this-marketplace-image> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group my-resource-group --name my-freeciv-vm --port 5556
Connect over SSH once the VM is running:
ssh azureuser@<vm-ip>
Confirm the server is healthy
The server starts automatically once first boot has written this VM's configuration. Check it and confirm the version:
systemctl is-active freeciv-server
Expected output
active
freeciv-server --version
Expected output
Freeciv version 3.2.5
Now confirm the network posture. Exactly one port belongs to this product, and it is the game port:
ss -tln | grep 5556
Expected output
LISTEN 0 1024 0.0.0.0:5556 0.0.0.0:*
LISTEN 0 1024 [::]:5556 [::]:*

Retrieve your connection details
First boot writes a root only file describing what your players need. It contains no password, because this server has none:
sudo cat /root/freeciv-credentials.txt
Expected output
# Freeciv 3.2.5 dedicated multiplayer server — generated on this VM's
# first boot by cloudimg.
#
# THIS SERVER HAS NO NETWORK ADMINISTRATOR PASSWORD, BY DESIGN.
...
FREECIV_URL=freeciv://10.0.0.4:5556
freeciv.host=10.0.0.4
freeciv.port=5556
freeciv.version=3.2.5
freeciv.client_series_required=3.2.x
The address recorded there is the address the VM sees for itself. If your players are outside the VNet, give them the VM's public IP address or DNS name instead, with the same port:
PUB=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2021-02-01&format=text")
echo "public : ${PUB:-none reported by instance metadata}"
echo "private: $(hostname -I | awk '{print $1}')"
Expected output
public : none reported by instance metadata
private: 10.0.0.4
Azure's instance metadata returns an empty public address for a Standard SKU
public IP, which is why the connection details file records the private address.
When it comes back empty like this, read the public address from the VM's Overview
page in the Azure Portal, or with az vm list-ip-addresses from your workstation,
and give your players that address with port 5556.

Prove the server really hosts games
A listening socket is not proof that a game server works, so this image ships a checker that speaks Freeciv's real wire protocol. It connects genuine clients, confirms an incompatible client and a privilege escalation are both refused, then creates and starts a real game on a private second instance so your live lobby is never disturbed:
sudo freeciv-selfcheck
Expected output
[freeciv-selfcheck] 1. Checking the server binary reports the pinned upstream version
OK: Freeciv version 3.2.5
[freeciv-selfcheck] 2. Checking the live service is active and bound on this VM's routable address
OK: freeciv-server.service active, TCP 5556 listening
[freeciv-selfcheck] 3. Joining the LIVE server as a real protocol client at 10.0.0.4:5556
OK: admitted by the live server, header widened, 3330 packets received
[freeciv-selfcheck] 4. Checking an incompatible client version is refused by the live server
OK: refused, server said: The client is missing a capability that this server needs.
[freeciv-selfcheck] 5. Checking network escalation to the 'hack' administrator level is refused
OK: hack access refused (reply: you_have_hack=false)
[freeciv-selfcheck] 6. Starting an isolated server instance on port 5599 for the game-lifecycle proof
OK: isolated instance listening on 5599
[freeciv-selfcheck] 7. Connecting TWO fully independent clients to the same server
OK: both clients joined; server lists them
[freeciv-selfcheck] 8. Checking a lobby message from one client is relayed live to the other
OK: the server relayed 'cloudimg-...' from cloudimgalpha to cloudimgbravo
[freeciv-selfcheck] 9. Creating an AI player and STARTING the game from the server console
OK: server console: > Starting game.
[freeciv-selfcheck] 10. Checking both connected clients are participants in the running game
OK: game running with both clients and the AI as players
[freeciv-selfcheck] 11. Checking the administrative control plane is local only
OK: console FIFO mode 660 in a 750 directory, state dir 750, network connections capped at 'basic'
FREECIV_SELFCHECK_OK: Freeciv 3.2.5 dedicated server verified end to end
It is safe to run at any time, including while a game is in progress, because the half that creates and starts a game runs against a private instance on its own port with its own throwaway state, and that instance is stopped again when the check finishes.

Point your players at the server
Each player opens their own Freeciv 3.2.x client and:
-
Chooses Connect to Network Game from the start screen
-
Enters your server's address in the host field and
5556as the port -
Enters the name they want to play under, then connects
They arrive in your lobby, and the server gives each of them a player slot automatically. From there the group agrees a ruleset and settings in the usual way and one of them starts the game, or you start it yourself from the server console as shown below.
If a player is refused, the reason is almost always the client version. The server tells them so explicitly rather than failing silently.
Run the server console
Everything the Freeciv server manual describes can be driven from the shell with freecivctl. It sends one command to the running server and prints what the server said back:
sudo freecivctl list players
Expected output
> List of players:
------------------------------------------------------------------------------
AI*1 [#ff0000]: Team 1, user Unassigned
AI, classic, difficulty level Easy
------------------------------------------------------------------------------
sudo freecivctl list connections
Expected output
> List of connections to server:
------------------------------------------------------------------------------
<no connections>
------------------------------------------------------------------------------
Useful commands include help, show, list scenarios, create <name> to add an AI player, remove <name>, cut <connection> to disconnect a player, save <name> to write a savegame, and start to begin the game.

Change the server settings
Server settings are changed live with set, and the change takes effect immediately:
sudo freecivctl set aifill 8
The settings most operators change first:
| Setting | What it does |
|---|---|
aifill |
How many player slots are filled with artificial intelligence players |
timeout |
Seconds each turn is allowed before it ends automatically, 0 for no limit |
size or mapsize |
How large the world is |
skilllevel |
Difficulty of the artificial intelligence players |
endturn |
The turn the game finishes on |
To make a change permanent, add it to the configuration this VM generated at first boot and restart the service. The file is a list of server console commands executed at start up:
sudo cat /etc/freeciv/cloudimg.serv
Edit it with your preferred editor, then apply it:
sudo systemctl restart freeciv-server
Choose a different ruleset
The image installs Freeciv's full server ruleset set. civ2civ3 is the upstream default; multiplayer is tuned for human against human games:
sudo freecivctl list rulesets
Switch ruleset before a game starts:
sudo freecivctl rulesetdir multiplayer
To make that the default for every restart, add the same line to /etc/freeciv/cloudimg.serv.
Save and load games
The server writes savegames under its own state directory:
sudo freecivctl save mygame
sudo ls -la /var/lib/freeciv/saves/
Expected output
> Game saved as /var/lib/freeciv/saves/mygame.sav.zst
-rw-r----- 1 freeciv freeciv 3394 Aug 7 12:21 mygame.sav.zst
The server also autosaves as a game progresses, into the same directory.
To bring a saved game back, use the console load <name> command, or start the
server from it by adding --file /var/lib/freeciv/saves/<name>.sav.zst to the
ExecStart line in /usr/local/sbin/freeciv-server-run. Load a savegame into the
ruleset it was created under: Freeciv reads the ruleset back out of the savegame,
and loading one into a server whose ruleset directory has since been changed can
be refused.
Server components
| Component | Version | Purpose |
|---|---|---|
| freeciv-server | 3.2.5 | The dedicated multiplayer game server |
| Freeciv server data | 3.2.5 | Rulesets, nation definitions and scenarios the rules engine needs |
| Ubuntu | 24.04 LTS | Base operating system |
Filesystem layout
| Path | Purpose |
|---|---|
/usr/local/bin/freeciv-server |
The server binary |
/usr/local/share/freeciv/ |
Rulesets, nations and scenarios |
/etc/freeciv/cloudimg.serv |
This VM's server configuration |
/var/lib/freeciv/ |
Savegames, autosaves and server state |
/run/freeciv/console.in |
The root only server console channel |
/usr/local/sbin/freecivctl |
Server console wrapper |
/usr/local/sbin/freeciv-selfcheck |
End to end protocol checker |
/root/freeciv-credentials.txt |
This VM's connection details |
/usr/share/doc/freeciv-server/ |
GPL 2.0 licence text and data manifest |
Network ports
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH administration |
| 5556 | TCP | Freeciv game port, the only listener this product opens |
Managing the service
sudo systemctl status freeciv-server
sudo systemctl restart freeciv-server
sudo journalctl -u freeciv-server -n 50 --no-pager
Scripts and log files
| Path | Purpose |
|---|---|
/usr/local/sbin/freeciv-firstboot.sh |
First boot configuration script |
/var/log/cloudimg-firstboot.log |
First boot log |
/etc/cloudimg-build-versions |
Pinned upstream version and source checksum |
The server's own console output goes to the systemd journal, not to a log file.
On startup
On the very first boot the image writes this VM's server configuration, releases the two start up gates, starts freeciv-server.service, waits for the game port to bind and records the connection details. On every later boot the server simply starts.
Troubleshooting
Players are refused with a message about a missing capability
Their client is not in the 3.2.x series. Freeciv's protocol is capability gated and a 3.1 or older client cannot negotiate with a 3.2 server. Ask them to install Freeciv 3.2.x. The refusal message names both versions.
Nothing answers on port 5556
Check the service and the gates in order:
systemctl is-active freeciv-server
If it is inactive, check whether first boot completed:
ls -la /var/lib/cloudimg/
You should see both freeciv-firstboot.done and freeciv-ready. If they are missing, first boot did not finish; read /var/log/cloudimg-firstboot.log.
If the service is active but players still cannot reach it, the port is not open in your Network Security Group. Confirm the server itself is listening:
ss -tln | grep 5556
freecivctl says the console channel is not present
The FIFO lives on tmpfs and is recreated each time the service starts, so this means the server is not running:
sudo journalctl -u freeciv-server -n 50 --no-pager
A player cannot run server commands
That is intended. Every network connection is capped at the basic access level, so privileged commands are refused. Run them yourself with sudo freecivctl instead.
If you deliberately want to hand a connected player control, raise that one connection's level from the console with sudo freecivctl cmdlevel ctrl NAME, substituting the name the player connected under. Understand what that does: ctrl lets them change settings and start the game, and the higher admin and hack levels give them progressively more of the server. Grant it to a named connection you trust, temporarily, and never by changing the cmdlevel first or cmdlevel new defaults in the configuration, which would hand that power to whoever connects next.
The self check reports an error
Read the numbered step that failed. It names the exact assertion. Common causes are the service not being active, or another process already holding the checker's scratch port 5599.
Security recommendations
-
Restrict SSH. Limit TCP 22 in your Network Security Group to your own address, and leave TCP 5556 as the only broadly reachable port.
-
Leave the access level capped.
cmdlevel basic firstandcmdlevel basic neware what stop an arriving connection from taking control of your server. Raise a specific player's level deliberately and temporarily rather than changing those defaults. -
Keep administration on SSH.
freecivctlis root only for a reason: it is the full server console. Do not expose it another way. -
Keep the VM patched. Unattended security upgrades are enabled; reboot after kernel updates.
-
Watch the disk if you enable frequent autosaves. Savegames accumulate under
/var/lib/freeciv/saves/.
Support
-
cloudimg support: support@cloudimg.co.uk
-
Freeciv server manual: https://www.freeciv.org/wiki/Server_Manual
-
Freeciv project: https://www.freeciv.org/
Freeciv is free software published under the GNU General Public License version 2. cloudimg is not affiliated with, endorsed by, or sponsored by the Freeciv project; this image packages the unmodified upstream dedicated server.