How to Configure Default Resource Limits for Systemd User Slices Using CGroups


2 views

When working with multi-user Linux systems, Systemd creates transient user-(UID).slice units for each logged-in user. These slices form the parent cgroup hierarchy for all user processes. By default, these automatically generated slices inherit basic configurations without strict resource constraints.

While you can override settings per-user with individual user-1000.slice files, maintaining consistent default limits across all users requires deeper Systemd integration. The transient nature of these slices (generated in /run/systemd/system/) makes template-based configuration impossible through conventional drop-in files.

Method 1: Global User Slice Configuration

Edit the base user.slice to affect all descendants:

# /etc/systemd/system/user.slice.d/90-resource-limits.conf
[Slice]
CPUQuota=150%
MemoryHigh=4G
MemoryMax=6G
TasksMax=5000

Method 2: Systemd System-Wide Drop-In

Create a system-wide configuration that applies to all user slices:

# /etc/systemd/system.conf.d/10-user-defaults.conf
DefaultCPUAccounting=yes
DefaultMemoryAccounting=yes
DefaultTasksAccounting=yes
DefaultTasksMax=2000

UID-Based Conditional Application

For more granular control, create a generator that writes slice files dynamically:

#!/bin/bash
# /usr/local/bin/user-slice-generator

UID_MIN=$(grep -E '^UID_MIN' /etc/login.defs | awk '{print $2}')
UID_MAX=$(grep -E '^UID_MAX' /etc/login.defs | awk '{print $2}')

for (( uid=UID_MIN; uid<=UID_MAX; uid++ )); do
  mkdir -p "/run/systemd/system/user-${uid}.slice.d"
  cat > "/run/systemd/system/user-${uid}.slice.d/90-resource-limits.conf" << EOF
[Slice]
MemoryMax=$(($uid % 100 * 100))M
CPUQuota=$(($uid % 10 * 10 + 100))%
EOF
done

After applying changes, verify with:

systemctl daemon-reload
systemd-cgtop
systemd-cgls

For specific user monitoring:

systemd-cgtop -u user-1000.slice
cat /sys/fs/cgroup/user.slice/user-1000.slice/cpu.max
  • Changes to system.conf require full system reboot
  • Memory limits use hierarchical accounting (child cgroups can't exceed parent)
  • CPU quotas operate on relative shares (100%=1 core)
  • Transient units don't persist across reboots

When attempting to impose per-user resource limits via systemd's cgroup integration, we encounter several architectural constraints. The transient nature of user.slice instances presents particular configuration challenges:

# Typical auto-generated user slice (example for UID 1001)
$ systemctl cat user-1001.slice
# /run/systemd/system/user-1001.slice
[Slice]
MemoryHigh=8G
CPUQuota=200%

While systemd doesn't provide direct templating for user slices, we can implement persistent configurations through several methods:

Method 1: Drop-in Configuration Files

Create directory structure in /etc/systemd/system:

sudo mkdir -p /etc/systemd/system/user-.slice.d
sudo vim /etc/systemd/system/user-.slice.d/90-defaults.conf

Example configuration:

[Slice]
MemoryHigh=4G
CPUQuota=150%
TasksMax=5000
IOWeight=100

Method 2: UID-Specific Overrides

For special cases requiring user-specific limits:

sudo systemctl edit user-1000.slice

Sample override:

[Slice]
MemoryHigh=12G
CPUQuota=300%
AllowedCPUs=0-3

Configure /etc/systemd/logind.conf for system-wide defaults:

[Login]
UserTasksMax=10000
DefaultMemoryHigh=6G
DefaultCPUQuota=180%

Check applied limits with:

systemd-cgls -u user-1000.slice
systemctl show user-1000.slice --property MemoryHigh,CPUQuota

For deeper inspection:

cat /sys/fs/cgroup/user.slice/user-1000.slice/cpu.max
cat /sys/fs/cgroup/user.slice/user-1000.slice/memory.high

Here's a complete deployment script for a multi-user system:

#!/bin/bash
# Set system-wide defaults
echo "Configuring base limits..."
cat > /etc/systemd/system/user-.slice.d/90-base.conf < /etc/systemd/system/user-1001.slice.d/10-developer-override.conf <

When implementing these configurations in production:

  • Test limits in staging environments first
  • Monitor systemd journal for cgroup-related errors
  • Consider combining with pam_limits for session-level constraints
  • Document all overrides for maintainability