RE:NODE
Обзор хостинга

VDS15 мин чтения

Several game servers on one VDS: ports, users, systemd

How to run four or five game servers on one box: a port map, one user each, systemd units with limits, LinuxGSM, staggered updates and backups, and when not to bother.

Эта статья пока на английском. Мы её переводим.

0 прочтений

Running several game servers on one VDS is a real and sensible thing to do, and it is almost never worth it for one or two. Below about three servers, a managed plan per game costs less in money once you value your own hours above zero, and costs nothing at all in evenings. The case for one box appears at four, five or six servers, when memory starts to pool usefully, when you want them all on one address, and when you are already comfortable with Linux.

If you have decided, the job has five parts: a port map you write down before you install anything, one unprivileged user per server, a systemd unit per server with resource limits on it, a way to send commands without a panel, and staggered updates and backups so that five things do not all hammer the same disk at four in the morning. This post goes through each, plus LinuxGSM and the option of installing a panel on your own machine.

Be honest about whether you should#

Start here, because the rest of the post is a lot of work to do for the wrong reason.

A managed game plan hands you a server about a minute after payment clears, with the install done, the ports allocated, a console, a file manager, SFTP, scheduled tasks and backup slots. A VDS hands you an empty Debian box and a root password within a day. Everything else in this post is the gap between those two sentences, and it is roughly a weekend the first time.

Separate managed plansOne VDS
Time to first server runningAbout a minute1-3 hours
MemoryFixed per plan, paid whether used or notPooled across everything
PortsAllocated per plan, more on the Network tabAny port you like
Console for each serverBuilt in, per serverRCON, tmux, or you build it
Giving a friend restart accessSubuser with limited permissionsAn SSH account, or a script
Updates and patchingNot your problemYours, on a schedule
A crash at 3amWatched for and restartedWhatever Restart= does

The honest dividing line is memory shape rather than count. Five servers that are each 2 GB and idle most of the week pool beautifully on a 16 GB VDS, because the one that spikes borrows from the four that are quiet. Two servers that are each genuinely 6 GB and busy do not pool at all, and you have bought a sysadmin job for nothing. Choosing between a VDS and a game panel has the full arithmetic, including what the operating system itself costs you before you run anything.

One more thing that is not obvious until you have done it: the second game server is easy and the fifth is not. Each one adds a port range to remember, an update schedule, a backup, a different config format and a different way of taking commands. The work is not linear.

Sizing: what actually fits#

Two numbers constrain you, and it is usually not the one people check.

Memory is the easy one. Subtract 300-400 MB for a minimal Debian or Ubuntu with nothing installed, more if you add Docker, a web server or monitoring, then divide what is left. An 8 GB VDS realistically gives you about 7 GB of game server.

CPU is the constraint that bites. Almost every game server simulates its world on one thread. Four servers all ticking at once need four threads that are each fast enough, and no amount of total core count helps if they are slow cores. On a two-vCPU box, two busy game servers are fine and four busy ones interfere with each other during peak hours, even with memory to spare. This is the same effect described in shared CPU and noisy neighbours, except that this time the noisy neighbour is you.

VDS sizeComfortable loadNot comfortable
8 GB, 2 vCPUTwo or three small servers, staggered peaksFour busy servers at once
16 GB, 4 vCPUFour or five, or one big modded world plus two smallEight of anything
24 GB, 6 vCPUSix, or a mixed stack with a database and a web appA dozen, whatever the memory says

Plan for peak, not for average. Five servers that each idle at 800 MB and each peak at 3 GB will not survive a Friday night together on 16 GB, and the resulting out-of-memory kill takes down whichever server was largest at the time rather than whichever one caused it. Swap and the OOM killer explains how that decision gets made and how to bias it.

A port map, written down first#

Do this before you install anything. Five minutes now saves an afternoon of a server that starts, binds nothing, and logs an "address already in use" line you will not notice for an hour.

GameDefault portsNotes
Minecraft Java25565/tcpPlus 25575/tcp if you enable RCON
Valheim2456/udp, 2457/udpQuery is always the game port plus one
Palworld8211/udpSet with -port
Counter-Strike 227015/udp, 27015/tcpPlus 27020/udp for GOTV
Terraria7777/tcpOne port, no query
Factorio34197/udpOne UDP port
TCP 25565UDP 2456UDP 27015Playersdifferent gamesPublic IP203.0.113.10MinecraftTCP 25565ValheimUDP 2456-2457CS2UDP 27015NVMe diskshared by everything
One address, several servers, one port map

Three rules make the map hold together. Give each server a block rather than a single number, because most games quietly want a second port for queries or a third for a feature you enable later. Leave gaps - space them ten or twenty apart, not one. And write the whole thing in a file on the machine, because in eight months you will be trying to remember which server owns 27025.

Source-engine games are the awkward case. Two instances on one machine need distinct values for -port, +tv_port and +clientport, and setting only the first gives you two servers fighting over the same GOTV socket, which fails in a way the log describes badly. Game server ports explained covers why query ports exist and what happens when only one of a pair is reachable.

Then open exactly those ports and nothing else:

bash
$ ufw default deny incoming$ ufw allow 22/tcp$ ufw allow 25565/tcp          # Minecraft$ ufw allow 2456:2457/udp      # Valheim game and query$ ufw allow 8211/udp           # Palworld$ ufw enable$ ufw status numbered

RCON ports are the exception: do not open them to the internet. Bind RCON to 127.0.0.1 and reach it over an SSH tunnel, which costs nothing and removes an entire category of problem. RCON safely explains why an exposed RCON port with a guessable password is the fastest way to lose a server, and the ufw firewall guide covers the rest of the ruleset.

One user per server#

This is the part people skip and later regret. Every game server gets its own unprivileged user and its own directory tree. Nothing runs as root, and nothing runs as the same user as anything else.

bash
$ adduser --disabled-password --gecos "" --home /srv/valheim valheim$ adduser --disabled-password --gecos "" --home /srv/minecraft minecraft$ chown -R valheim:valheim /srv/valheim$ sudo -u valheim -i           # become that user to install or edit

The reason is containment. Game servers run mods and plugins written by strangers, occasionally load content uploaded by players, and expose network services that parse untrusted input. When one of them is compromised - and keeping a modded server clean is the fuller version of that worry - the blast radius should be one directory, not the machine. A separate user also means a stray rm -rf in the wrong terminal fails with a permission error instead of succeeding.

There is a practical benefit too. ps aux and systemd-cgtop become readable, because the user column tells you immediately which server is using the CPU. Separate Steam installs go in separate homes, so steamcmd +force_install_dir /srv/valheim/server and +force_install_dir /srv/pz/server never collide. SteamCMD explained has the update script pattern.

systemd is the supervisor#

Not tmux, not screen, not nohup. A process started in a terminal multiplexer does not start at boot, does not restart after a crash, and is invisible to anything you set up later. Use a systemd unit, and use a template so that adding the fifth server is copying one environment file rather than one unit file.

/etc/systemd/system/gameserver@.service
[Unit]Description=Game server: %iAfter=network-online.targetWants=network-online.target[Service]User=%iGroup=%iWorkingDirectory=/srv/%iEnvironmentFile=/etc/gameservers/%i.envExecStart=/srv/%i/start.shRestart=on-failureRestartSec=20KillSignal=SIGINTTimeoutStopSec=120CPUQuota=150%MemoryHigh=3500MMemoryMax=4GNice=-5[Install]WantedBy=multi-user.target

%i is the instance name, so systemctl enable --now gameserver@valheim runs /srv/valheim/start.sh as the valheim user with /etc/gameservers/valheim.env loaded. One unit file, one line per server.

Four directives are doing real work here:

  • KillSignal=SIGINT is the one people leave out and the one that costs worlds. Many game servers save on a clean interrupt and lose everything since the last autosave on a SIGKILL. The default unit sends SIGTERM and gives up after 90 seconds; TimeoutStopSec=120 gives a large world time to finish writing.
  • CPUQuota=150% caps that server at one and a half cores. This is the setting that stops one modded world from starving the other four during a raid, and it is the main reason to prefer systemd over LinuxGSM's own supervision.
  • MemoryMax gives the server its own ceiling. Hitting it kills only that cgroup, not the largest process on the machine, which is a much better failure than the global out-of-memory kill.
  • Restart=on-failure with a RestartSec of fifteen or twenty seconds. Do not use always with a one-second delay: a server that fails to start loops forever and fills your disk with logs.

Then check what everything is actually using:

bash
$ systemctl status gameserver@valheim$ journalctl -u gameserver@valheim -f$ systemd-cgtop$ systemctl list-units 'gameserver@*'

systemd-cgtop is the per-service version of top, and on a box with five servers it is the fastest way to see which one has gone wrong. The rest of the unit file syntax is in systemd services for your apps.

Sending commands without a panel#

This is the friction nobody warns you about. On a panel there is a console per server. On a VDS, a systemd-managed process has no terminal you can type into, and journalctl is read-only.

Two workable answers. Where the game supports RCON, use it, bound to localhost:

bash
$ mcrcon -H 127.0.0.1 -P 25575 -p "$RCON_PASS" "say Restart in 5 minutes" "save-all"$ ssh -L 25575:127.0.0.1:25575 deploy@203.0.113.10   # tunnel from your laptop

Where it does not, run the server inside a tmux session owned by its user and drive it with send-keys:

bash
$ sudo -u valheim tmux send-keys -t valheim "save" Enter$ sudo -u valheim tmux attach -t valheim      # detach again with Ctrl-b d

That is the approach LinuxGSM takes, and it works, at the cost of a slightly odd systemd unit. Whichever you pick, script the things you do often - announce, save, stop - because doing them by hand across five servers at update time is how steps get missed.

LinuxGSM: what it gives you and where it stops#

LinuxGSM is a set of shell scripts that installs, configures, updates, backs up and monitors dedicated servers for well over a hundred games. It is genuinely good, it is free, and for a mixed stack it saves hours of reading each game's installation notes.

bash
$ wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh$ bash linuxgsm.sh vhserver          # creates the vhserver script$ ./vhserver install$ ./vhserver start$ ./vhserver details                 # ports, paths, status$ ./vhserver update$ ./vhserver backup$ ./vhserver console

Each game has a short code - vhserver for Valheim, mcserver for Minecraft, gmodserver for Garry's Mod, tf2server for Team Fortress 2, and so on. Settings live in lgsm/config-lgsm/<code>/<code>.cfg, which overrides the shipped defaults the same way jail.local does for fail2ban.

LinuxGSM refuses to run as root, which enforces the one-user-per-server rule for you. Its details command prints the exact ports a game needs, which is the fastest way to build the port map described above.

Two honest limits. First, its monitor command is designed to be run from cron every few minutes, and it will happily restart a server that systemd is also trying to restart. Pick one supervisor: either systemd units with Restart=on-failure and no monitor cron entry, or LinuxGSM's own monitoring and no systemd unit. Running both produces a server that restarts twice and a log that makes no sense.

crontab -u vhserver -e
*/5 * * * * /srv/valheim/vhserver monitor > /dev/null 2>&10 4 * * * /srv/valheim/vhserver update > /dev/null 2>&1

Second, LinuxGSM does not give you resource limits. It starts the process; it does not cap its CPU or memory. On a box with one or two servers that is fine. On a box with five, the CPUQuota and MemoryMax lines above are the difference between one bad server and five bad servers, so most people end up with systemd units regardless and use LinuxGSM for installation and updates only. Cron expressions explained covers the schedule syntax if the five fields are unfamiliar.

Updates, backups and restarts, staggered#

Five servers doing the same thing at the same time is the mistake that turns a working box into an unusable one for ten minutes every night.

  • Stagger the backups. A tar of a 40 GB world is a sustained read and a sustained write on the same device. Five at once saturates it. Put them twenty minutes apart.
  • Stagger the restarts. Restarting everything at 05:00 means every server reloads its world simultaneously, which is the heaviest thing any of them do. Restart schedules that help covers which servers benefit from a restart at all, because several do not.
  • Do not auto-update a modded server. A game patch on the day it lands breaks every mod until authors catch up. Update vanilla servers automatically; update modded ones by hand, after checking, and keep a copy of the working mod folder. What to do when a mod update breaks is the recovery procedure.

A systemd timer is tidier than cron for this, because the log ends up in the journal beside the service it backs up:

bash
$ tar -czf /srv/backups/valheim-$(date +%F-%H%M).tar.gz -C /srv/valheim worlds_local$ find /srv/backups -name 'valheim-*.tar.gz' -mtime +14 -delete$ restic -r sftp:backup@198.51.100.5:/srv/restic backup /srv/valheim/worlds_local

The critical part is the destination. A backup on the same disk as the server protects against a corrupt save and nothing else - not a deleted directory, not a failed disk, not a mistake made at midnight. Send it somewhere else, and restore one occasionally to prove it works, because a backup nobody has restored is a hypothesis. Testing a restore before you need it is the ten-minute version of that habit.

Finally, the machine itself. Weekly apt update && apt full-upgrade, automatic security updates enabled, a default-deny firewall, key-only SSH and fail2ban on the SSH port. None of that happens by itself, and a box running five game servers is a more interesting target than a box running one. The first hour on a new VDS is the checklist, and Linux commands for server admins covers the daily reading.

Or install a panel on your own VDS#

The common ambition is both: root access and a real interface so that other people can restart things without an SSH key. Pterodactyl is the usual choice and it is perfectly installable, but be clear about what you are taking on.

It is two components. The panel is a Laravel application needing a web server, PHP with its extensions, a MySQL-compatible database, Redis and Composer. Wings is a Go daemon needing Docker, talking to the panel over its own port, with SFTP served separately. Upstream defaults put the Wings API on 8080 and its SFTP listener on 2022, with the panel on 80 and 443.

That is five or six services to keep patched, a certificate for the panel hostname, and a Docker image per game. Budget around 1 GB of memory before any game server runs. On a 24 GB VDS that is a rounding error; on the 8 GB tier it is an eighth of your machine spent on infrastructure rather than on players. What a Pterodactyl panel gives you covers the architecture in more detail.

A reasonable rule: install a panel on your own machine when hosting for other people is the product, and you are charging for it. Do not install one so that three friends can press Restart. On a managed RE:NODE plan that is a subuser account with granular permissions - console only, files only, no billing - on a role that can be time-boxed, with a per-server activity log. Subusers and least privilege walks through setting that up, and it takes about two minutes.

That is the honest summary of this whole post. Every managed plan gets the same panel with the same console, file manager, per-server SFTP, schedules and backup slots, and the server exists about a minute after payment clears. A VDS gets you full root access, prepared by hand and delivered within 24 hours, and everything above becomes yours. Pick the one that matches how many servers you are actually running and how much of your week you want back.

FAQ#

How many game servers fit on one VDS?

Count fast threads, not gigabytes. Most game servers simulate on one thread, so a two-vCPU box comfortably runs two or three that peak at different times, and a six-vCPU box runs five or six. Memory sets a hard ceiling; CPU sets the one you actually feel.

Can they all share one IP address?

Yes. That is the normal arrangement, and it is why the port map matters. Each server binds a different port on the same address, and players connect with address:port. Only one server per protocol can own a given port number.

Should I use Docker for each server?

You can, and it gives you clean isolation and easy limits, but it adds an image to maintain per game and a firewall caveat: Docker publishes ports by writing its own rules, which are consulted before ufw's, so a container can be reachable even when the firewall says the port is closed. Bind to 127.0.0.1 where you can. Docker on a VDS has the detail.

Is tmux good enough to keep a server running?

For something you are watching, yes. For anything permanent, no. A tmux session does not start after a reboot and does not restart after a crash. Use a systemd unit and keep tmux for the console, if the game has no RCON.

What happens when one server uses all the memory?

Without limits, the kernel picks the largest process on the machine and kills it, which is often not the one that misbehaved. With MemoryMax on each unit, the offender hits its own ceiling and only it dies. Set the limits.

Is this cheaper than separate managed plans?

Sometimes. Below three servers, almost never, once you count the hours. Above five, usually, because memory pools and you pay for the machine rather than for five separate ceilings. Price both, then add a realistic number of hours per month to the VDS side before comparing.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000