Skip to content

Tuning the Kernel With sysctl


Writing directly to /proc/sys works, but it has two real limitations: you need to remember the exact path for every parameter, and the change vanishes the moment the system reboots. sysctl is the dedicated tool built to solve both problems — a proper interface for reading and writing the same kernel tunables, plus a real mechanism for making a change stick permanently.

Reading Values: sysctl -a And Direct Lookups

sysctl -a

Lists every currently readable kernel parameter and its value — a genuinely enormous list, rarely something you’d browse in full, but useful to know exists when you’re not sure of a parameter’s exact name.

To check one specific value:

sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0

The Naming Pattern: Dots Instead Of Slashes

Notice that net.ipv4.ip_forward corresponds exactly to /proc/sys/net/ipv4/ip_forward — the file path from the procfs chapter, with slashes replaced by dots and the /proc/sys/ prefix dropped entirely. Every sysctl parameter name follows this same mechanical transformation, which means if you ever encounter an unfamiliar path under /proc/sys, you already know its sysctl name without needing to look it up separately, and vice versa.

Making A Runtime Change: sysctl -w

sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

This does exactly what writing directly to /proc/sys would have done — the same immediate, in-memory kernel change — just through a cleaner interface that doesn’t require remembering the underlying file path or reaching for tee to write as root. Like the direct-write approach, though, this still doesn’t survive a reboot on its own.

Making It Persistent: /etc/sysctl.d/

Permanent kernel tunable changes belong in configuration files, applied automatically at every boot by a dedicated systemd service. The main file is /etc/sysctl.conf, but the better practice — following the same pattern already seen with rsyslog.d and logrotate.d — is a dedicated file under /etc/sysctl.d/ instead of editing the main file directly:

sudo nano /etc/sysctl.d/99-custom.conf
net.ipv4.ip_forward = 1
vm.swappiness = 10

Syntax here is simple: parameter name, =, value, one per line. The 99- prefix is a convention, not a requirement — files in this directory are processed in filename order, and a high number like 99 ensures your custom settings are applied last, after anything else that might set related defaults earlier in the sequence.

Applying A Config File Without Rebooting

Just like /etc/fstab had mount -a for testing without a reboot, sysctl configuration has an equivalent:

sudo sysctl -p /etc/sysctl.d/99-custom.conf

This reads and immediately applies every setting in that specific file, right now — the same discipline of testing a configuration change live rather than simply trusting it and waiting for the next reboot to find out if it worked.

To reload everything from every standard configuration location at once, rather than one file at a time:

sudo sysctl --system

This processes /etc/sysctl.conf, everything under /etc/sysctl.d/, and a couple of other standard locations, applying all of it in the correct order — genuinely the more common command to reach for after making any change, since it guarantees nothing gets missed.

A Few Genuinely Common Real-World Tunables

net.ipv4.ip_forward — whether this machine forwards IP packets between interfaces. Needs to be 1 for any machine acting as a router or gateway; 0 (the default) is correct for an ordinary server or workstation that shouldn’t be routing traffic on behalf of anything else.

vm.swappiness — how aggressively the kernel favors swapping memory out to disk versus keeping it in RAM, on a scale from 0 to 100. A server running a database, where you generally want the kernel to avoid swapping as long as possible, might set this considerably lower than the default (commonly 60) — 10, for instance — to keep more in physical memory before resorting to swap.

fs.file-max — the system-wide maximum number of open file descriptors allowed at once. A busy server running many concurrent connections or processes can genuinely hit this ceiling, at which point new files simply fail to open system-wide until something closes existing ones.

net.core.somaxconn — the maximum length of the queue for pending incoming network connections. A busy server accepting a high rate of new connections can benefit from raising this above its fairly conservative default, reducing the chance of connections being refused during a sudden burst of traffic.

Best Practices

Avoid editing /etc/sysctl.conf directly. A dedicated file under /etc/sysctl.d/ keeps your customizations clearly separated, easier to review, and easier to remove cleanly later without hunting through a larger shared file.

Comment your changes. A sysctl.d file with no explanation for why a non-default value was chosen is exactly the kind of thing a future administrator (quite possibly yourself, months later) will be hesitant to touch or remove, unsure whether it’s still needed.

Test with sysctl -p or --system before assuming a change works, exactly the same discipline emphasized for /etc/fstab earlier in this course — confirm live, don’t just trust a config file and wait for the next reboot to find out.

Warning

Kernel tunables aren’t purely performance knobs — some have genuine security implications. Disabling certain network-related protections (like source address validation, controlled by other net.ipv4 parameters not covered individually here) to “fix” a networking issue can inadvertently weaken the system against spoofing-based attacks. Understand what a parameter actually controls before changing it, rather than changing values based on a forum post promising a performance improvement without explaining the tradeoff.

What’s Next

You can now read, test, and permanently configure kernel behavior through the proper, supported interface. The next chapter rounds out the virtual filesystem landscape with a focused look at a few more you’ll encounter on any running system — tmpfs, devtmpfs, and cgroupfs.

Last updated on