VPS Tutorials
Set Up a Satisfactory Dedicated Server on a VPS (2026): SteamCMD, New Ports, Backups and Auto-Updates
Set up a Satisfactory dedicated server on an Ubuntu 24.04 x86_64 VPS with SteamCMD, covering App ID 1690800, the new ports, Server Manager claiming, systemd, backup and restore, and auto-updates.

If you want to play Satisfactory with friends long-term, hosting a temporary session on one player's PC runs into a very real problem: when the host goes offline, the factory stops; when the host changes computers, the save has to be moved; updates, backups and admin passwords all pile up on a personal computer. Once you deploy a dedicated server to a VPS, the world can run around the clock, players can log in and build at any time, and admins can schedule maintenance windows, backups and upgrades independently.
This article uses an Ubuntu 24.04 x86_64 VPS as an example, using the official native Linux server, SteamCMD and systemd, and walks through installation, claiming the server, opening the new ports, backups, restore and auto-updates in full. First, a reminder of the change most likely to trip up anyone copying an old tutorial: since Satisfactory 1.0, the old 15000/UDP and 15777/UDP are no longer used; the current defaults require 7777/TCP, 7777/UDP and 8888/TCP.
The Satisfactory official community Wiki dedicated server documentation lists the server Steam App ID as 1690800. It supports native 64-bit Windows and Linux, but only x86-64, not ARM.
As of August 2026, the official Wiki's current version template shows the default branch as 1.2.3.1. This article does not put the patch number into the install command, because SteamCMD downloads the current stable version from the default branch; the command will still work for future minor updates.
| Item | Value used in this article |
|---|---|
| SteamCMD App ID | 1690800 |
| OS | Ubuntu 24.04 LTS x86_64 |
| Server program | FactoryServer.sh |
| Game and query | 7777/UDP |
| HTTPS API | 7777/TCP |
| Reliable messaging | 8888/TCP |
Before buying a VPS, confirm the architecture in the console:
uname -m
lscpu | grep -E 'Architecture|Model name|Virtualization'
uname -m should output x86_64. If it is aarch64 or arm64, even if the system can install SteamCMD, it cannot run the official server directly. The official documentation also specifically notes that the generic kvm64 CPU model exposed by some KVM VPSs can prevent the server from starting; in that case, ask the provider to switch to host-passthrough or a newer x86-64 CPU model, or simply switch to an instance that supports modern instruction sets, rather than repeatedly reinstalling the OS.
Satisfactory factory scale keeps growing, and conveyor belts, trains, drones and large numbers of buildings all add CPU and memory pressure. The official documentation gives a minimum of 8GB of memory and recommends 16GB for large saves or more than 4 players. When actually buying, you also need to leave headroom for Ubuntu, SteamCMD, file caching and maintenance operations.
| Use case | Recommended starting configuration | NVMe disk | Notes |
|---|---|---|---|
| 2–4 players, new save | 4 high-clock vCPUs, 8GB memory | 50GB | Can run the server, but watch memory before building large factories |
| 4–8 players, long-term save | 4–6 high-clock vCPUs, 16GB memory | 80GB | Better suited to long-term operation and online backups |
| 8+ players or very large factories | 6–8 high-clock vCPUs, 16–32GB memory | 100GB+ | Needs scaling based on monitoring data |
These are practical starting points, not guarantees of player count or performance. The Satisfactory server cares a lot about single-core performance, so don't just compare marketing numbers like "8 cores" or "16 cores." When shared CPU is heavily oversold, the machine's overall load may look low while the game still shows rubber-banding, building delays and autosave stutter.
The data center should be as close as possible to the main players, and you should confirm the provider allows game servers, supports UDP, has enough monthly traffic and has clear DDoS handling rules. If you haven't chosen a machine yet, you can first look at game server VPS configuration and network line selection.
First log in to the VPS via SSH, update the system and install dependencies:
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl ca-certificates tar lib32gcc-s1 lib32stdc++6 ufw
Don't run the game server as root long-term. Create a system user without admin privileges, and prepare the install and backup directories:
sudo adduser --system --group \
--home /home/satisfactory \
--shell /bin/bash satisfactory
sudo install -d -o satisfactory -g satisfactory /opt/steamcmd
sudo install -d -o satisfactory -g satisfactory /opt/satisfactory
sudo install -d -m 750 -o root -g satisfactory /var/backups/satisfactory
Check the directories and disk space:
id satisfactory
df -h /opt /home /var/backups
sudo -u satisfactory test -w /opt/satisfactory && echo 'install dir writable'
If /opt and /home are on the same small system disk, keeping backups on that disk won't protect you from the VPS being deleted or the disk failing. This article first creates a local recovery point, but later you should still sync critical backups to another machine or object storage.
Download the Linux version of SteamCMD from Valve's official CDN:
sudo -u satisfactory curl -fsSL \
https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz \
-o /opt/steamcmd/steamcmd_linux.tar.gz
sudo -u satisfactory tar -xzf \
/opt/steamcmd/steamcmd_linux.tar.gz \
-C /opt/steamcmd
sudo -u satisfactory /opt/steamcmd/steamcmd.sh +quit
The first run updates SteamCMD itself. After it finishes, confirm the script and directory ownership:
ls -l /opt/steamcmd/steamcmd.sh
sudo -u satisfactory test -x /opt/steamcmd/steamcmd.sh \
&& echo 'steamcmd ready'
Don't download packaged server files from forum attachments, cloud drives or unknown mirrors. SteamCMD can anonymously fetch the official dedicated server files directly, so there's no need to put a personal Steam account and password on the VPS.
Use App ID 1690800 to install the current default branch:
sudo -u satisfactory /opt/steamcmd/steamcmd.sh \
+force_install_dir /opt/satisfactory \
+login anonymous \
+app_update 1690800 validate \
+quit
After the download finishes, check the key files:
sudo -u satisfactory test -x /opt/satisfactory/FactoryServer.sh \
&& echo 'FactoryServer ready'
du -sh /opt/satisfactory
ls -l /opt/satisfactory/FactoryServer.sh
If SteamCMD reports insufficient disk space, don't just clear the download cache and force the install to continue. Saves, logs and future updates all need extra space; you should expand the disk first, and make sure inodes aren't exhausted either:
df -h
df -i
Before formally configuring systemd, start it once in the foreground so you can see errors directly:
sudo -u satisfactory env HOME=/home/satisfactory \
/opt/satisfactory/FactoryServer.sh \
-Port=7777 \
-ReliablePort=8888
The first start needs to generate the config directory and initialize the service, which may take a few minutes. Don't force-kill it just because the terminal temporarily shows no new output. In another SSH window, check the process and listening ports:
pgrep -af FactoryServer
sudo ss -lntup | grep -E ':7777|:8888'
curl -k https://127.0.0.1:7777
TCP and UDP for 7777, and TCP for 8888, should both appear. If curl returns no matching API route, an HTTP error or a JSON error, that isn't necessarily a fault; as long as the TLS connection completes and a server response is received, the local HTTPS API is listening.
Once you confirm the start succeeded, press Ctrl+C in the terminal running the server. The Linux version receives SIGINT and exits normally. The official documentation warns: a normal exit does not equal an autosave; before future maintenance, save in-game or in Server Manager first, then stop the server.
The current Satisfactory default ports are as follows:
| Port | Protocol | Purpose | Public inbound |
|---|---|---|---|
7777 | UDP | Game and query traffic | Required |
7777 | TCP | HTTPS API | Required |
8888 | TCP | Reliable messaging channel | Required |
First make sure the SSH rule exists, then enable UFW:
sudo ufw allow OpenSSH
sudo ufw allow 7777/udp comment 'Satisfactory game and query'
sudo ufw allow 7777/tcp comment 'Satisfactory HTTPS API'
sudo ufw allow 8888/tcp comment 'Satisfactory reliable messaging'
sudo ufw enable
sudo ufw status numbered
Then go to the VPS provider's console security group or cloud firewall and add exactly the same three inbound rules. The system UFW and the cloud security group are two layers of filtering; missing either layer can cause "the process is fine but the outside world can't connect." You can check layer by layer with the port, firewall and security group troubleshooting checklist.
Don't keep copying the pre-1.0 15000/UDP and 15777/UDP rules; they are no longer used. And don't open all TCP/UDP ports just to save effort.
If one VPS runs multiple Satisfactory instances, you can change the ports, for example:
/opt/satisfactory/FactoryServer.sh \
-Port=7778 \
-ReliablePort=8889
The public port of the standard Port must match the server's listening port; you can't just use ordinary NAT to forward external 7778 to internal 7777 at will. If you really need external mapping for the reliable messaging port, then use -ExternalReliablePort as described in the official documentation, and update the firewall accordingly.
After the server runs successfully for the first time, open the Satisfactory client and go to Server Manager from the main menu:
- Choose to add a server, and enter the VPS public IP and the default port
7777. - The first connection prompts you to claim the server; set the server name and admin password.
- The admin password should be random and unique; don't reuse your SSH, email or Steam password.
- Create a new game, or import an existing
.savsave. - In the server settings, confirm the autosave interval, save on disconnect and auto-load session.
- If you want a private server, also set a player connection password and share it only through private channels.
Server management settings are saved in a location like the following, where PORT is replaced by the port the instance actually uses:
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/ServerSettings.PORT.sav
The Linux server save directory is:
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server
When importing an old save, stop the server first, then copy the .sav file as the satisfactory user, to avoid root ownership preventing the game from reading it:
sudo systemctl stop satisfactory 2>/dev/null || true
sudo install -d -o satisfactory -g satisfactory \
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server
sudo cp /path/to/your-save.sav \
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server/
sudo chown satisfactory:satisfactory \
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server/your-save.sav
Replace /path/to/your-save.sav with the real file path. After starting, choose to load that save in Server Manager; don't directly edit the binary .sav or ServerSettings.PORT.sav.
After foreground start, ports and claiming are all confirmed working, create /etc/systemd/system/satisfactory.service:
[Unit]
Description=Satisfactory dedicated server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=satisfactory
Group=satisfactory
Environment=HOME=/home/satisfactory
WorkingDirectory=/opt/satisfactory
ExecStartPre=/opt/steamcmd/steamcmd.sh +force_install_dir /opt/satisfactory +login anonymous +app_update 1690800 validate +quit
ExecStart=/opt/satisfactory/FactoryServer.sh -Port=7777 -ReliablePort=8888
Restart=on-failure
RestartSec=60
KillSignal=SIGINT
TimeoutStopSec=180
[Install]
WantedBy=multi-user.target
This configuration references the official Wiki's guide to running as a systemd service, and explicitly sets HOME to ensure saves land in the expected service user directory.
Reload systemd and start:
sudo systemctl daemon-reload
sudo systemctl enable --now satisfactory
sudo systemctl status satisfactory --no-pager
sudo journalctl -u satisfactory -n 100 --no-pager
ExecStartPre runs SteamCMD before each service start, so restarting the service checks for updates first. This is convenient for maintenance, but if the service repeatedly crashes due to an error, the update check will also run again before each restart. Don't change RestartSec to a few seconds, and don't use an infinite fast loop to mask a real fault.
View live logs:
sudo journalctl -u satisfactory -f
The game's own logs are usually located at:
/opt/satisfactory/FactoryGame/Saved/Logs
If systemd shows active (running) but players still can't join, first check the logs to see whether world loading completed, then check whether all three ports are listening at the same time. Don't judge that the game world is connectable based only on process status.
Don't run app_update directly while the server process is running. The 0x606 update error listed in the official documentation is commonly caused by a running FactoryServer holding the files to be replaced.
The safe update process is:
- Save manually in Server Manager or in-game, for example as
before-update. - Notify players to log off and wait for the save to complete.
- Stop the service.
- Run the SteamCMD update and validate.
- Restart and check the logs and version.
The commands are as follows:
sudo systemctl stop satisfactory
sudo -u satisfactory env HOME=/home/satisfactory \
/opt/steamcmd/steamcmd.sh \
+force_install_dir /opt/satisfactory \
+login anonymous \
+app_update 1690800 validate \
+quit
sudo systemctl start satisfactory
sudo journalctl -u satisfactory -n 100 --no-pager
Since the systemd unit in this article already includes ExecStartPre, after manually running SteamCMD, systemctl start will check once more, which usually completes quickly. Alternatively, after saving, you can directly sudo systemctl restart satisfactory and let systemd update automatically after stopping the service.
Before a major version update, don't rely on just one local backup. First check the official patch notes and known community issues, keep a rollback-capable copy of the save, and then schedule a maintenance window.
The core directory to back up is not the install directory, but Saved under the service user's HOME:
sudo -u satisfactory find \
/home/satisfactory/.config/Epic/FactoryGame/Saved \
-maxdepth 3 -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' \
| tail -n 30
Before maintenance, save in-game first, then stop the server and create a timestamped archive:
sudo systemctl stop satisfactory
backup_stamp=$(date +%Y%m%d-%H%M%S)
sudo tar \
-C /home/satisfactory/.config/Epic/FactoryGame \
-czf "/var/backups/satisfactory/satisfactory-${backup_stamp}.tar.gz" \
Saved
sudo systemctl start satisfactory
sudo ls -lh /var/backups/satisfactory
Spot-check that the archive can be read:
latest_backup=$(sudo find /var/backups/satisfactory \
-maxdepth 1 -type f -name 'satisfactory-*.tar.gz' \
-print | sort | tail -n 1)
sudo tar -tzf "$latest_backup" | head -n 30
It's recommended to keep at least "the last 7 daily backups and the last 4 weekly backups," and sync copies to a failure domain different from the VPS. For backup scripts, object storage and restore drills, see the VPS backup strategy guide.
Restoring replaces the current Saved, so take another on-site snapshot first:
sudo systemctl stop satisfactory
restore_stamp=$(date +%Y%m%d-%H%M%S)
sudo mv \
/home/satisfactory/.config/Epic/FactoryGame/Saved \
"/home/satisfactory/.config/Epic/FactoryGame/Saved.before-restore-${restore_stamp}"
sudo -u satisfactory tar \
-C /home/satisfactory/.config/Epic/FactoryGame \
-xzf /var/backups/satisfactory/satisfactory-YYYYMMDD-HHMMSS.tar.gz
sudo chown -R satisfactory:satisfactory \
/home/satisfactory/.config/Epic/FactoryGame/Saved
sudo systemctl start satisfactory
sudo journalctl -u satisfactory -n 100 --no-pager
Replace the filename with the real backup you want to restore. After starting, have the admin enter Server Manager first to confirm the session, save time and server settings, then let other players join.
First check the full logs instead of repeatedly running systemctl restart:
sudo systemctl status satisfactory --no-pager -l
sudo journalctl -u satisfactory -b --no-pager
find /opt/satisfactory/FactoryGame/Saved/Logs \
-maxdepth 1 -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' \
| sort | tail
Confirm the system is x86_64, memory hasn't been killed by the OOM Killer, directory ownership is correct, and check whether the VPS uses a kvm64 CPU model with compatibility issues:
uname -m
lscpu | grep 'Model name'
sudo journalctl -k | grep -i -E 'out of memory|killed process|oom'
sudo chown -R satisfactory:satisfactory \
/opt/satisfactory /home/satisfactory
First confirm local listening:
sudo ss -lntup | grep -E ':7777|:8888'
sudo ufw status numbered
curl -k https://127.0.0.1:7777
Then check whether all three cloud security group rules are present. The most common mistake is opening only 7777/UDP and missing 7777/TCP or 8888/TCP; another common mistake is following old tutorials and opening only 15777/UDP and 15000/UDP.
First confirm the service has truly stopped:
sudo systemctl stop satisfactory
pgrep -af FactoryServer || echo 'server stopped'
sudo -u satisfactory /opt/steamcmd/steamcmd.sh \
+force_install_dir /opt/satisfactory \
+login anonymous \
+app_update 1690800 validate \
+quit
If you can still see the FactoryServer process, don't just kill -9. First find out whether it was started by another terminal, a script or a duplicate systemd unit, and send SIGINT to end it normally in the corresponding way.
Check whether the file is in the correct directory for the Linux server, whether the extension is .sav, and whether the owner is satisfactory:
sudo -u satisfactory find \
/home/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server \
-maxdepth 1 -type f -name '*.sav' -ls
If the file belongs to root, fix the ownership, restart the service, and then choose to load it in Server Manager. Don't overwrite the currently active save while the server is running.
Record data before upgrading the plan:
free -h
uptime
vmstat 1 10
pid=$(pgrep -n FactoryServer-Linux-Shipping || pgrep -n FactoryServer)
ps -p "$pid" -o pid,%cpu,%mem,rss,etime,cmd
If a single vCPU is near full load for a long time, prioritize switching to an instance with higher single-core performance; if available memory is very low and swapping continuously, add memory. When disk wait is high, check NVMe performance and whether backup tasks overlap with autosaves. Long-term servers can integrate Prometheus and Grafana VPS monitoring to observe CPU, memory, disk and network trends.
uname -misx86_64, and the CPU is not an oldkvm64model with compatibility risks.- SteamCMD uses the dedicated server App ID
1690800, not the game client App ID. - The service runs as a dedicated
satisfactoryuser, not root. 7777/TCP,7777/UDPand8888/TCPare allowed in both UFW and the cloud security group.- The server has been claimed in Server Manager, and a unique admin password has been set.
- Autosave, save on disconnect and auto-load session are configured as needed.
- systemd can start on boot,
KillSignal=SIGINT, and the logs show no persistent crash loop. - Before updating, you save and stop the service first, and never run SteamCMD while FactoryServer is running.
- A backup read test has been completed, and at least one backup has been copied off-site.
- You have actually joined, exited and reconnected from an external client, and confirmed the latest progress still exists.
Only after completing these checks does this VPS move from "can start" to "maintainable long-term." For a game server like Satisfactory whose saves keep growing, stable CPU, correct new ports, verifiable backups and rhythmic maintenance matter far more than getting the program running once.