Gaming Azure

Freeciv Dedicated Multiplayer Server on Ubuntu 24.04 on Azure User Guide

| Product: Freeciv 3.2 Compatible Dedicated Multiplayer Game Server on Ubuntu 24.04 on Azure

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 hack access 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 first and cmdlevel basic new, so every network connection, including the very first to arrive, is capped at the basic command access level. basic is 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.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 the game port cannot be bound by a server carrying configuration written on somebody else's machine.

  • One port, and nothing else. TCP 5556 is 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 freeciv system 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, sandbox and alien, 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         [::]:*

The dedicated multiplayer game server active under systemd, with the Freeciv game port as its only listener

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.

The per VM connection details this server writes on first boot: the address players point their Freeciv client at

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.

A real protocol session: clients admitted, an incompatible client and a privilege escalation refused, a game created and started

Point your players at the server

Each player opens their own Freeciv 3.2.x client and:

  1. Chooses Connect to Network Game from the start screen

  2. Enters your server's address in the host field and 5556 as the port

  3. 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.

The root only server console: listing the players in the running game and changing a live server setting

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 first and cmdlevel basic new are 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. freecivctl is 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

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.