Linux Sysctl Tuning: Kernel Parameter Optimization Guide

Linux Sysctl Tuning: Kernel Parameter Optimization Guide

Arjun’s Systems Brief: I have spent the better part of a decade tuning Linux systems for production workloads. Sysctl is the single most underused tool in the average administrator’s toolkit. Most people know about vm.swappiness and that is where their knowledge ends. This guide covers what actually matters across Ubuntu, Fedora, and Arch-based systems.

Every performance-tuned Linux system uses sysctl. Whether you are running a high-traffic web server, a container host, or a development workstation, the kernel parameters exposed through /proc/sys/ control how your system handles memory, networking, security, and file I/O. Getting these wrong means wasted resources. Getting them right means your system actually performs the way the hardware was designed to deliver. If you are new to Linux performance tuning, our guide on speeding up Ubuntu covers the basics before diving into kernel-level adjustments.

I wrote this guide because most sysctl tutorials only cover Ubuntu and stop at swappiness. That is not good enough. If you manage mixed environments, you need to understand the differences between distributions. Fedora defaults to different security parameters than Ubuntu. CachyOS tunes aggressively for desktop performance. These differences matter when you are writing configuration that needs to work across your fleet.

What Is sysctl and Why Does It Matter

Sysctl is a Linux utility that reads and modifies kernel parameters at runtime. These parameters control everything from how aggressively the kernel swaps memory pages to how your network stack handles TCP connections. The tool interfaces with /proc/sys/, a virtual filesystem that exposes kernel tunables as plain text files.

The reason sysctl matters is simple. Linux defaults are conservative. They are designed to work on everything from a Raspberry Pi to a mainframe. That means they are leaving performance on the table for your specific workload. A database server has different memory needs than a desktop. A web server handling 10,000 concurrent connections needs different network buffers than a laptop browsing the web.

Pro Tip: Never tune sysctl parameters without understanding what they control. The kernel documentation at /usr/share/doc/linux-doc/ or man 5 sysctl explains each parameter. I have seen systems crash because someone set vm.overcommit_memory to 2 without understanding the implications.

Reading and Writing Kernel Parameters

Reading sysctl parameters is straightforward. Use sysctl -a to list every available parameter and its current value. This produces a long output, so pipe it through grep to find what you need.

fosslinux@ubuntu:~$ sysctl net.core.somaxconn
net.core.somaxconn = 4096

Writing parameters temporarily uses the -w flag. This change persists until the next reboot.

fosslinux@ubuntu:~$ echo 'fosslinux' | sudo -S sysctl -w net.core.somaxconn=1024
net.core.somaxconn = 1024

You can also read parameters directly from the proc filesystem. This is useful in scripts where you want to avoid the sysctl binary overhead.

fosslinux@ubuntu:~$ cat /proc/sys/net/core/somaxconn
4096

Insight: The /proc/sys/ path uses slashes as separators (net/core/somaxconn), while sysctl uses dots (net.core.somaxconn). They are the same parameter accessed different ways.

How Linux Distributions Handle sysctl Persistence

This is where distributions diverge significantly, and it is the source of most confusion. There are two mechanisms for making sysctl changes permanent: the legacy /etc/sysctl.conf file and the modern /etc/sysctl.d/ drop-in directory.

The Legacy Approach: /etc/sysctl.conf

Ubuntu 26.04 does not even ship with an /etc/sysctl.conf file. Fedora creates it but leaves it empty, symlinking it to /etc/sysctl.d/99-sysctl.conf for backward compatibility. The old approach of dumping all your customizations into one monolithic file is deprecated.

fosslinux@ubuntu:~$ ls -la /etc/sysctl.conf
ls: cannot access '/etc/sysctl.conf': No such file or directory

The Modern Approach: sysctl.d/ Drop-in Files

The recommended approach is creating numbered drop-in files in /etc/sysctl.d/. The naming convention matters: files are loaded in lexicographic order, so 50-tuning.conf loads before 99-custom.conf. This lets you override distro defaults cleanly.

fosslinux@ubuntu:~$ ls /etc/sysctl.d/
README.sysctl

fosslinux@ubuntu:~$ ls /usr/lib/sysctl.d/
10-apparmor.conf    50-default.conf     55-bufferbloat.conf
50-pid-max.conf     55-console-messages.conf

To create a custom tuning file, place it in /etc/sysctl.d/ with a number higher than the distro defaults.

fosslinux@ubuntu:~$ echo 'fosslinux' | sudo -S bash -c 'cat > /etc/sysctl.d/99-custom-tuning.conf << EOF
# Custom performance tuning
net.core.somaxconn = 65535
vm.swappiness = 10
vm.dirty_ratio = 15
EOF'

CachyOS takes this further with its own tuning file at /usr/lib/sysctl.d/70-cachyos-settings.conf that applies aggressive performance defaults.

fosslinux@cachyos:~$ cat /usr/lib/sysctl.d/70-cachyos-settings.conf | head -15

Why It Matters: If you are writing sysctl configuration for mixed environments, always use the drop-in file approach. Ubuntu 26.04 will ignore /etc/sysctl.conf entirely. Fedora will honor it through the symlink. Arch-based systems like CachyOS expect drop-in files. Using the modern approach works everywhere.

Networking Parameters That Actually Matter

Networking is where sysctl tuning delivers the most visible performance improvements. I tune these parameters on every server I deploy.

net.core.somaxconn: Connection Queue Depth

This parameter controls the maximum length of the socket listen queue. If you run a web server or any application that accepts many concurrent connections, the default value is almost always too low.

fosslinux@ubuntu:~$ sysctl net.core.somaxconn
net.core.somaxconn = 4096

On Ubuntu 26.04, the default is 4096. On older systems, it might be 128. For a production web server, I set this to 65535. The kernel will not actually use more memory for larger values, it just allows more pending connections during traffic spikes.

net.ipv4.tcp_tw_reuse: TIME_WAIT Socket Recycling

When a TCP connection closes, the socket enters a TIME_WAIT state for 60 seconds. On high-traffic servers, you can exhaust available ports. The tcp_tw_reuse parameter allows the kernel to reuse TIME_WAIT sockets for new connections when it is safe to do so.

fosslinux@ubuntu:~$ sysctl net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_reuse = 2

The value of 2 means the kernel uses a loopback-aware algorithm that is safe for most workloads. I never set this to 1 (global reuse) because it can cause issues with certain firewall configurations.

TCP Buffer Sizes

The TCP buffer parameters control how much memory the kernel allocates for send and receive operations. These three values represent the minimum, default, and maximum buffer sizes in bytes.

fosslinux@ubuntu:~$ sysctl net.ipv4.tcp_rmem
net.ipv4.tcp_rmem = 4096  131072  26265952

fosslinux@ubuntu:~$ sysctl net.ipv4.tcp_wmem
net.ipv4.tcp_wmem = 4096  16384  4194304

Notice the difference between Ubuntu and Fedora here. Fedora allocates a higher maximum receive buffer (33554432 vs 26265952 on Ubuntu). This is one of those distribution-specific defaults that can trip you up when writing cross-distro configuration.

net.ipv4.ip_local_port_range

This defines the ephemeral port range for outgoing connections. If your server makes many outbound connections (load balancer, proxy, database connection pooler), expanding this range prevents port exhaustion.

fosslinux@ubuntu:~$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768  60999

Worth Knowing: The tcp_tw_reuse parameter only affects outbound connections. It has no effect on incoming connections. If your server is a listener (web server, database), this parameter will not help with TIME_WAIT accumulation from client disconnections.

Memory Tuning: When Defaults Are Not Enough

Memory parameters control how the kernel manages RAM, swap, and page cache. Getting these wrong can cause performance cliffs that are difficult to diagnose.

vm.swappiness: Swap Aggressiveness

This is the most commonly tuned sysctl parameter, and also the most misunderstood. Swappiness controls how aggressively the kernel moves anonymous memory pages to swap.

fosslinux@ubuntu:~$ sysctl vm.swappiness
vm.swappiness = 60

fosslinux@cachyos:~$ sysctl vm.swappiness
vm.swappiness = 150

Notice that CachyOS sets swappiness to 150. This is intentional. CachyOS is tuned for desktop responsiveness where you want the kernel to use swap proactively to keep more RAM available for the page cache, which speeds up file operations. On a server with abundant RAM, I typically set this to 10 or even 1.

vm.dirty_ratio and vm.dirty_background_ratio

These parameters control when the kernel starts writing dirty (modified) pages to disk. The dirty_ratio sets the percentage of memory that can be dirty before processes are forced to write. The dirty_background_ratio triggers background writeback earlier.

fosslinux@ubuntu:~$ sysctl vm.dirty_ratio vm.dirty_background_ratio
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10

fosslinux@cachyos:~$ sysctl vm.dirty_ratio vm.dirty_background_ratio
vm.dirty_ratio = 0
vm.dirty_background_ratio = 0

CachyOS shows zero for both ratios because it uses byte-based limits instead. Check vm.dirty_bytes and vm.dirty_background_bytes on CachyOS.

fosslinux@cachyos:~$ sysctl vm.dirty_bytes vm.dirty_background_bytes
vm.dirty_bytes = 268435456
vm.dirty_background_bytes = 67108864

This means CachyOS allows up to 256MB of dirty pages before forcing writeback, and starts background writeback at 64MB. The byte-based approach is more predictable on systems with varying amounts of RAM.

vm.vfs_cache_pressure

This parameter controls how aggressively the kernel reclaims memory used for directory and inode caching. Lower values keep caches around longer, which speeds up file operations.

fosslinux@ubuntu:~$ sysctl vm.vfs_cache_pressure
vm.vfs_cache_pressure = 100

fosslinux@cachyos:~$ sysctl vm.vfs_cache_pressure
vm.vfs_cache_pressure = 50

CachyOS sets this to 50, meaning it is half as aggressive about reclaiming file caches compared to Ubuntu. This is another desktop-optimization decision that keeps frequently accessed files cached longer.

Security Hardening Through sysctl

Several sysctl parameters provide network-level security hardening. These are often overlooked but can prevent common attack vectors.

net.ipv4.conf.all.rp_filter: Reverse Path Filtering

Reverse path filtering verifies that incoming packets arrive through the interface the kernel would use to respond. This prevents IP spoofing attacks.

fosslinux@ubuntu:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 2

fosslinux@fedora:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 0

fosslinux@cachyos:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1

This is a critical difference. Fedora defaults to 0 (disabled), Ubuntu uses 2 (loose mode), and CachyOS uses 1 (strict mode). For security, I recommend setting this to 1 on all systems.

ICMP and Redirect Protection

These parameters reduce attack surface by ignoring potentially malicious ICMP traffic and redirect messages.

fosslinux@ubuntu:~$ sysctl net.ipv4.conf.all.accept_redirects net.ipv4.icmp_echo_ignore_broadcasts net.ipv4.tcp_syncookies
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1

Notice that Fedora has accept_redirects = 1, which allows ICMP redirects. This is less secure than Ubuntu and CachyOS defaults. On production servers, I always set this to 0.

Recommended Security Profile

Here is the security hardening configuration I apply to production servers.

fosslinux@ubuntu:~$ cat /etc/sysctl.d/99-security.conf
# Security hardening
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1

Applying Changes Without Reboot

One of sysctl’s biggest advantages is that most parameters can be changed at runtime without rebooting. There are three methods, and I use all three depending on the situation.

Method 1: Apply All Drop-in Files

The --system flag reads and applies every file in /etc/sysctl.d/ and /usr/lib/sysctl.d/. This is what I run after deploying a new configuration.

fosslinux@ubuntu:~$ echo 'fosslinux' | sudo -S sysctl --system

Method 2: Apply a Specific File

Use -p to apply changes from a single file. This is useful for testing changes without affecting other parameters.

fosslinux@ubuntu:~$ echo 'fosslinux' | sudo -S sysctl -p /etc/sysctl.d/99-custom-tuning.conf

Method 3: Apply a Single Parameter

For quick changes during troubleshooting, apply a single parameter with the -w flag.

fosslinux@ubuntu:~$ echo 'fosslinux' | sudo -S sysctl -w vm.swappiness=10
vm.swappiness = 10

Remember that the -w flag only applies until the next reboot. To make it permanent, add it to a drop-in file.

Common Tuning Recipes

Here are configurations I use regularly. Copy them, adjust the values for your workload, and test before deploying to production.

Web Server Profile

fosslinux@ubuntu:~$ cat /etc/sysctl.d/99-web-server.conf
# Web server tuning
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 2
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.ip_local_port_range = 1024 65535

Database Server Profile

fosslinux@ubuntu:~$ cat /etc/sysctl.d/99-database.conf
# Database server tuning
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
vm.min_free_kbytes = 65536
fs.file-max = 2097152

Desktop Workstation Profile

fosslinux@ubuntu:~$ cat /etc/sysctl.d/99-desktop.conf
# Desktop responsiveness tuning
vm.swappiness = 60
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.vfs_cache_pressure = 100
fs.inotify.max_user_watches = 524288

Distro-Specific Defaults Reference

Understanding default values across distributions helps you write configuration that works everywhere. Here is a comparison table based on the VMs I tested.

Parameter Ubuntu 26.04 Fedora 44 CachyOS
net.core.somaxconn 4096 4096 4096
vm.swappiness 60 60 150
net.ipv4.tcp_tw_reuse 2 2 2
vm.dirty_ratio 20 20 0 (uses bytes)
vm.vfs_cache_pressure 100 100 50
net.ipv4.conf.all.rp_filter 2 0 1
net.ipv4.tcp_keepalive_time 7200 7200 120
fs.file-max 9223372036854775807 9223372036854775807 2097152

Frequently Asked Questions

Is it safe to change sysctl parameters at runtime?

Most parameters can be changed safely. The kernel validates new values and rejects invalid ones. However, some parameters (like vm.overcommit_memory) can cause problems if set incorrectly. Always test on a non-production system first and monitor your system after applying changes.

How do I know which parameters to tune for my workload?

Start with monitoring. Use vmstat, iostat, and sar to identify bottlenecks. If you see high swap usage, tune memory parameters. If you see connection timeouts, tune networking parameters. Never tune blindly based on someone else’s configuration.

Do sysctl changes survive a kernel upgrade?

Yes. Custom drop-in files in /etc/sysctl.d/ survive kernel upgrades because they are not part of the kernel package. However, distribution upgrades may overwrite files in /usr/lib/sysctl.d/. Always keep your customizations in /etc/sysctl.d/.

Can I use sysctl.d/ on older systems?

The sysctl.d/ mechanism has been supported since systemd 197 (2013). All current LTS distributions support it. If you are running something older than Ubuntu 16.04 or RHEL 7, you may need to stick with /etc/sysctl.conf.

What is the difference between dirty_ratio and dirty_bytes?

dirty_ratio sets the limit as a percentage of total RAM. dirty_bytes sets it as an absolute byte count. The byte-based approach is more predictable on systems with varying RAM sizes. If both are set, the byte-based parameter takes precedence (as CachyOS demonstrates).

How do I revert a sysctl change?

Remove the parameter from your drop-in file and run sudo sysctl --system to reload. For temporary changes made with sysctl -w, a reboot restores defaults. You can also set the parameter back to its original value explicitly.

Sysctl tuning is not about copying configurations from the internet. It is about understanding your workload, measuring your bottlenecks, and adjusting parameters that address specific problems. Start with the defaults, measure your system, and make targeted changes that solve real issues. That is the approach that has served me well across hundreds of production systems. For more advanced performance techniques, check our guide on advanced Ubuntu optimization and the official Linux kernel sysctl documentation for the complete parameter reference.

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *