Factorio is the easiest dedicated server on this whole blog. No SteamCMD, no anti-cheat, no 12 GB download. The official headless build is a single tarball you grab straight from factorio.com, and a fresh world idles under 1 GB. It only gets hungry once someone builds a megabase.
TL;DR:
# grab the official headless build (no Steam account needed)
adduser --disabled-password --gecos "" factorio && sudo -iu factorio
curl -L https://factorio.com/get-download/stable/headless/linux64 -o factorio.tar.xz
tar -xJf factorio.tar.xz # extracts to ./factorio/
cd factorio
./bin/x64/factorio --create saves/myworld.zip
cp data/server-settings.example.json server-settings.json # edit it
./bin/x64/factorio --start-server saves/myworld.zip \
--server-settings server-settings.json
Details below.
Get the headless build
There's no Steam dependency — the headless server is a free, separate download. Do it as an unprivileged user:
apt update && apt install -y xz-utils curl
adduser --disabled-password --gecos "" factorio
sudo -iu factorio
curl -L https://factorio.com/get-download/stable/headless/linux64 -o factorio.tar.xz
tar -xJf factorio.tar.xz
cd factorio
That stable URL always points at the current stable release. To pin a version, swap stable for the exact number, e.g. .../1.1.110/headless/linux64. The headless build is self-contained — it doesn't need the graphical game installed.
Create a world
The server needs a save to host. Generate one (with default map settings) before first launch:
./bin/x64/factorio --create saves/myworld.zip
Want custom map gen — ore richness, water, cliffs? Write a map-gen-settings.json (there's an example in data/) and pass --map-gen-settings. For an existing single-player save, just copy its .zip into saves/ and host that.
server-settings.json
Copy the example and edit it. This is where the name, description, visibility and admin list live:
cp data/server-settings.example.json server-settings.json
The fields that matter:
{
"name": "Diengdoh Factorio",
"description": "Friendly EU co-op. Stable channel.",
"max_players": 0,
"visibility": { "public": true, "lan": true },
"username": "",
"token": "",
"game_password": "changeme",
"require_user_verification": true,
"autosave_interval": 10,
"autosave_slots": 5,
"admins": ["YourFactorioName"]
}
- public: true lists you on the official matchmaking server browser. That requires a real factorio.com account — put your username and a server token (from your factorio.com profile, not your password) in
username/token. No account or don't care about the public list? Setpublic: falseand players join by direct IP. - max_players: 0 means unlimited.
- autosave_interval is minutes. Factorio autosaves are cheap and have saved me more than once — keep it tight.
- admins are matched by in-game username and can run
/promote,/banetc. without RCON.
Run it and open the port
./bin/x64/factorio --start-server saves/myworld.zip \
--server-settings server-settings.json
Factorio needs exactly one UDP port, 34197:
ufw allow 34197/udp
That's it. No TCP for the game itself. Firewall basics: /ufw-firewall-rules-ubuntu/.
RCON for remote console
Want to run commands without being in-game? Add RCON on a TCP port:
./bin/x64/factorio --start-server saves/myworld.zip \
--server-settings server-settings.json \
--rcon-port 27015 --rcon-password "use-a-real-one"
ufw allow from 203.0.113.10 to any port 27015 proto tcp # your IP only
Same rule as always — never expose RCON to the open internet.
Mods
Mods are just zip files. Drop them into the mods/ folder next to the save dir and the server loads them on start:
mkdir -p mods
# copy each Mod_1.2.3.zip into mods/
Every connecting client must have the same mods at the same versions or they're rejected at the door — that's the number one "my friend can't join" cause. To pull mods server-side automatically you can add your factorio.com username/token and let it sync, but I prefer dropping the exact zips in manually so versions are pinned. Factorio writes a mods/mod-list.json you can edit to enable/disable without deleting files.
systemd unit
# /etc/systemd/system/factorio.service
[Unit]
Description=Factorio Headless Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=factorio
WorkingDirectory=/home/factorio/factorio
ExecStart=/home/factorio/factorio/bin/x64/factorio \
--start-server /home/factorio/factorio/saves/myworld.zip \
--server-settings /home/factorio/factorio/server-settings.json
Restart=on-failure
RestartSec=10
# graceful: let it finish writing the autosave on stop
KillSignal=SIGINT
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now factorio
journalctl -u factorio -f
SIGINT gives the server a chance to save before exit instead of dropping the last few minutes of progress. More on units in /systemd-service-unit-file/.
Gotchas
- Mod version mismatch. Clients are rejected unless their mods match exactly. Pin versions; don't let half your players auto-update.
- public: true with no token. If you set public but leave
username/tokenempty, the server logs an auth error and never shows in the browser. Either fill them in or gopublic: false. - Megabase RAM. A fresh map is tiny; a thousand-hour factory with bots everywhere can hit several GB and chew CPU on UPS (updates per second). If your server tanks to 30 UPS, that's the factory, not the network.
- Updating. There's no in-place updater for headless — you download the new tarball and extract over the install (saves and mods live in their own dirs, so they survive). Stop the service first.
- Wrong working dir. Launch from the install root or it won't find
data/. The systemdWorkingDirectoryhandles that.
Verify
# port bound?
ss -tulpn | grep 34197
# hosting and ready?
journalctl -u factorio --no-pager | grep -i "Hosting game"
# watch joins
journalctl -u factorio -f | grep -i "joined the game"
In game: Multiplayer → Connect to address → <your-ip>:34197, enter the password. If the public list is on and your token's valid, it'll also show in the browser within a minute.
Lighter than the SteamCMD beasts on this blog — if you want the heavier survival kind next, see Enshrouded or 7 Days to Die.