08 · Kernel Tuning: sysctl & /proc Parameters¶
Level 1 introduced /proc and /sys as windows into live kernel state, most of it read-only. sysctl is the
dedicated, friendlier interface to the writable subset of that state — kernel-tunable parameters you can read,
change instantly on a running system, and optionally make persistent across reboots, all without recompiling or
rebooting anything.
sysctl is just a nicer path to /proc/sys¶
Every sysctl parameter has a direct filesystem equivalent under /proc/sys/, with dots in the sysctl name
becoming slashes in the path: net.ipv4.ip_forward is exactly /proc/sys/net/ipv4/ip_forward. sysctl the
command is a convenience layer — nicer names, batch reading, and crucially, support for persisting a setting
across reboots via config files — but reading or writing the /proc/sys file directly has the identical, immediate
effect, because that's literally the same kernel interface underneath.
Worked example: a sysctl change taking effect live, no reboot¶
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
$ cat /proc/sys/net/ipv4/ip_forward
0
$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
$ cat /proc/sys/net/ipv4/ip_forward
1
(Real output from this course's lab VM.) net.ipv4.ip_forward controls whether this machine's kernel will route
packets between interfaces at all (the difference between "an endpoint" and "a router") — flipping it from 0
to 1 with sysctl -w takes effect immediately, confirmed by reading the raw /proc/sys file right
afterward: no service restart, no reboot, the kernel's packet-forwarding behavior genuinely changed the instant
the write happened.
Worked example: real persistent configuration¶
$ ls /etc/sysctl.d/
99-cloudimg-ipv6.conf 99-lima.conf README.sysctl
$ cat /etc/sysctl.d/99-lima.conf
kernel.unprivileged_userns_clone=1
net.ipv4.ping_group_range = 0 2147483647
net.ipv4.ip_unprivileged_port_start=0
(Real output — this is this VM's actual boot-time sysctl configuration, not an illustration.) 99-lima.conf
exists because this VM needs settings most default installs don't: kernel.unprivileged_userns_clone=1 lets an
unprivileged user create user namespaces (Lesson 7's unshare demo, and anything Lima/container tooling needs,
depend on this), and net.ipv4.ip_unprivileged_port_start=0 lowers the normally-root-only privileged port
threshold (ports below 1024 traditionally require root to bind) all the way to 0, so an unprivileged process
inside this VM can bind even classic "privileged" ports like 80 or 443 directly — a deliberate, specific
relaxation this VM's environment needed, not a universal default.
How It Actually Works¶
Numbered filename prefixes (99-lima.conf) in /etc/sysctl.d/ aren't decorative — sysctl reads every file in
that directory in lexical filename order and applies them in sequence, so a later-processed file's setting for
the same key wins over an earlier one; the convention of prefixing with numbers (lower numbers processed first,
so they can be safely overridden by higher-numbered, more specific files) exists to make override order
predictable without needing to read every file's content to know which one "wins." This is the same pattern
/etc/apt/apt.conf.d/, systemd drop-in directories, and many other Linux configuration systems use — a
deliberate design convention, not something specific to sysctl.
Not every kernel parameter can be changed live this way. Some are genuinely runtime-adjustable (like
ip_forward, which the kernel can safely act on differently from one packet to the next); others only take
effect at boot or module-load time and are exposed read-only or write-once (a parameter's own documentation, or
simply trying a write and checking the result, is the way to find out which kind you're dealing with — there's
no single flag in the output distinguishing them). This matters because tuning guides sometimes suggest a
sysctl -w change "to test it," and for boot-time-only parameters that test is silently meaningless — the write
may succeed without the running kernel actually behaving differently until the next boot.
Common mistakes¶
- Changing a sysctl live with
sysctl -wand forgetting it reverts on reboot. Unless the same value is also written into a file under/etc/sysctl.d/(andsysctl --systemor a reboot applies it), a live change is temporary — a classic source of "it worked yesterday and now it's back to broken" confusion after a maintenance reboot. - Editing multiple sysctl.d files with conflicting settings for the same key and not checking processing
order. As covered above, lexical filename order decides the winner —
sysctl --systemwith verbose output shows exactly which file's value for each key was actually applied last. - Assuming a networking sysctl change takes effect for already-established connections. Many networking parameters (buffer sizes, certain TCP behaviors) only apply to new connections or sockets created after the change — existing ones keep whatever was in effect when they were created.
Exercise¶
Run sysctl vm.swappiness and sysctl net.ipv4.ip_forward on a Linux machine you control, and read both values'
meanings from the kernel documentation. Then check /etc/sysctl.d/ for any files already there, read what each
one changes and why (often there's a comment explaining the reason), and identify whether any of them rely on the
filename-ordering behavior to override an earlier file's setting.