
Ports, firewalls and public listing
A server that runs is not yet a server people can join. This guide covers every port BattleSpades uses, firewall and router setup, relays for hosts without a public IP, and how to appear in the AoSPlay server list and the original Steam browser.
Ports at a glance
Everything is UDP. A plain server needs exactly one port.
| Port (default) | Protocol | Needed when | Set by |
|---|---|---|---|
27015 (sample config) | UDP | Always: game traffic (ENet) and A2S server queries share this socket | [server] port or --port |
game port + 1 (e.g. 27016) | UDP | Only with Steam listing: Steam A2S query socket | [steam] query_port (0 = game + 1) |
8766 | UDP | Only with Steam listing: Steam updater/master traffic | [steam] steam_port |
32887 | UDP | Only if players must join from rows of the unmodified retail Steam browser, which always connects to 32887 | set [server] port = 32887 |
There is no remote-admin TCP port: administration happens in game through chat commands (/admin). If you leave out [server] port entirely, the server listens on 27015, the same as the shipped config.toml. 32887 is only an opt-in for the stock Steam browser.
Open the firewall
Allow inbound UDP on the game port in the operating system firewall and in any cloud firewall / security group in front of a VPS.
New-NetFirewallRule -DisplayName "BattleSpades 27015" -Direction Inbound `
-Protocol UDP -LocalPort 27015 -Action Allowsudo ufw allow 27015/udp
sudo firewall-cmd --permanent --add-port=27015/udp
sudo firewall-cmd --reloadOn Windows the first launch may also show a firewall prompt for BattleSpades.exe or python.exe; allowing it on private and public networks has the same effect.
Home hosting: port forwarding and NAT
- 01Fix the host's LAN address
Give the server machine a DHCP reservation (or static IP) in your router, e.g.
192.168.1.20. - 02Forward UDP
In the router's port-forwarding page, forward external UDP
27015to192.168.1.20port27015. Forward any Steam ports too if you use Steam listing. - 03Find your public address
Look up your public IPv4 (search “what is my IP”). Players connect to
that-address:27015. - 04Test from outside
Join from a different internet connection, or run the A2S probe below from another network.
python deploy/a2s_probe.py --host 203.0.113.10 --port 27015List your server on AoSPlay
The AoSPlay (Revival) list is what the maintained clients and this website show. Registration is verified: the site sends an A2S query to the address your request comes from, checks it is a real Ace of Spades protocol-168 server, and only then lists it and returns a one-time server token.
- 01Make it reachable
Finish the firewall and port-forwarding steps; the server must be running.
- 02Register from the server machine
Run
deploy/register_server.pyon the host itself (the site uses the IP it sees, not one you type). - 03Store the token
The script prints
AOS_MASTER_WRITE_TOKEN=aos_srv_…once. Save it like a password; it only works for that address and port. - 04Configure the server
Set
[revival] public_hostto your public IPv4 and keepenabled = true. - 05Start with the token
Provide
AOS_MASTER_WRITE_TOKENas an environment variable (never inconfig.toml). The server then sends heartbeats and appears in the list within seconds.
python deploy/register_server.py --port 27015 \
--name "My AoS Server" --map CastleWars --mode CTF \
--max-players 24 --region europe
# identifier=203.0.113.10:27015
# status=active
# verified=true
# AOS_MASTER_WRITE_TOKEN=aos_srv_...
# Store this token now; the API will not return it again.[revival]
enabled = true
base_url = "https://www.aosplay.net"
public_host = "203.0.113.10" # your public IPv4 or DNS name
region = "europe"
require_identity = false$env:AOS_MASTER_WRITE_TOKEN = "aos_srv_..."
.\BattleSpades.exeAOS_MASTER_WRITE_TOKEN=aos_srv_... ./BattleSpades
# systemd unit: add under [Service]
# Environment=AOS_MASTER_WRITE_TOKEN=aos_srv_...If the verification probe timed out, the registration stays pending and nothing is listed. Fix the port, then ask for verification again with the same token:
curl -X PATCH https://www.aosplay.net/api/master/servers/register \
-H "Authorization: Bearer aos_srv_..." \
-H "Content-Type: application/json" \
-d '{"port":27015}'Identity, ranked stats and relays
- Players with a Revival account or a validated Steam copy get a one-time join ticket; the server checks it with your token.
require_identity = truerefuses players without one. - Round results are queued in
state/round-results.sqlite3and uploaded at round end; keep that file across upgrades. - A new registration is a community listing. Statistics from it count for ranked leaderboards only after an AoSPlay administrator marks the server as trusted (
stats_trusted). Ask on Discord once your server is stable. - Behind a relay or a router that maps a different external port, keep
[server] portas the local port and setAOS_PUBLIC_HOST,AOS_PUBLIC_PORT(andAOS_PUBLIC_QUERY_PORTif it differs).[revival] server_idmust then equalpublic_host:public_port. - Without a token the server logs
AoS Revival master disabled: AOS_MASTER_WRITE_TOKEN is not setand simply stays unlisted; direct connections keep working.
Optional: the retail Steam browser
BattleSpades can also register with Valve's master server so the original in-game Steam browser can find it. This is optional and more fragile than AoSPlay listing: it needs Valve's proprietary 32-bit runtime (never bundled), extra ports, and Valve retired the legacy list endpoint the unmodified 2015 browser used, so a healthy registration does not guarantee that the old browser shows the row.
- 01Runtime
On Windows, put the original signed x86
steam_api.dllin thesteam-runtimefolder next to the server. Desktop Steam provides the rest automatically. - 02Config
Enable
[steam]as shown below. The game,steam_portand query ports must all differ. - 03Ports
Forward UDP for the game port,
steam_port(8766) and the query port (game + 1). - 04Retail joins
The unmodified browser always joins UDP 32887, so use
[server] port = 32887if joining from those rows matters. - 05Verify
Startup logs
Steam GameServer011 initialized, thenSteam master logon complete. From another network runscripts/check_steam_registration.py.
[steam]
enabled = true
runtime_dir = "steam-runtime"
steamclient_dir = "" # auto-discover desktop Steam
steam_port = 8766
query_port = 0 # game port + 1
public = true
secure = false
require_registration = falsepy scripts\check_steam_registration.py 203.0.113.10 `
--game-port 27015 --query-port 27016Headless Linux hosts use a separate sidecar instead of the Windows helper; the systemd templates and instructions are in deploy/steam-linux/ of the BattleSpades repository. The Docker image always disables Steam listing. Each server joinable from retail Steam rows needs its own public IPv4, because those rows always use port 32887.
Common questions
Do I need to open TCP ports?+
No. The game, A2S queries and Steam registration are all UDP. AoSPlay heartbeats are ordinary outbound HTTPS.
My server runs but nobody can join from outside.+
Test in order: 127.0.0.1 on the host, then the LAN address from another device (OS firewall), then from another internet connection (router/cloud firewall). If only the last fails, check the forwarding rule and whether you are behind CGNAT.
Can I change the port later?+
Yes, but update the firewall, the router forward and your AoSPlay registration (the token is bound to address and port, so register the new port).
Is Steam listing required for Steam players?+
No. A Steam copy is validated through the normal protocol-168/Revival identity path, not through the Steam browser. Players using the maintained clients find servers in the AoSPlay list.

