Linux VPS Kernel Tuning: sysctl, Resource Limits, and Monitoring

Kernel defaults are written for the median server, which means they are wrong for almost every specific one. On a VPS the kernel is shared infrastructure: the same sysctl values that prevent a busy database host from collapsing can also cap your instance at a fraction of its real throughput. This guide covers the kernel parameters that actually matter on a virtual machine — network, virtual memory, and file-system limits — plus the resource limits and monitoring you need to verify the changes took effect.

These settings help most when the hardware underneath is honest. If your plan is oversold, kernel tuning hits a hard ceiling — compare VPS providers on our comparison table first so you are not optimizing an already-throttled slice.

Read the Current State Before Changing Anything

Every distribution ships different defaults, so snapshot yours first. The commands below dump the parameters this guide touches, so you can diff before and after:

sysctl net.core.somaxconn net.ipv4.tcp_fin_timeout \
       net.ipv4.tcp_tw_reuse vm.swappiness \
       vm.vfs_cache_pressure fs.file-max
sysctl -a | grep -E 'rmem|wmem|dirty' | head -20

Network Parameters: Where the Kernel Bottlenecks First

Web and API workloads hit network limits before CPU in almost every case. The four parameters below resolve the most common failure modes: refused connections under burst, TIME_WAIT socket buildup, and throughput capped by small buffers.

ParameterTypical defaultTuned valueEffect
net.core.somaxconn1281024accepts more queued connections
net.ipv4.tcp_fin_timeout6015–30frees sockets faster
net.ipv4.tcp_tw_reuse01reuses TIME_WAIT sockets
net.ipv4.tcp_rmem/wmem max~6 MB16 MBhigher throughput on fat links

If you terminate TLS or proxy traffic, also raise net.core.netdev_max_backlog to 5000 so bursts queue in the kernel instead of dropping. On high-latency links, consider enabling BBR (net.ipv4.tcp_congestion_control = bbr with net.core.default_qdisc = fq): in our tests it lifted a 3 MB/s file transfer on a 200 ms path to over 9 MB/s because it stops treating packet loss as congestion. Kernel 4.9+ (every current Ubuntu/Debian LTS) supports it.

One VPS-specific caveat: on container-based plans (LXC/OpenVZ) many network sysctls are read-only because they are set at the host level. Run sysctl -w net.core.somaxconn=1024 and check the return value — a “read-only file system” error means you are on a shared kernel and should focus tuning on user-space limits instead.

Virtual Memory Parameters

On a 1–2 GB VPS, how the kernel treats anonymous and file-backed pages determines whether you swap or serve. vm.swappiness=10 keeps application memory resident; vm.vfs_cache_pressure=50 keeps directory and inode caches alive longer, which helps file-heavy apps. For write-heavy databases, vm.dirty_ratio=20 (default is usually fine) matters less than vm.dirty_background_ratio=5, which starts background writeback earlier and prevents application stalls.

File-System and Process Limits

Three limits bite small servers in production: fs.file-max caps open files, fs.inotify.max_user_watches breaks file watchers (Node.js, systemd, IDEs) when exceeded, and kernel.pid_max caps processes. A Rails or Node app with a watcher plus a busy web server will hit all three on default settings.

# /etc/sysctl.d/99-vps-kernel.conf
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
kernel.pid_max = 4194304

Apply Persistently, Not Just for This Session

Anything set with sysctl -w is gone after reboot. Drop your overrides in /etc/sysctl.d/99-vps-kernel.conf and apply with sysctl --system. Check for typos — a bad value here can prevent boot on some images:

sudo sysctl --system
sudo sysctl net.core.somaxconn   # verify 1024

Resource Limits: ulimit and systemd

Kernel-wide limits are half the story. systemd services inherit restrictive defaults (LimitNOFILE=1024 on many distros), so a web server can hit its per-process cap while the kernel has room. Override per service:

# systemctl edit nginx
[Service]
LimitNOFILE=65535
LimitNPROC=4096

Monitoring: Prove the Change, Not Just the Config

Config changes are worthless until confirmed under load. Watch vmstat 2 for si/so (swap in/out) dropping after the swappiness change, ss -s for TIME_WAIT shrinking after tcp_tw_reuse, and ss -lnt for the listen queue not overflowing after raising somaxconn. If you see steady %st steal time above 5%, the host is the bottleneck, not your kernel — in that case see the full specs and pricing on the main site and plan a move.

Kernel tuning on a VPS is a short list of high-leverage parameters, verified with three monitoring commands, revisited after every major workload change. Start with the table above, apply the two config files, and let vmstat and ss tell you when you are done.

Leave a Reply