> ## Content Index
> Fetch the complete content index at: https://blog.sudowl.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Factorio Headless Server on Linux
- URL: https://blog.sudowl.com/factorio-headless-server-linux/
- Published: 2026-06-17T10:00:00.000Z
- Updated: 2026-10-11T08:26:51.000Z
- Description: Set up a Factorio headless dedicated server on Ubuntu/Debian — download the official tarball, server-settings.json, port 34197 UDP, mods, RCON and a systemd unit.
- Author: Lukas
- Tags: Gameserver, Linux

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:**

```bash
# 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:

```bash
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:

```bash
./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:

```bash
cp data/server-settings.example.json server-settings.json

```

The fields that matter:

```json
{
  "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? Set `public: false` and 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`, `/ban` etc. without RCON.

## Run it and open the port

```bash
./bin/x64/factorio --start-server saves/myworld.zip \
  --server-settings server-settings.json

```

Factorio needs exactly **one UDP port, 34197**:

```bash
ufw allow 34197/udp

```

That's it. No TCP for the game itself. Firewall basics: [/ufw-firewall-rules-ubuntu/](https://blog.sudowl.com/ufw-firewall-rules-ubuntu/).

## RCON for remote console

Want to run commands without being in-game? Add RCON on a TCP port:

```bash
./bin/x64/factorio --start-server saves/myworld.zip \
  --server-settings server-settings.json \
  --rcon-port 27015 --rcon-password "use-a-real-one"

```

```bash
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:

```bash
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

```ini
# /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

```

```bash
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/](https://blog.sudowl.com/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`/`token` empty, the server logs an auth error and never shows in the browser. Either fill them in or go `public: 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 systemd `WorkingDirectory` handles that.

## Verify

```bash
# 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](https://blog.sudowl.com/enshrouded-dedicated-server-linux/) or [7 Days to Die](https://blog.sudowl.com/7-days-to-die-dedicated-server-linux/).

---

### Related posts

- [Rust Dedicated Server on Linux](https://blog.diengdoh.com/rust-dedicated-server-linux/?ref=blog.sudowl.com)
- [7 Days to Die Dedicated Server on Linux](https://blog.diengdoh.com/7-days-to-die-dedicated-server-linux/?ref=blog.sudowl.com)
- [Project Zomboid Dedicated Server on Linux](https://blog.diengdoh.com/project-zomboid-dedicated-server-linux/?ref=blog.sudowl.com)