
How to Run a FiveM Server Using Docker
Deploy a reliable FiveM server with Docker Compose: install, configure server.cfg, open ports, persist data, and manage updates.
This guide is part of our complete FiveM server management hub, covering everything from initial setup to scaling your community.
TL;DR
- Install Docker Engine + Docker Compose v2 on Ubuntu. (Docker Documentation)
- Create a project folder, add
.env(setLICENSE_KEY,SERVER_NAME, ports) and a minimalcompose.yaml. - Start with
docker compose up -d; watch logs withdocker compose logs -f. - Edit
data/server.cfg(hostname, endpoints, resources); restart the container. - Open firewall for 30120/TCP+UDP and 40120/TCP (txAdmin). txAdmin’s default port is 40120. (Cfx.re Docs)
- Always run the container with stdin/tty enabled to avoid crashes. (GitHub)
Prerequisites
- OS: Linux Ubuntu 22.04+ (notes for macOS/Windows below).
- Hardware: 2+ vCPU, 4–8 GB RAM (more for heavy resources), SSD recommended.
- Docker: Install Docker Engine and Compose v2 from official docs. (Docker Documentation)
- FiveM License Key: Generate in the Cfx.re portal (Keymaster). Keep it secret. (support.cfx.re)
- Firewall/NAT: Ability to open/forward ports 30120 (TCP+UDP) and optionally 40120 (TCP). (Cfx.re Docs)
- (Optional) A domain/subdomain for txAdmin.
Architecture overview
One container runs FXServer using the spritsail/fivem image. Data is bind-mounted to persist server.cfg, resources, and logs. Ports 30120/TCP+UDP are exposed to players; 40120/TCP exposes txAdmin when enabled. A healthcheck can probe http://127.0.0.1:30120/info.json. (GitHub)
+-------------------- Docker Host (Ubuntu) --------------------+
| /home/fivem/data --> /config (in container) |
| /home/fivem/txData --> /txData (txAdmin data) |
| |
| Exposed: 30120/tcp+udp [FXServer] | 40120/tcp [txAdmin] |
| Healthcheck: GET 127.0.0.1:30120/info.json |
+-------------------------------------------------------------+
Quick Start (copy-paste)
1) Create a project folder
# Optional: dedicated system user and directories
sudo useradd -r -m -d /home/fivem -s /usr/sbin/nologin fivem || true
sudo mkdir -p /home/fivem/{data,txData}
sudo chown -R "$USER":"$USER" /home/fivem
cd /home/fivem
2) Create .env
cat > .env <<'EOF'
# === REQUIRED ===
LICENSE_KEY=REPLACE_WITH_YOUR_CFX_KEY
# Convenience (used by ports mapping below)
FXSERVER_PORT=30120
TXADMIN_PORT=40120
# Not read by the image directly; use it when editing server.cfg
SERVER_NAME="My Docker FiveM"
# Optional: if omitted, default config generation sets a random RCON password
RCON_PASSWORD=
EOF
3) Minimal compose.yaml (pin a tag)
Smallest working setup using the upstream image. Uses tty+stdin to prevent crash. (GitHub)
# compose.yaml
services:
fivem:
image: spritsail/fivem:stable
container_name: fivem
environment:
- LICENSE_KEY=${LICENSE_KEY}
# Optional toggles (see table below):
# - NO_DEFAULT_CONFIG=1 # required if you want to use txAdmin
# - NO_LICENSE_KEY=1 # if you put the key in server.cfg instead
# - NO_ONESYNC=1 # disable OneSync in default config
# - RCON_PASSWORD=${RCON_PASSWORD}
volumes:
- ./data:/config # server.cfg, resources, logs
ports:
- "${FXSERVER_PORT}:30120/tcp"
- "${FXSERVER_PORT}:30120/udp"
tty: true # prevent startup crash (equiv. to -t)
stdin_open: true # prevent startup crash (equiv. to -i)
restart: unless-stopped
Start it:
docker compose up -d
docker compose logs -f
4) Extended variant (txAdmin, healthcheck, limits)
# compose.extended.yaml
services:
fivem:
image: spritsail/fivem:stable
container_name: fivem
environment:
- LICENSE_KEY=${LICENSE_KEY}
- NO_DEFAULT_CONFIG=1 # enable txAdmin (no default +exec)
# - NO_LICENSE_KEY=1 # if storing key in server.cfg
# - RCON_PASSWORD=${RCON_PASSWORD}
volumes:
- ./data:/config
- ./txData:/txData # persist txAdmin data
ports:
- "${FXSERVER_PORT}:30120/tcp"
- "${FXSERVER_PORT}:30120/udp"
- "${TXADMIN_PORT}:40120/tcp" # txAdmin Web UI (default 40120)
tty: true
stdin_open: true
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:30120/info.json >/dev/null 2>&1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
# Basic resource knobs for standalone Compose (not Swarm 'deploy')
cpus: 2
mem_limit: "6g"
ulimits:
nofile:
soft: 1048576
hard: 1048576
restart: unless-stopped
If
wgetis unavailable in the image, remove the healthcheck or replace with a TCP probe. txAdmin persists under/txData, port 40120 is its default. (GitHub)
Configuration & Persistence
- On first run, defaults are written to the bind mount
./data(container path/config). Edit./data/server.cfgand restart the container. (GitHub)
Typical server.cfg bits:
# data/server.cfg
# Network endpoints (leave 0.0.0.0 to listen on all interfaces)
endpoint_add_tcp "0.0.0.0:30120"
endpoint_add_udp "0.0.0.0:30120"
# Server name
set sv_hostname "My Docker FiveM"
# License key (use this only if NOT using LICENSE_KEY env)
# sv_licenseKey "REPLACE_WITH_YOUR_CFX_KEY"
# Example: ensure a basic resource
# ensure chat
Directory layout (host):
/home/fivem
├─ data/ -> /config (server.cfg, resources/, logs/)
└─ txData/ -> /txData (txAdmin profiles & DB)
Backups
- Bind-mount backup:
tar -C /home/fivem -czf fivem-backup_$(date +%F).tgz data txData
- If you switch to named volumes, back up like:
docker run --rm -v fivem_data:/data -v "$PWD":/backup busybox \
sh -c 'tar -czf /backup/fivem_data_$(date +%F).tgz -C / data'
Environment variables (from spritsail/fivem)
| Name | Purpose | Example |
|---|---|---|
LICENSE_KEY | Required FiveM server license key to start FXServer | LICENSE_KEY=xxxxx |
RCON_PASSWORD | RCON password used when creating default configs; random 16-char if unset | RCON_PASSWORD=strongpass |
NO_DEFAULT_CONFIG | Disable default +exec so txAdmin can manage the server | 1 |
NO_LICENSE_KEY | Don’t read key from env; keep it in server.cfg | 1 |
NO_ONESYNC | Disable OneSync in default configs | 1 |
These env vars and paths /config, /txData, plus the need for -ti are defined by the upstream image. (GitHub)
Secret handling: Prefer
NO_LICENSE_KEY=1and putsv_licenseKeyinserver.cfgwith correct file permissions if you don’t want the key in the container env. (GitHub)
Networking & Security
Required ports
| Purpose | Port | Proto |
|---|---|---|
| Player connections / API | 30120 | TCP+UDP |
| txAdmin Web UI (optional) | 40120 | TCP |
| Legacy master (rarely needed) | 30110 | UDP |
FiveM defaults to 30120; txAdmin’s default is 40120. (GitHub)
UFW examples (Ubuntu)
sudo ufw allow 30120/tcp
sudo ufw allow 30120/udp
sudo ufw allow 40120/tcp # only if you enable txAdmin
sudo ufw reload
nftables (example ruleset extract)
sudo nft add table inet filter
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input tcp dport {30120,40120} accept
sudo nft add rule inet filter input udp dport 30120 accept
Least privilege & secrets
- Run on a hardened host; avoid mapping extra capabilities; don’t run Docker as
rootuser on the host. - Keep RCON enabled only if needed; protect txAdmin with strong credentials and restrict access at the firewall.
- If you use SELinux-based distros (not Ubuntu), add
:Z/:zto bind mounts to fix context issues.
Updates & Rollbacks
Update to latest pinned tag
docker compose pull
docker compose up -d
Pin by digest (immutable)
# Pull and discover the digest of the current tag
docker pull spritsail/fivem:stable
docker inspect --format='{{index .RepoDigests 0}}' spritsail/fivem:stable
# Use the printed value in compose, e.g.:
# image: spritsail/fivem@sha256:abcdef...
Rollback
- Change the image reference back to the previous tag/digest and
docker compose up -d. - Keep recent image digests with
docker image ls --digests.
The image provides stable and latest tags; prefer stable for fewer surprises. (GitHub)
Monitoring & Maintenance
- Status:
docker ps,docker compose ps - Logs:
docker compose logs -f - Stats:
docker stats fivem - Healthcheck: Polls
info.json; remove/adjust if tooling missing. (Cfx.re Docs) - Disk:
docker system df, prune old images if needed. - Backups: Cron the tar command in “Configuration & Persistence”.
Troubleshooting
- Invalid license key: Verify in Cfx.re portal and ensure only one server is using the key. (support.cfx.re)
- Ports already in use:
sudo ss -lntup | grep 30120; stop conflicting service or changeFXSERVER_PORT. - Can’t reach txAdmin: Open 40120/TCP or change port; confirm
NO_DEFAULT_CONFIG=1. (Cfx.re Docs) - Container exits on start: Ensure
tty: trueandstdin_open: trueare set. (GitHub) - Time/DNS issues: Ensure host time sync (systemd-timesyncd/chrony) and working DNS (
/etc/resolv.conf). - SELinux denials (non-Ubuntu): Use
:Z/:zon bind mounts or adjust contexts. - info.json/players.json blocked: Some convars or proxies can affect these endpoints; confirm server responds on
GET /info.json. (Cfx.re Docs)
Performance Tips
- CPU/Memory: Pin CPUs and set memory limits (see extended compose).
- Storage: Use SSD/NVMe; keep resource packs optimized; avoid huge, uncompressed assets.
- Networking: Keep latency low; ensure host isn’t CPU throttled; prioritize UDP 30120.
- Host kernel: Reasonable defaults work; advanced sysctls (
net.core.*mem_max) can be tuned if you know your workload. - Logs: Use log rotation (as in extended example).
macOS / Windows notes
- macOS (Docker Desktop): Bind-mounted file I/O is slower than native Linux; consider Docker Desktop’s Synchronized file shares for better performance and ensure the folder is shared in settings. (Docker Documentation)
- Windows (WSL2): Published ports are reachable via localhost on Windows; exposing to LAN can require extra configuration depending on mode. Prefer hosting on Linux for public servers. (Docker Documentation)
Clean Uninstall
# Stop and remove the container (keep data)
docker compose down
# Remove container + anonymous networks + images (keeps bind-mounted data)
docker compose down --rmi local --remove-orphans
# If you used named volumes (not in this guide), list and remove explicitly:
# docker volume ls
# docker volume rm <volume_name>
To delete all data, remove the bind-mounted directories:
sudo rm -rf /home/fivem/data /home/fivem/txData
FAQ
Can I host multiple servers on one host?
Yes. Use separate project directories, different FXSERVER_PORT/TXADMIN_PORT, and distinct bind mounts. txAdmin supports per-profile data in /txData. (Cfx.re Docs)
How do I change the server name/IP shown in the list?
Edit sv_hostname in data/server.cfg. The IP/port comes from your published ports and NAT config.
Can I restart automatically on crash?
Yes. restart: unless-stopped in Compose; also consider systemd timers for watchdogs.
Where are backups located?
Where you create them—e.g., fivem-backup_YYYY-MM-DD.tgz in your working directory. See the backup commands above.
How do I enable txAdmin?
Set NO_DEFAULT_CONFIG=1, bind-mount /txData, and open 40120/TCP. (GitHub)
Do I need 30110 open?
Rarely. It was used for legacy listing; modern setups typically only need 30120 and txAdmin’s 40120 if used. (Cfx.re Community)
How do I move the server to another machine?
Copy data/ and txData/ to the new host, recreate the same Compose file, and start.
Links & Credits
- Upstream image:
spritsail/fivem(env vars, paths, usage, txAdmin notes,-tirequirement). (GitHub) - Docker:
- Install Docker Engine on Ubuntu. (Docker Documentation)
- Install Docker Compose v2 (Linux plugin). (Docker Documentation)
- Sharing local files with containers (volumes vs bind mounts). (Docker Documentation)
- Cfx.re / FiveM:
- Create a server registration (license) key. (support.cfx.re)
- txAdmin docs (default port 40120; data path). (Cfx.re Docs)
- Proxy/connection flow (
/info.json). (Cfx.re Docs)
Bleib auf dem Laufenden
Erhalte die neuesten FiveM-Tutorials, Mod-Releases und exklusive Updates direkt in dein Postfach.
Kein Spam. Jederzeit abbestellbar.