sysctl reads and changes kernel parameters at runtime: network buffers, memory behaviour, IP forwarding and hundreds more. A few of them really do make a difference on servers. Most “ultimate sysctl.conf” lists copied from the internet don’t, and some make things worse. This guide covers the mechanics and the settings worth knowing.

On a KVM VPS (like all VPS.DO VPS plans) you run your own kernel, so you can change these freely. Container-based virtualization often blocks them.

Read and set values

sysctl net.core.somaxconn                 # read one
sysctl -a | grep swappiness               # search
sudo sysctl -w vm.swappiness=10           # set now (lost at reboot)

The same values appear as files under /proc/sys/ (dots become slashes): cat /proc/sys/vm/swappiness.

Make changes persistent

Put settings in a file under /etc/sysctl.d/:

sudo tee /etc/sysctl.d/99-custom.conf > /dev/null <<'EOF'
vm.swappiness = 10
net.core.somaxconn = 4096
EOF
sudo sysctl --system         # load all sysctl files now

Files are applied in lexical order, so 99- wins over earlier ones. Don’t edit /etc/sysctl.conf directly on distributions that ship it as a package file. Your own file in sysctl.d survives upgrades and is easy to find.

Settings worth knowing

Memory

vm.swappiness = 10

This controls how eagerly the kernel swaps out application memory rather than dropping file cache (default 60). On servers with databases or app processes, 10 keeps the working set in RAM longer. See swap usage.

vm.overcommit_memory = 1

Redis recommends this so background saves (which fork) don’t fail. Only set it if you run Redis and understand that it disables the kernel’s allocation heuristics.

TCP congestion control: BBR

net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

BBR (from Google) often improves throughput on long-distance and lossy paths, such as serving users far away or across the Pacific. It’s one of the few changes with a clearly visible benefit for web and download servers. Check it’s available, then verify:

sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control

Connection backlog

net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192

somaxconn caps the listen queue for accepting connections. Modern kernels (5.4+) default to 4096 already. Raise it for very busy servers. The application must request a big backlog too (Nginx listen 443 ssl backlog=4096;).

Port range for many outgoing connections

net.ipv4.ip_local_port_range = 10240 65535

Proxies and apps making many outbound connections (to upstreams or APIs) can run out of ephemeral ports. Keepalive connections to upstreams are the better fix. See Nginx load balancing.

Connection tracking

net.netfilter.nf_conntrack_max = 262144

If dmesg shows nf_conntrack: table full, dropping packet, the firewall’s connection tracking table is too small for your traffic. That’s common on busy servers using iptables, nftables or UFW. See dmesg.

IP forwarding (VPN, routers, containers)

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

This is required for WireGuard or OpenVPN gateways and NAT. Docker enables it itself. See WireGuard.

net.ipv4.tcp_syncookies = 1                   # SYN flood resilience (usually already on)
net.ipv4.conf.all.rp_filter = 1               # drop spoofed source addresses
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1

Most are already set by distribution defaults. Verify them as part of hardening. See Linux server hardening.

File handles and inotify

fs.file-max = 2097152
fs.inotify.max_user_watches = 524288

max_user_watches matters for file watchers (Syncthing, IDE servers, some build tools) that report “ENOSPC: System limit for number of file watchers reached”. Per-process open-file limits are set elsewhere. See ulimit.

What to avoid

  • net.ipv4.tcp_tw_recycle — removed from the kernel because it broke clients behind NAT. Copy-pasted configs still include it and produce errors.
  • Huge buffer sizes (rmem_max/wmem_max at hundreds of MB) “for speed”: modern kernels auto-tune buffers. Increase them only for measured high-bandwidth, high-latency transfers.
  • vm.swappiness = 0 as a cure-all: it can make the OOM killer act sooner. 10 is a gentler choice.
  • Applying dozens of settings at once: change one thing, measure, keep it if it helps.

Verify after reboot

sudo sysctl --system | grep -i error
sysctl vm.swappiness net.ipv4.tcp_congestion_control

Some keys only exist once a module is loaded. nf_conntrack_max needs the nf_conntrack module, so it may be applied too early at boot. Add the module to /etc/modules-load.d/ if needed.

Quick reference

Task Command
Read sysctl key
Set temporarily sudo sysctl -w key=value
Persistent file in /etc/sysctl.d/99-custom.conf
Reload all sudo sysctl --system
Enable BBR default_qdisc=fq + tcp_congestion_control=bbr
Lower swapping vm.swappiness=10
Forwarding net.ipv4.ip_forward=1

Related: load average and VPS speed optimization.

  • Linux
  • Performance
  • Networking