The most surprising thing about sysctl.d is that it’s not really about setting kernel parameters at all; it’s about telling systemd how to set them for you, and doing so in a way that’s both organized and persistent.

Let’s see it in action. Imagine you want to tune your network stack for better performance, perhaps by increasing the maximum number of open TCP connections. Normally, you’d use sysctl -w net.core.somaxconn=4096. This change is immediate but temporary; it’ll be gone on reboot. To make it persistent, you’d traditionally edit /etc/sysctl.conf or add a file in /etc/sysctl.d/.

Here’s how systemd handles it.

First, create a configuration file. Let’s call it /etc/sysctl.d/99-network-tuning.conf. The 99- prefix is important; it dictates the order of loading, with higher numbers loading later and potentially overriding earlier settings.

# /etc/sysctl.d/99-network-tuning.conf
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096

Now, how does systemd know to apply this? It’s not magic. systemd has a built-in service, systemd-sysctl.service, which is designed specifically for this. When your system boots, systemd-sysctl.service is triggered. It scans all files in /etc/sysctl.d/ (and /usr/lib/sysctl.d/ for package-provided defaults, and /run/sysctl.d/ for runtime-generated settings), sorts them by their filename prefixes, and then applies each key = value pair using the sysctl() system call.

You can see this in the systemd unit file itself, typically found at /usr/lib/systemd/system/systemd-sysctl.service. It’s a simple service that runs a command:

[Unit]
Description=Apply Kernel Indexes
Documentation=man:systemd-sysctl.service(8) man:sysctl.d(5)
ConditionNeedsTerminfo=false

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/systemd-sysctl

The ExecStart=/usr/sbin/systemd-sysctl command is the key. The systemd-sysctl binary is what actually reads the .conf files and applies the settings.

To verify that your settings are applied, you can use the sysctl command directly:

sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog

If you want to see what systemd-sysctl would do without actually applying it, you can run systemd-sysctl --dry-run. This is invaluable for testing your configuration files before committing them.

sudo systemd-sysctl --dry-run

This command will list all the settings it would apply, along with the source file for each.

The beauty here is that systemd centralizes this management. Instead of needing to remember to add entries to /etc/sysctl.conf and then manually run sysctl -p after making changes, systemd handles the persistence and application automatically on boot. You can also trigger it manually to apply all settings from the .d directories:

sudo systemctl restart systemd-sysctl.service

This command will re-read all the sysctl.d files and apply any changes, similar to sysctl -p but respecting the systemd ordering and management.

The sysctl.d directory structure is also designed for modularity. Distribution packages can drop their own tuned parameters into /usr/lib/sysctl.d/, and system administrators can override or add their own in /etc/sysctl.d/. Files in /etc/sysctl.d/ will take precedence over those in /usr/lib/sysctl.d/ if they have the same name, and the numerical prefix ensures a predictable application order. For example, a package might put network-related defaults in /usr/lib/sysctl.d/50-network.conf, and you could override specific values in /etc/sysctl.d/90-my-network-overrides.conf.

One subtle but important point is how systemd-sysctl handles changes. When you run systemctl restart systemd-sysctl.service or when it runs at boot, it doesn’t just apply new settings. It also attempts to revert settings that are no longer present in the configuration files. This is managed by the RemainAfterExit=yes in the service file. If a parameter was set by systemd-sysctl and is removed from the configuration, systemd-sysctl will try to set it back to its previous value. However, determining the "previous" value can be complex, and often it reverts to a system default or a value set earlier in the boot process. It’s generally safer to explicitly set parameters back to a known default if you intend to remove them from your sysctl.d configuration.

The next step in kernel parameter management is understanding how these settings interact with cgroups, where resource limits can be applied more granularly to specific processes or services.

Want structured learning?

Take the full Systemd course →