Rust is the heaviest "small" server I run. A vanilla 3500 world idles around 4-5 GB and climbs the longer it goes since the last wipe. Budget 6 GB and a couple of real cores or it stutters the moment a few players start building.

TL;DR:

# deps + steam user
apt update && apt install -y steamcmd lib32gcc-s1 tmux
adduser --disabled-password --gecos "" steam
sudo -iu steam

# install app id 258550 (anonymous)
steamcmd +force_install_dir /home/steam/rust \
  +login anonymous +app_update 258550 validate +quit

# launch
cd /home/steam/rust
./RustDedicated -batchmode -nographics \
  +server.identity myserver +server.port 28015 \
  +server.maxplayers 50 +server.worldsize 3500 +server.seed 12345 \
  +rcon.port 28016 +rcon.password "changeme" +rcon.web 1

Details below.

Install SteamCMD and the server

Run as root for the deps, then do everything else as an unprivileged steam user:

apt update
apt install -y steamcmd lib32gcc-s1 tmux
adduser --disabled-password --gecos "" steam
sudo -iu steam

If apt can't find steamcmd, enable multiverse and accept the license non-interactively:

add-apt-repository multiverse && dpkg --add-architecture i386 && apt update
echo steam steam/question select "I AGREE" | debconf-set-selections
echo steam steam/license note '' | debconf-set-selections
apt install -y steamcmd

App id 258550, anonymous login — no account needed for the dedicated server:

steamcmd +force_install_dir /home/steam/rust \
  +login anonymous +app_update 258550 validate +quit

The download is ~12 GB and Facepunch ships a forced update on the first Thursday of every month. Keep validate in your update command — Rust's asset bundles corrupt on a half-finished pull and the symptom is a server that boots but kicks everyone with a checksum error.

The cvars that matter

Rust has no config file you edit by hand for the basics — you pass +server.* cvars on the command line (or in a server.cfg it reads at boot). The ones I always set:

./RustDedicated -batchmode -nographics \
  +server.identity   "myserver" \
  +server.hostname   "Diengdoh Rust | Vanilla" \
  +server.port       28015 \
  +server.maxplayers 50 \
  +server.worldsize  3500 \
  +server.seed       12345 \
  +server.description "Friendly EU vanilla. Monthly wipe." \
  +server.url        "https://blog.diengdoh.com" \
  +rcon.port         28016 \
  +rcon.password     "use-a-real-one" \
  +rcon.web          1
  • server.identity is the folder name under server/ where your map, blueprints and bans live. Pick one and never change it or you orphan the save.
  • server.worldsize and server.seed together define the map. Same seed + same size = same map. Changing either forces a fresh map — i.e. a wipe.
  • worldsize drives RAM. 3000 is small and cheap, 4500 is big and hungry. Don't set 6000 on a VPS unless you like the OOM killer.
  • rcon.web 1 makes RCON a websocket on the RCON port, which is what every admin tool (RustAdmin, the RCON apps) expects.

Ports and ufw

Three ports. Game traffic is 28015 UDP, RCON is 28016 TCP, and the optional Rust+/companion query is 28017 TCP:

ufw allow 28015/udp           # game
ufw allow 28017/tcp           # rust+ / app, optional
ufw allow from 203.0.113.10 to any port 28016 proto tcp   # RCON — lock it down

Never open 28016 to the whole internet. RCON is full admin over your server; restrict it to your own IP or tunnel it over SSH. Firewall primer: /ufw-firewall-rules-ubuntu/.

Plugins with Oxide / uMod

Vanilla is fine, but most admins want Oxide (uMod) for permissions, kits, and admin tools. Carbon is the newer alternative that loads the same plugins; pick one, not both.

# as steam, in the install dir
cd /home/steam/rust
curl -sL https://umod.org/games/rust/download/develop -o oxide.zip
unzip -o oxide.zip && rm oxide.zip

Restart the server once and Oxide creates oxide/plugins/, oxide/config/ and oxide/data/. Drop .cs plugin files into oxide/plugins/ and Oxide hot-loads them — no restart needed. The gotcha: a Facepunch update breaks Oxide until uMod ships a matching build, usually within a day. If your modded server won't boot right after the monthly update, that's why. Don't auto-update a modded box on wipe day.

systemd unit

tmux is fine for a test. For anything real, use systemd so it restarts on crash and comes back on boot:

# /etc/systemd/system/rust.service
[Unit]
Description=Rust Dedicated Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=steam
WorkingDirectory=/home/steam/rust
ExecStartPre=/usr/games/steamcmd +force_install_dir /home/steam/rust +login anonymous +app_update 258550 validate +quit
ExecStart=/home/steam/rust/RustDedicated -batchmode -nographics \
  +server.identity myserver +server.port 28015 +server.maxplayers 50 \
  +server.worldsize 3500 +server.seed 12345 \
  +rcon.port 28016 +rcon.password "use-a-real-one" +rcon.web 1
Restart=on-failure
RestartSec=10
KillSignal=SIGTERM
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now rust
journalctl -u rust -f

The ExecStartPre line re-validates on every start so you're current after wipe day — drop it on a modded box where you want to control update timing yourself. More on units in /systemd-service-unit-file/.

Gotchas

  • RAM creep. A server's memory climbs across a wipe cycle as the map fills with bases and entities. What idles at 4 GB on wipe day can be 7 GB three weeks in. Size for week three, not day one.
  • Wipe day. First Thursday monthly Facepunch force-updates the protocol and clients can't join an un-updated server. Map wipes are forced; blueprint wipes are your choice (delete the server/<identity>/player.blueprints.* data). Communicate your wipe schedule or players walk.
  • Oxide lag after updates. Covered above — modded servers stay down until uMod catches up. Plan maintenance windows around it.
  • server.seed 0 is random. Leave it unset or 0 and you get a different map every boot, which silently wipes you every restart. Always pin a seed.
  • CPU matters as much as RAM. Rust's entity simulation is single-thread-heavy. A box with lots of slow cores is worse than fewer fast ones.

Verify

# ports bound?
ss -tulpn | grep -E '28015|28016'

# server reported ready?
journalctl -u rust --no-pager | grep -i "SteamServer Initialized"

# watch joins
journalctl -u rust -f | grep -i "has entered the game"

In game: press F1, type client.connect <your-ip>:28015. If it shows in the community browser, your ports and hostname are right.

Building out a stable? The same SteamCMD + systemd pattern runs Enshrouded and 7 Days to Die — both memory-hungry like this one. Project Zomboid is the lighter option.


Related posts