Self-Hosting a 7 Days to Die V3.1 Dedicated Server on Linux with Docker
Published 2026-08-12 · SameOS Tools
This guide runs a 7 Days to Die V3.1 dedicated server on a home Linux box with Docker Compose. Installation and joining are the short part. The catch is that many older guides now leave difficulty, XP, and Blood Moon settings apparently ignored: V3.0 folded those settings into one SandboxCode, then V3.1 changed that code again for day/night enemy and animal density and respawn controls. So this guide treats installation, configuration, and recoverable operation as one job.
Before you start - V3.1 is the current stable branch
As of August 12, 2026, V3.1.0 b14 is stable, and the developer tells dedicated-server players to put both server and client on Default Public Version. This setup uses vinanrra/7dtd-server v0.9.3, a community-maintained image built around LinuxGSM. SteamCMD downloads the game from the stable branch separately, so the Docker image version and game version are two different numbers. The image is for x86-64 (AMD64), not an ARM board such as a Raspberry Pi.
Requirements - four cores and 16GB of RAM recommended
Steam's general game table lists a 2.8GHz quad-core CPU and 8GB of memory as minimums, with 12GB recommended, but those figures also cover the client. The official dedicated-server support guide recommends 16GB. Current Linux server files alone are roughly 16GB, making the listing's 15GB storage figure too tight; allow at least 40GB, or around 80GB if you retain backups. The steps below add your account to the docker group, which effectively grants root-level control, so use only a trusted server account. If either id command prints something other than 1000, put those numbers into PUID and PGID in the compose file.
# 1) Install download tools and the editor used in this guide (Ubuntu and Debian)
sudo apt-get update
sudo apt-get install -y curl ca-certificates nano
# 2) Download Docker's official install script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 3) Verify both Docker and Compose are installed
docker --version
docker compose version
# 4) Check the current account's user and primary group IDs
id -u
id -g
# 5) Run Docker without sudo (the docker group is effectively root-level)
sudo usermod -aG docker "$USER"
newgrp docker
docker run --rm hello-world
# 6) Create the server working folders
mkdir -p ~/7dtd && cd ~/7dtd
mkdir -p data lgsm serverfiles logs backups
The compose.yaml file - expose only the game ports
This file persists the server files, world, LinuxGSM config, logs, and backups in five host folders. Recreating the container does not erase them. The upstream example also publishes optional WebAdmin and Telnet ports 8080 through 8082; there is no reason to put them on the internet before authentication and access controls exist, so they are deliberately absent here. START_MODE is 1 in daily use and 3 only on patch day. Docker console logs rotate across five 20MB files instead of growing without a bound.
# ~/7dtd/compose.yaml
services:
7dtdserver:
image: vinanrra/7dtd-server:v0.9.3
container_name: 7dtdserver
restart: unless-stopped
stop_grace_period: 2m # allow time for a clean save and shutdown
logging:
driver: local # prevent unbounded Docker log growth
options:
max-size: "20m"
max-file: "5"
environment:
LINUXGSM_VERSION: v25.2.0
START_MODE: "${START_MODE:-1}" # 1 normally; 3 only while updating
VERSION: stable # Default Public Version
PUID: "1000" # replace with the id -u result above
PGID: "1000" # replace with the id -g result above
TimeZone: Asia/Seoul # replace with your local IANA timezone
BACKUP: "YES" # scheduled daily backup
BACKUP_HOUR: "5" # 5 AM in the container timezone
BACKUP_MAX: "7" # remove backups older than seven days
MONITOR: "YES" # LinuxGSM recovers a crashed process
UPDATE_MODS: "NO"
volumes:
- ./data:/home/sdtdserver/.local/share/7DaysToDie
- ./lgsm:/home/sdtdserver/lgsm/config-lgsm/sdtdserver
- ./serverfiles:/home/sdtdserver/serverfiles
- ./logs:/home/sdtdserver/log
- ./backups:/home/sdtdserver/lgsm/backup
ports:
- "26900:26900/tcp" # primary game port over TCP
- "26900:26900/udp" # primary game port over UDP
- "26901:26901/udp" # additional game connection UDP
- "26902:26902/udp" # additional game connection UDP
- "26903:26903/udp" # compatibility UDP recommended by current support docs
ulimits:
nofile:
soft: 10240
hard: 10240
First boot - verify installation and find the config
The first boot begins by downloading the dedicated server into ./serverfiles, not by hiding it inside the container, so it will not accept players immediately. A busy log is not automatically an error; wait until LinuxGSM reports ONLINE. After installation, the config this image actually uses is ./serverfiles/sdtdserver.xml on the host. Editing a serverconfig.xml somewhere else will not affect this setup. The container defaults to root, but LinuxGSM refuses root management commands, so every exec below deliberately includes --user sdtdserver.
# Validate the YAML and resolved settings first
docker compose config
# Start the first install in the background
docker compose up -d
# Follow installation (Ctrl+C stops following; the server keeps running)
docker compose logs -f --tail=150
# After install, verify LinuxGSM's version, status, and ports
docker compose exec --user sdtdserver 7dtdserver ./sdtdserver details
# Do not continue until this file exists
ls -l ./serverfiles/sdtdserver.xml
sdtdserver.xml - change values, do not replace the whole file
Stop cleanly, then find the properties below in the generated XML and change only their value attributes. Do not save this small excerpt as the entire file; the omitted settings are still required. Escape &, <, and " in names or descriptions as &, <, and ". Replace ServerPassword with a real long password and set Region to the server's location. GameWorld and GameName select the save path, so settle them before the first session. Changing either later does not delete the old world; it opens a different new save and looks like a reset. For console crossplay, the baseline is an eight-player cap, crossplay and EAC enabled, and no unsupported server mods.
# Stop cleanly and copy the original before editing
docker compose stop
cp -a ./serverfiles/sdtdserver.xml ./serverfiles/sdtdserver.xml.before-v31
# Locate existing lines, then open the file and change only their values
grep -nE 'ServerName|ServerDescription|ServerPassword|ServerVisibility|ServerDisabledNetworkProtocols|ServerMaxPlayerCount|ServerAllowCrossplay|EACEnabled|IgnoreEOSSanctions|Region|Language|ServerPort|GameWorld|GameName' \
./serverfiles/sdtdserver.xml
nano ./serverfiles/sdtdserver.xml
<!-- Edit matching lines to look like these; do not replace the whole file. -->
<property name="ServerName" value="SameOS V3.1 Survival Server"/>
<property name="ServerDescription" value="A private server for friends"/>
<property name="ServerPassword" value="CHANGE_ME_LONG_PASSWORD"/>
<property name="ServerVisibility" value="2"/>
<property name="ServerDisabledNetworkProtocols" value="SteamNetworking"/>
<property name="ServerMaxPlayerCount" value="8"/>
<property name="ServerAllowCrossplay" value="true"/>
<property name="EACEnabled" value="true"/>
<property name="IgnoreEOSSanctions" value="false"/>
<!-- Replace Asia with the real location, such as Europe or NorthAmericaEast. -->
<property name="Region" value="Asia"/>
<property name="Language" value="English"/>
<property name="ServerPort" value="26900"/>
<property name="GameWorld" value="Navezgane"/>
<property name="GameName" value="sameos-v31"/>
# Start again and check for configuration errors
docker compose up -d
docker compose logs --tail=100 7dtdserver
The V3.1 change - regenerate and verify SandboxCode
Since V3.0, dozens of old XML properties such as GameDifficulty, XPMultiplier, DayNightLength, BloodMoonFrequency, and LootAbundance live inside one SandboxCode instead of individual lines. To continue a V2.6 world, recreate its rules under New Game → Sandbox Options, use Copy Code, and paste the result into the XML. More importantly, V3.1 split enemy and animal density and respawn rates into day and night options, so a custom V3.0 code may be invalid. The developer warns that an invalid code can reset some or all settings to defaults; regenerating it in a V3.1 client is the safe path. With console crossplay enabled, some custom rules are outside the console-allowed range, so inspect Sandbox warnings in the restart log and test a real console join.
# Stop the running server cleanly, then open the SandboxCode line
docker compose stop
grep -n 'SandboxCode' ./serverfiles/sdtdserver.xml
nano ./serverfiles/sdtdserver.xml
<!-- Replace YOUR_V3_1_SANDBOX_CODE with the actual code copied from V3.1. -->
<property name="SandboxCode" value="YOUR_V3_1_SANDBOX_CODE"/>
# Start after saving the XML
docker compose up -d
# Open the LinuxGSM console to verify effective values
docker compose exec --user sdtdserver 7dtdserver ./sdtdserver console
# Type this inside the console
getsandboxoptions
# The short alias is equivalent: gso
# Detach without stopping the server: press Ctrl+B, then D
# Do not press Ctrl+C; it can terminate the server.
Letting friends join - match protocols on firewall and router
Traffic must pass both the server firewall and the router. Open TCP 26900 plus UDP 26900 through 26903 in UFW, then forward the same protocols to a fixed internal server address on the router. UDP 26903 currently has no primary role, but the official support guide recommends opening it for connection compatibility. Test internal-IP:26900 from the same house first, then public-IP:26900 from an outside connection such as phone tethering. If the router WAN address differs from the public IP below, carrier-grade NAT or a second router may prevent ordinary port forwarding from working.
# Find the server's internal address
hostname -I
# UFW firewall - one TCP port and four UDP ports
sudo ufw allow 26900/tcp comment '7DTD game TCP'
sudo ufw allow 26900:26903/udp comment '7DTD game UDP'
sudo ufw status
# Find the public IPv4 address seen by the internet
curl -4 https://ifconfig.me ; echo
# Verify the ports Docker actually published
docker compose port 7dtdserver 26900
docker compose ps
# Match these rules on the router
# 26900 TCP -> server's internal address
# 26900-26903 UDP -> server's internal address
Safe shutdowns and backups - do not use kill
This image traps Docker SIGTERM and calls the LinuxGSM clean-stop command. That makes docker compose stop wait up to the two-minute grace period above for save and shutdown; docker kill bypasses that path and should not be used. BACKUP=YES briefly stops the game at the scheduled hour, archives the world folder, and starts it again. BACKUP_MAX=7 means files older than seven days are removed, not that exactly seven files are kept. Pick a quiet BACKUP_HOUR and copy the XML config separately as well. The restore-test below only proves that the archive extracts in isolation; a live restore requires stopping the server and preserving the current data under another name before swapping it.
# Manual backup - the game briefly stops, then starts again automatically
docker compose exec --user sdtdserver 7dtdserver ./scripts/server_backup.sh
# Check the world archive and keep a separate XML config copy
ls -lh ./backups
cp -a ./serverfiles/sdtdserver.xml \
"./backups/sdtdserver.xml-$(date +%Y%m%d-%H%M%S)"
# Practice extracting into a fresh temporary folder each time
# Replace YYYY-MM-DD-HHMMSS with the actual filename just created.
restore_dir=$(mktemp -d ./restore-test.XXXXXX)
tar -xzf ./backups/sdtdserver-YYYY-MM-DD-HHMMSS.tar.gz \
-C "$restore_dir" --strip-components=5
find "$restore_dir" -type f | head
# Normal stop and start
docker compose stop
docker compose up -d
Updating on patch day - backup and verify stable first
Updating the Docker image and game files in persistent storage are separate operations. This setup pins the community image and uses START_MODE=3 only to update SteamCMD's stable branch. Before a patch, stop the server completely and archive the world, XML, mods, and compose file on the host. That avoids racing a scheduled backup script that starts the game again just before another stop. Continue only after the archive test succeeds, then check LinuxGSM details and make sure every client uses Default Public Version. The last command returns the container to normal START_MODE=1.
cd ~/7dtd
# 1) Stop first and create one consistent offline backup
docker compose stop
backup_file="./backups/pre-update-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "$backup_file" ./data ./lgsm \
./serverfiles/sdtdserver.xml ./serverfiles/Mods ./compose.yaml
tar -tzf "$backup_file" >/dev/null
echo "Backup verified: $backup_file"
# 2) Only continue if both tar commands succeeded; update stable, then start
START_MODE=3 docker compose up -d --force-recreate
docker compose logs -f --tail=150
# 3) After leaving the log with Ctrl+C, verify version and status
docker compose exec --user sdtdserver 7dtdserver ./sdtdserver details
# 4) Return to normal start mode 1 and verify one clean boot
docker compose up -d --force-recreate
docker compose exec --user sdtdserver 7dtdserver ./sdtdserver details
Quick checks when friends cannot connect
- Confirm that both game and server use
Default Public Version. A client on another build cannot join a V3.1 server. - Make sure
./sdtdserver detailsreports ONLINE. A running container is not yet joinable while the first world is still generating. - Confirm you edited
./serverfiles/sdtdserver.xml. Aserverconfig.xmlelsewhere is not read by this image. - Regenerate a custom V3.0
SandboxCodein the V3.1 screen, then inspect effective values withgso. - Recheck TCP 26900 and UDP 26900 through 26903 on both firewall and router. A DHCP address change can leave forwarding pointed at the wrong machine.
- If router WAN and public IP differ, investigate CGNAT or double NAT. You may need a public IP, access to the upstream router, or a suitable tunnel.
- Ports 8080 through 8082 are management interfaces, not a fix for game connectivity. Never publish them without authentication and access restrictions.
Frequently asked questions
Why is my 7 Days to Die V3.1 server not showing up?
The first world may still be generating, client and server branches may differ, or TCP 26900 and UDP 26900 through 26903 may be blocked. Test the internal address first and confirm LinuxGSM details reports ONLINE.
Can I reuse a V3.0 SandboxCode in V3.1?
It may remain valid, but V3.1 split enemy and animal density and respawn controls into day and night values. Regenerate a custom code in the V3.1 UI and verify it with getsandboxoptions as the official release note recommends.
Which ports does a 7 Days to Die dedicated server need?
Open TCP 26900 plus UDP 26900 through 26903 in both the host firewall and router forwarding rules. UDP 26903 currently has no primary role, but the official support guide recommends it for compatibility.
Does docker compose stop save the world safely?
The vinanrra/7dtd-server image used here traps SIGTERM and calls LinuxGSM clean shutdown. Keep the two-minute stop_grace_period and use docker compose stop; avoid docker kill, which bypasses the clean-stop path.
How do I fix a client/server version mismatch?
Put both client and dedicated server on Default Public Version, back up the world, and update stable server files with START_MODE=3. Verify the version and ONLINE status in LinuxGSM details afterward.