Cgroups (control groups) are a Linux kernel feature that lets you limit, account for, and isolate the resource usage of processes. On a shared game server, cgroups can reliably cap CPU time, memory, and block I/O for each game instance, but they cannot isolate the kernel, the filesystem namespace, or network ports — those require additional technologies like containers or virtual machines. This article explains exactly what cgroups do, what they don’t do, and how to use them safely on a multi-game server.
Background: Why Shared Game Servers Need Cgroups
Running multiple game servers on one physical machine is common for hosts and hobbyists. Without limits, one game — say a modded Minecraft server or a busy Counter-Strike server — can consume all available RAM or CPU, causing lag or crashes for every other game on the box. Cgroups were introduced in Linux kernel 2.6.24 (2008) and have been the standard way to enforce resource limits since systemd integrated them by default. They are the same mechanism Docker and LXC use under the hood, so understanding cgroups directly transfers to containerized game hosting.
How Cgroups Work: Controllers and Hierarchies
Cgroups operate through controllers, each managing one type of resource. The main controllers relevant to game servers are:
- cpu — limits CPU time in shares or absolute quotas (e.g., 50% of one core).
- memory — sets a hard limit on RAM, plus a separate swap limit.
- blkio — throttles disk reads/writes per second or per I/O operation.
- pids — caps the number of processes/threads a game can spawn.
- cpuset — pins a game to specific CPU cores, useful for latency-sensitive titles.
In the modern cgroups v2 (default since kernel 4.15, and the only version in systemd 240+), all controllers hang off a single hierarchy. You create a directory under /sys/fs/cgroup, write the PID of the game process into cgroup.procs, and set limits by writing to files like memory.max or cpu.max. The kernel enforces these limits immediately, without requiring the game to cooperate.
What Cgroups Can Isolate: CPU, Memory, Disk I/O, and PIDs
Here is what a cgroup can reliably do on a shared game server:
- CPU time: You can give each game a guaranteed share (e.g., 2 cores) and a hard ceiling (e.g., 4 cores). The
cpu.maxfile takes two numbers: quota (microseconds per period) and period (default 100,000 µs). A quota of 200,000 means 2 full cores. Games that use multiple threads, like Factorio or Ark, benefit from a quota that matches their expected thread count. - Memory: Set
memory.maxto a value like 4G. When the game exceeds it, the kernel triggers OOM-kill inside that cgroup — only the offending game dies, not the whole server. You can also setmemory.swap.maxto 0 to disable swapping for latency-sensitive games. - Disk I/O:
io.maxlets you cap read/write bandwidth (e.g., 100 MB/s) and IOPS. This stops a world-generation spike from starving other games’ disk access. - Process count:
pids.maxprevents a runaway script or a game that leaks threads from exhausting the system’s PID table. - CPU pinning:
cpuset.cpusrestricts a game to specific cores. This reduces cache thrashing between instances and is important for games with strict tick rates, like dedicated Source servers that run at 64 or 128 ticks per second.
These limits are enforced by the kernel, so they work even if the game is malicious or buggy. They also provide accounting: memory.current and cpu.stat tell you exactly how much each game used, which is invaluable for capacity planning.
What Cgroups Cannot Isolate: Kernel, Filesystem, Network, and Security
Despite their power, cgroups have hard limits. They do not provide:
- Kernel isolation: All games share the same kernel. A kernel panic or a vulnerability that escalates to root affects every cgroup. Cgroups cannot sandbox syscalls or hide kernel information.
- Filesystem isolation: A cgroup does not restrict which files a process can read or write. Without additional filesystem namespaces, any game can browse the host’s directories. You need chroot, containers, or VMs for that.
- Network isolation: Cgroups have no network controller. You cannot limit bandwidth per cgroup (that requires tc or net_cls, which is not a cgroup controller). You also cannot assign separate IPs or firewall rules per cgroup without network namespaces.
- Security isolation: Cgroups are not a security boundary. A process in one cgroup can send signals to, ptrace, or kill processes in another cgroup if they run as the same user. You must run each game under a separate UID (or use user namespaces) to prevent interference.
- GPU isolation: Cgroups do not manage GPU memory or compute. Tools like NVIDIA’s MPS or vGPU are required for GPU sharing.
This is why containers (which add namespaces) or VMs are needed for true multi-tenant isolation. Cgroups are a resource governor, not a sandbox.
How to Use Cgroups on a Shared Game Server (Practical Steps)
On a modern systemd-based distro, you rarely touch cgroup files directly. Instead, you use systemd slices or scopes. For a quick manual test, you can use systemd-run:
- Start a game with
systemd-run --scope -p MemoryMax=4G -p CPUQuota=200% ./game_server. This creates a transient scope with those limits. - To make limits permanent, create a systemd service file with
MemoryMax=4GandCPUQuota=200%under[Service]. - For legacy cgroups v1, use
cgcreateandcgsetfrom thecgroup-toolspackage, then launch withcgexec. - Monitor usage with
systemd-cgtopor read files under/sys/fs/cgroup/. For example,cat /sys/fs/cgroup/system.slice/yourgame.service/memory.current.
Common pitfalls: forgetting that CPUQuota is relative to one core (200% = 2 cores), not setting MemorySwapMax=0 to avoid swapping, and not setting TasksMax to limit threads. Also, on cgroups v2, you must enable controllers in the child cgroup by writing to cgroup.subtree_control — systemd does this automatically for its own slices, but manual cgroups require it.
Comparing Cgroups, Containers, and Virtual Machines
For shared game servers, the three main isolation levels are:
- Cgroups only: Lightest, lowest overhead (near zero), but no filesystem or network isolation. Best for trusted games or when you want to run many instances on one OS.
- Containers (Docker/LXC): Add namespaces for filesystem, PID, network, and UID. Each game sees its own root filesystem and network stack. Overhead is still low, but you must manage images and port mappings. Containers use cgroups for resource limits, so you still need the same cgroup knowledge.
- Virtual machines: Full kernel isolation. A game cannot crash the host kernel, and a VM escape is far less likely. Overhead is higher (each VM runs a full OS), but for untrusted games or Windows-only titles, VMs are the only safe option.
Many hosts use a hybrid: one VM per customer, and cgroups inside that VM to separate individual game worlds. This gives security and resource control without paying the full VM cost per game.
Common Problems and Misconceptions
One common misconception is that cgroups can prevent a game from seeing other processes. They cannot — ps still shows everything. Another is that cgroups limit network bandwidth; they do not. You need tc for that, and it is not cgroup-based (though you can use cgroup packet filters with net_cls in cgroups v1, it is not a true per-cgroup bandwidth cap).
A frequent mistake is setting a memory limit too low for a game that has a large world or many players. For example, a modded Minecraft server with 50 mods can easily use 6 GB. If you set memory.max to 4 GB, the kernel will OOM-kill it mid-save, corrupting the world. Always test with a realistic player count and monitor memory.peak (available in newer kernels) to set a safe limit.
Another issue is that CPU quotas can cause latency spikes if the quota is too low. A game that needs 3 cores but gets a quota of 2 will stutter. Use cpuset for latency-sensitive games instead of a quota, or set a quota high enough to cover peak usage.
Frequently Asked Questions
Can cgroups limit network bandwidth per game?
No. Cgroups do not have a network controller. You can use tc (traffic control) with classful qdiscs and match packets by cgroup ID (only in cgroups v1 with net_cls), but this is complex and not a direct cgroup feature. For practical per-game bandwidth limits, use a container with a virtual NIC and apply tc on that interface, or use a VM with its own NIC.
Do cgroups work on Windows game servers?
No. Cgroups are a Linux kernel feature. Windows has Job Objects, which provide similar CPU and memory limits, but the configuration and behavior differ. If you are running Windows games on Linux via Wine, cgroups still apply to the Wine process as a whole, not per-Windows-process.
Can I use cgroups to prevent a game from crashing the whole server?
For memory and CPU, yes. If a game exceeds its memory limit, the OOM killer kills that game’s processes, not others. For CPU, a quota prevents it from starving other processes. However, cgroups cannot prevent a game from crashing the kernel (e.g., via a kernel bug) or from filling the disk (use filesystem quotas for that).
Do I need root to create cgroups?
On cgroups v2, creating a cgroup and setting limits requires root (or CAP_SYS_ADMIN). Non-root users can be delegated a sub-hierarchy (e.g., via systemd’s Delegate=yes in a user service), but that is advanced. Most game hosts run their servers as root or under a systemd service, so this is usually not a problem.
What is the difference between cgroups v1 and v2 for game servers?
Cgroups v2 (default on modern distros) has a unified hierarchy, meaning you cannot mount controllers separately. It also has a cleaner interface (e.g., memory.max instead of memory.limit_in_bytes) and supports memory.peak for tracking high-water marks. Some older tools like cgcreate do not support v2; use systemd or direct file writes instead. For game servers, v2 is preferred because it allows better memory accounting and avoids the confusion of multiple hierarchies.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Philips DST7060/20 7000 Series Iron: Specs & Fit
- Coal Fueled Jet Aircraft: Could It Work?675 L
- Remote Desktop on Raspberry Pi: How to Enable It
- Word Select Last Line in Paragraph?
- Google Assistant IFTTT Recipes: 7 Useful Automations
- OLED TVs in Dark Rooms: Why They Look Better and When They Don’t