Skip to content
LinuxHow-To Published Updated 5 min readViews unavailable

How to Tune Kernel Parameters on Linux with sysctl

A complete walkthrough reading, changing, and persisting kernel runtime parameters — with a few of the most commonly tuned examples explained, not just listed.

sysctl is the standard interface for reading and changing Linux kernel parameters at runtime — the same /proc/sys tree covered elsewhere on this blog, accessed through a purpose-built command instead of raw file reads and writes.

Step 1: view a specific parameter’s current value

sysctl net.ipv4.ip_forward

Every sysctl parameter name maps directly to a path under /proc/sysnet.ipv4.ip_forward corresponds to /proc/sys/net/ipv4/ip_forward, with dots replacing slashes.

Step 2: list every currently available parameter

sysctl -a

This is a long list — hundreds of tunable parameters across networking, virtual memory, kernel scheduling, and more — worth knowing exists even if you only ever look up specific ones you need.

Step 3: change a parameter temporarily (until reboot)

sudo sysctl -w net.ipv4.ip_forward=1

Changes made this way take effect immediately but don’t survive a reboot — useful for testing a change before committing to it permanently.

Step 4: persist a change permanently

# /etc/sysctl.conf, or a file in /etc/sysctl.d/
net.ipv4.ip_forward = 1
sudo sysctl -p

sysctl -p reloads settings from the configuration file immediately, without requiring a reboot to apply a persisted change.

Step 5: a commonly tuned example — increasing the file descriptor ceiling

fs.file-max = 2097152

Relevant when running services that need far more open file descriptors than the conservative default supports — see fixing ‘too many open files’ errors for the full troubleshooting path this setting is part of.

Step 6: a commonly tuned example — adjusting swap aggressiveness

vm.swappiness = 10

vm.swappiness (0–100) controls how aggressively the kernel prefers swapping out memory versus reclaiming page cache — lowering it from the default (typically 60) is a common tweak on systems with plenty of RAM where any swapping at all causes a noticeable performance hit.

Step 7: a commonly tuned example — network buffer sizes for high-throughput workloads

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

Relevant for high-bandwidth or high-latency network connections, where the default socket buffer sizes limit achievable throughput regardless of available bandwidth.

Step 8: verify a change actually took effect

sysctl net.core.rmem_max
cat /proc/sys/net/core/rmem_max

Both commands should agree — sysctl is just a friendlier interface over the same underlying /proc/sys values.

Why understanding what you’re changing matters more than copying a tuning guide

Sysctl parameters exist because the kernel’s defaults represent a reasonable general-purpose tradeoff — changing them shifts that tradeoff in a specific direction for a specific workload, not a universal improvement. Copying a list of “performance tuning” sysctl values from a guide without understanding what each one actually trades off is how systems end up with settings tuned for a completely different workload than the one actually running on them — worth understanding the specific problem each parameter addresses before changing it, rather than treating tuning guides as universally applicable defaults.

Step 9: understand file ordering when multiple sysctl.d files set the same parameter

sysctl --system

Rather than one single /etc/sysctl.conf, current systemd-based distributions read from several locations — /etc/sysctl.d/*.conf, /run/sysctl.d/*.conf, /usr/lib/sysctl.d/*.conf, and the legacy /etc/sysctl.conf — processed in a specific defined order, with later files overriding earlier ones for the same parameter name. sysctl --system (rather than the older sysctl -p alone) applies all of these in their correct precedence order and, critically, prints exactly which file supplied the final effective value for each parameter — genuinely useful for tracking down a setting that appears correctly configured in one file but isn’t actually taking effect because a different file loaded later is silently overriding it.

Step 10: a security-relevant example — hardening against IP spoofing and SYN floods

net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1

rp_filter (reverse path filtering) rejects incoming packets whose source address couldn’t plausibly have arrived via the interface they came in on — a real defense against a category of IP spoofing, though worth disabling per-interface on hosts doing asymmetric routing where legitimate traffic can genuinely violate the check. tcp_syncookies lets the kernel handle a SYN flood by encoding connection state into the SYN-ACK sequence number itself, rather than allocating a real half-open connection slot per attempt — avoiding the connection-table exhaustion a SYN flood is specifically designed to cause. Both are commonly enabled by default on current distributions, but worth confirming explicitly rather than assuming, particularly on a system whose defaults were set by an older installation image.

Step 11: a stability example — controlling how eagerly the kernel kills processes under memory pressure

vm.overcommit_memory = 0
vm.oom_kill_allocating_task = 0

overcommit_memory controls whether the kernel allows processes to allocate more virtual memory than is actually physically backable, betting that not every allocated page will actually be used simultaneously — mode 0 (the default heuristic) is reasonable for most workloads, while mode 2 (strict accounting, no overcommit) trades away that flexibility for predictability on systems where an unexpected OOM kill is worse than an allocation failing outright and being handled explicitly by the application. This is exactly the kind of parameter where “the default is wrong for my workload” requires actually understanding what tradeoff the default represents, not just following a generic tuning checklist.

Related:

Sources:

Comments