Factorio is a factory-building game with cooperative multiplayer, and Wube Software publishes a free headless build of the game for running dedicated servers. The headless server has no graphics, uses little memory for small and medium factories, and keeps your map running when nobody is hosting from their PC.
In this tutorial you will install the Factorio headless server on Ubuntu 24.04, create a map, configure the server name, password and admins, run it as a systemd service under its own user, add mods and set up backups.
Prerequisites
To follow this tutorial, you will need:
- A server running Ubuntu 24.04, for example a CubePath VPS. Factorio's simulation runs mostly on one core, so fast single-core performance matters more than core count. 2 vCPUs and 2 GB of RAM are enough for a new map; large late-game factories can need 4 GB or more.
- A non-root user with
sudoprivileges and UFW enabled. - A copy of Factorio for each player. To list the server publicly you also need a factorio.com account.
Step 1 - Creating a dedicated user
Run the server under its own unprivileged user. Create a system account whose home directory is /opt/factorio, where the server will live:
sudo adduser --system --group --home /opt/factorio factorio
Confirm it exists:
id factorio
uid=999(factorio) gid=988(factorio) groups=988(factorio)
Step 2 - Downloading the headless server
Wube provides a stable download link that always points to the latest stable headless release. Download it to a temporary file:
curl -fL -o /tmp/factorio_headless.tar.xz https://factorio.com/get-download/stable/headless/linux64
The archive contains a top-level factorio/ directory. Extract it into /opt, so the files land in /opt/factorio, and give ownership to the factorio user:
sudo tar -xJf /tmp/factorio_headless.tar.xz -C /opt
sudo chown -R factorio:factorio /opt/factorio
rm /tmp/factorio_headless.tar.xz
Check the installed version:
sudo -u factorio /opt/factorio/bin/x64/factorio --version
Version: 2.0.x (build ..., linux64, headless)
...
Step 3 - Creating a map
The server needs a save file to load. Create a new map with default settings in the saves directory:
sudo -u factorio mkdir -p /opt/factorio/saves
sudo -u factorio /opt/factorio/bin/x64/factorio --create /opt/factorio/saves/world.zip
The command generates the map and exits. Confirm the save exists:
ls -lh /opt/factorio/saves/
To customize the map (resources, enemies, seed), copy data/map-gen-settings.example.json to map-gen-settings.json, edit it, and pass it when creating the map with --map-gen-settings /opt/factorio/map-gen-settings.json. You can also upload a save you started in single player: copy its .zip file from your PC's Factorio saves folder into /opt/factorio/saves/ and change its owner to factorio.
Step 4 - Configuring the server
Server options live in a JSON file. Start from the example Factorio ships:
sudo -u factorio cp /opt/factorio/data/server-settings.example.json /opt/factorio/server-settings.json
sudo -u factorio nano /opt/factorio/server-settings.json
Change at least these keys and leave the rest as they are:
{
"name": "Your Server Name",
"description": "Your server description",
"max_players": 0,
"visibility": {
"public": false,
"lan": false
},
"username": "",
"token": "",
"game_password": "your_server_password",
"require_user_verification": true,
"autosave_interval": 10,
"autosave_slots": 5,
"auto_pause": true
}
max_playersset to0means no limit.visibility.publiclists the server in the public server browser. It requires your factorio.comusernameandtoken, which you find on your profile page at factorio.com. Withfalse, players join by IP address.require_user_verificationchecks that every player owns the game through a factorio.com account.autosave_intervalis in minutes, andautosave_slotsis the number of rotating autosave files.auto_pausepauses the game while no players are connected.
Check that the file is still valid JSON after editing:
python3 -m json.tool /opt/factorio/server-settings.json > /dev/null && echo OK
OK
Next, create the admin list. Admins can kick, ban and run server commands. The file is a JSON array of factorio.com user names:
sudo -u factorio nano /opt/factorio/server-adminlist.json
["your_factorio_username"]
Step 5 - Opening the firewall port
Factorio uses a single UDP port, 34197 by default:
sudo ufw allow 34197/udp
sudo ufw status
Step 6 - Creating the systemd service
A systemd unit starts the server on boot, restarts it after a crash and stops it cleanly. Create the unit file:
sudo nano /etc/systemd/system/factorio.service
Paste the following:
[Unit]
Description=Factorio headless server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=factorio
Group=factorio
WorkingDirectory=/opt/factorio
ExecStart=/opt/factorio/bin/x64/factorio \
--start-server-load-latest \
--server-settings /opt/factorio/server-settings.json \
--server-adminlist /opt/factorio/server-adminlist.json \
--port 34197
KillSignal=SIGINT
Restart=on-failure
RestartSec=10
TimeoutStopSec=60
[Install]
WantedBy=multi-user.target
--start-server-load-latest loads the most recent save in saves/, including autosaves, so the server always resumes from the newest state. KillSignal=SIGINT makes systemctl stop behave like pressing Ctrl+c in the console, which saves the map before the server exits.
Reload systemd and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now factorio
sudo systemctl status factorio
Follow the log until the server is ready:
sudo journalctl -u factorio -f
... Info ServerMultiplayerManager.cpp: ... changing state from(CreatingGame) to(InGame)
Press Ctrl+c to stop following the log. Check the port:
sudo ss -ulnp | grep 34197
To join, open Factorio, go to Multiplayer > Connect to address, enter your_server_ip (add :34197 only if you changed the port) and the game password.
Step 7 - Administering the server
Admins listed in server-adminlist.json can run commands from the in-game chat console, opened with the ~ key. Useful commands:
| Command | What it does |
|---|---|
/players online | List connected players |
/kick player reason | Kick a player |
/ban player reason | Ban a player |
/promote player | Make a player an admin |
/server-save | Save the game immediately |
/whitelist add player | Add a player to the whitelist |
The whitelist only takes effect when you add --use-server-whitelist to the ExecStart line; with it, only listed players can join.
Step 8 - Installing mods
Every player must run exactly the same mods and versions as the server. The easiest way to get a matching set is to enable the mods in your own game, then copy them to the server.
On your PC, the mods are .zip files in the Factorio mods folder (%APPDATA%\Factorio\mods on Windows, ~/.factorio/mods on Linux). Copy the zip files and mod-list.json to the server, for example with scp:
scp ~/.factorio/mods/*.zip ~/.factorio/mods/mod-list.json your_user@your_server_ip:/tmp/
On the server, move them into place and restart:
sudo mkdir -p /opt/factorio/mods
sudo mv /tmp/*.zip /tmp/mod-list.json /opt/factorio/mods/
sudo chown -R factorio:factorio /opt/factorio/mods
sudo systemctl restart factorio
The log lists each mod as it loads:
sudo journalctl -u factorio -n 100 | grep -i "Loading mod"
Players who connect without the right mods are offered to download them automatically when they join.
Step 9 - Backing up saves
The server writes regular autosaves, but they sit on the same disk as the server. A daily archive of the saves directory, kept for a week, protects you from a corrupted save or a bad mod update. Create a backup directory and open the factorio user's crontab:
sudo -u factorio mkdir -p /opt/factorio/backups
sudo -u factorio crontab -e
Add these lines:
0 5 * * * tar -czf /opt/factorio/backups/saves-$(date +\%F).tar.gz -C /opt/factorio saves server-settings.json server-adminlist.json
30 5 * * * find /opt/factorio/backups -name 'saves-*.tar.gz' -mtime +7 -delete
The % is escaped because cron treats a bare % as a newline. To restore, stop the service, copy the .zip save you want from the archive into /opt/factorio/saves/, make it the most recently modified file (for example with touch), and start the service.
Updating the server
Players need the same game version as the server. To update, stop the service, download the new release and extract it over the existing installation. The archive only contains program files, so your saves, mods and configuration are kept:
sudo systemctl stop factorio
curl -fL -o /tmp/factorio_headless.tar.xz https://factorio.com/get-download/stable/headless/linux64
sudo tar -xJf /tmp/factorio_headless.tar.xz -C /opt
sudo chown -R factorio:factorio /opt/factorio
rm /tmp/factorio_headless.tar.xz
sudo systemctl start factorio
Update your mods to versions compatible with the new release before starting the server, otherwise it refuses to load them.
Troubleshooting
The service fails with an error about server-settings.json. The file is not valid JSON, usually because of a missing or extra comma. Run the python3 -m json.tool check from Step 4, which prints the line with the error.
Players see "Mod mismatch" or cannot load the map. The mods or versions on the server differ from the client. Copy the exact mod files again as in Step 8.
The game runs slowly (UPS drops) on a big factory. Check CPU usage with top. Factorio's game loop is mostly single threaded, so a faster CPU helps more than more cores.
Players cannot connect. Check that UFW allows 34197/udp and that the server reached the InGame state in the log.
Conclusion
You now have a Factorio headless server on Ubuntu 24.04, running as a systemd service under its own user, with a password, admins, mods and daily backups.
As next steps, you can list the server publicly by adding your factorio.com token, enable the whitelist for a private group, and copy your backups off the server to object storage.
