Factorio Field guide

Factorio Headless Server on Ubuntu: systemd Automation, Non-Root User & Saves

Factorio headless server setup on Ubuntu: non-root system daemon, world creation, UDP 34197 firewalling, and systemd unit configuration with SIGINT graceful save handling.

Factorio Headless Server on Ubuntu: systemd Automation, Non-Root User & Saves

Running a dedicated headless Factorio server on Linux Ubuntu provides maximum computing throughput for massive megabases. Unlike hosting multiplayer sessions through a standard desktop Steam graphical interface, the headless server binary operates without rendering graphics pipelines, optimizing every available CPU tick cycle for deterministic factory state updates.

This guide walks through deploying the official Factorio headless package on Ubuntu 22.04/24.04, generating a fresh multi-surface game world, configuring UDP firewall rules, and authoring an isolated systemd service unit with graceful termination handling.

Non-Root User Creation and Package Extraction#

Server hardening best practices require network-facing daemons to run under unprivileged system identities. Create a dedicated factorio user without interactive login capabilities and configure /opt/factorio as the home directory:

bash
sudo useradd -r -m -d /opt/factorio -s /usr/sbin/nologin factorio && sudo apt update && sudo apt install -y curl tar xz-utils

Download the latest stable Factorio headless tarball directly from Wube Software and extract it into the installation path:

bash
cd /tmp && curl -L https://www.factorio.com/get-download/stable/headless/linux64 -o factorio_headless.tar.xz && sudo tar -xf factorio_headless.tar.xz -C /opt/ && sudo chown -R factorio:factorio /opt/factorio

Initializing World Generation and Configuration#

Before starting the server daemon, initialize a fresh save archive where your industrial facility will reside:

bash
sudo -u factorio /opt/factorio/bin/x64/factorio --create /opt/factorio/saves/my-world.zip

The engine creates /opt/factorio/saves/my-world.zip. Next, duplicate the configuration template from data/server-settings.example.json into config/server-settings.json, where you can define the server title, admin token authentication, and the autosave_interval.

Network Firewall and UDP Port Forwarding#

Factorio communicates via a proprietary state-synchronization protocol built strictly on top of UDP. The canonical listening port is 34197. Allow this inbound traffic through Ubuntu's UFW:

bash
sudo ufw allow 34197/udp

If you prefer operating persistent Factorio multiplayer servers alongside the Space Age expansion without navigating terminal commands, specialized Factorio server hosting offers one-click Mod Portal synchronization, automatic save rotations, and live web consoles.

Authoring the systemd Unit with Graceful Stop Logic#

A critical aspect of hosting Factorio under systemd is proper shutdown signaling. Sending a forced SIGKILL causes immediate data loss for unwritten factory progress. Sending SIGINT (equivalent to pressing Ctrl+C in an interactive terminal) instructs the engine to cleanly write all active chunk states to the zip archive before shutting down.

Author the service definition at /etc/systemd/system/factorio.service:

ini
[Unit]
Description=Factorio Headless Dedicated Server
After=network.target

[Service]
Type=simple
User=factorio
Group=factorio
WorkingDirectory=/opt/factorio
ExecStart=/opt/factorio/bin/x64/factorio --start-server /opt/factorio/saves/my-world.zip --server-settings /opt/factorio/config/server-settings.json
ExecStop=/bin/kill -s INT $MAINPID
Restart=on-failure
RestartSec=15s
TimeoutStopSec=45

[Install]
WantedBy=multi-user.target

Notify systemd of the new unit, enable the daemon on host startup, and initialize the service:

bash
sudo systemctl daemon-reload && sudo systemctl enable --now factorio && sudo systemctl status factorio

Your automated factory now executes in the background. Real-time game events, player connections, and desync reports can be observed using journalctl -u factorio -f.

Sources#