A server appearing in the list is not the same as a completed connection. Diagnose four separate stages: finding the endpoint, exchanging game packets, admitting the player and loading the factory. The stage that fails determines the next check.
This guide assumes an existing Factorio 2.x headless server directly on Ubuntu 24.04, with the binary in /opt/factorio, runtime data in /srv/factorio and factorio.service from the installation guide. It targets matching PC clients. Keep your current factory and expansion choice; creating a new save is not a connection repair. Run commands on the server unless stated otherwise, and substitute your actual paths and port.
Identify the last successful stage#
Record the client's complete error, version, selected address and attempt time. Ask whether another player can join the same world now.
| Observation | Investigation |
|---|---|
| Server absent from public list | Listing settings and registration logs; also try an explicit address |
| Direct join receives no response | UDP socket, endpoint, filters and route |
| Password, identity, version or mod rejection | Admission and compatibility; preserve the exact message |
| Map starts downloading but stalls | Transfer path, server/client logs, disk and upload conditions |
| Joined factory runs slowly | Simulation/performance investigation, after connection checks |
Inspect the instance actually running#
sudo systemctl status factorio --no-pager
sudo systemctl cat factorio
/opt/factorio/bin/x64/factorio --version
sudo journalctl -u factorio -n 100 --no-pager
sudo ss -lunp 'sport = :34197'
Compare the binary in ExecStart with the one whose version you printed. Check the log for the loaded save and errors; an active service can still be loading a large factory. Use the process shown by ss to distinguish this instance from another server using the expected port.
The Factorio command reference documents --port, --bind and settings-file selection. Read the effective unit, including its drop-ins. A listener bound only to loopback cannot serve remote players; an explicit private address must belong to this machine. 0.0.0.0 is a binding address, not an address to give friends. If --bind includes a port, reconcile it with the socket you actually observe instead of guessing which setting took effect.
For the existing data layout, inspect recent runtime output:
sudo tail -n 100 /srv/factorio/factorio-current.log
If that file is missing, first check the actual write-data configuration and service journal. Do not create a replacement directory and launch a second server just to obtain a log.
Test an explicit address before fixing discovery#
In the client's Multiplayer menu, use Connect to address with the public VPS IPv4 and actual port, such as PUBLIC_IP:34197. Do not include http://. Compare this with a hostname attempt; an IP-only success directs attention to DNS or an SRV endpoint, not the factory ZIP.
Factorio's multiplayer reference separates public listing, LAN visibility and direct joining, and specifies UDP 34197 as the default game port. An intentionally hidden server can accept a direct connection. Conversely, a listed server can still have a blocked path. Keep a private server private while diagnosing it.
For a home-hosted instance, use its LAN address from inside that LAN and compare with an external-network attempt. External success with local failure needs local routing/WiFi investigation; it does not establish that every such failure is NAT loopback. A VPS with a public address does not require forwarding a port on a joining player's home router.
Check UDP through both filters#
Inspect Ubuntu's rules before editing:
sudo ufw status verbose
sudo ufw status numbered
When UFW is active, add a missing UDP permission only after checking applicable earlier deny rules:
sudo ufw allow 34197/udp
sudo ufw status numbered
Ubuntu's firewall documentation covers rule inspection. A TCP permission on the same number is different. Also inspect the provider's firewall for this VPS: UDP, actual destination port and intended source addresses. If UFW is inactive, locate the actual filtering system rather than toggling it blindly. Preserve SSH and other application access before separately enabling any firewall.
A web-based TCP port checker and PowerShell Test-NetConnection -Port cannot validate Factorio's UDP exchange. UDP has no TCP-style connection handshake, and an arbitrary probe may receive no response from a healthy game socket. Use a real Factorio client alongside a short server capture.
sudo apt update
sudo apt install -y tcpdump
sudo tcpdump -ni any 'udp port 34197' -c 30
Ask the affected player to try joining. Stop with Ctrl+C if necessary: the packet count is not a timeout. The tcpdump manual documents the options; the command prints summaries without writing a payload file.
Match traffic to the attempt time and the player's public address. No corresponding datagrams sends you upstream toward the endpoint, provider rules or client route. Incoming traffic without a visible response calls for guest filtering, binding and application-log checks. Exchange in both directions narrows the search but does not prove map loading or gameplay. If only one network fails, compare a hotspot attempt and retain both results before changing global server settings.
Keep credentials and admission separate#
Read /srv/factorio/server-settings.json locally without posting it publicly. Wube's template separates three things: game_password admits players; password or token authenticates the server account for public listing; require_user_verification checks player identity. The installed release's own example file is the right template when fields differ.
For a wrong game password, share the intended password privately. Do not put it in shell command arguments or support screenshots. For identity failures, verify the player's legitimate Factorio account/login and read the corresponding error; setting verification to false changes access policy rather than repairing connectivity.
If the launch uses a whitelist or banlist, inspect the selected file and exact player name. Administrative status and admission are distinct. A server-full response also needs an access/capacity decision, not another firewall rule.
Before editing settings, stop the service normally and retain a private copy. Validate the existing JSON, then start and inspect fresh output:
sudo -u factorio python3 -m json.tool /srv/factorio/server-settings.json >/dev/null && \
sudo systemctl start factorio
sudo journalctl -u factorio -n 60 --no-pager
Run this after your stopped edit. If JSON validation fails, leave the service stopped and repair the file before another start.
Match versions before investigating map transfer#
Compare full client and server release numbers, not just “2.x” or “stable”. Read the mod mismatch offered by the game, including enabled versions and dependencies. For Space Age, all participants need the expansion. A base-game factory and an expansion factory are different choices; removing expansion components from an existing save is not a safe shortcut.
Use the mods and saves guide for controlled changes. Preserve the last working binary, mod set and save together before updating. Do not overwrite a working factory simply because one client is on a newer branch.
When admission succeeds but transfer stalls, compare both logs around that moment. On the server:
df -h /srv/factorio
df -i /srv/factorio
Check actual write failures, competing transfers and configured upload limits; do not raise unrelated simulation settings to fix a download. A firewall allowing small exchanges does not establish that every packet on the path survives. If a direct LAN attempt works but an external transfer fails, that comparison is useful evidence for a network investigation.
For several supported instances on your infrastructure, Nexardo's panel for your own VPS can organise administration. Machine enrollment and managed-instance creation are separate from adopting this manual server.
Finish by joining the intended factory, completing the download and performing an ordinary action. For an unresolved case, collect endpoint, full versions, enabled mod set, attempt time, relevant client/server errors and capture observations. Redact account tokens, passwords and private player data before sharing the record.




