Overview

The Linux kernel exposes thousands of tunable parameters through /proc/sys/ and the sysctl interface, covering networking, memory, filesystem, security, and more. Properly adjusting these parameters can significantly improve system performance and stability, but blind tuning can be counterproductive. This article systematically covers the sysctl system across four dimensions — networking, file descriptors, memory, and security — and provides production tuning templates and parameter validation methods.

sysctl System

Viewing and Modifying Parameters

# View all parameters
$ sysctl -a

# View specific parameter
$ sysctl net.ipv4.tcp_max_syn_backlog
$ sysctl vm.swappiness

# Temporary modification (lost on reboot)
$ sysctl -w vm.swappiness=10

# Load from file
$ sysctl -p /etc/sysctl.d/99-custom.conf

# Permanent: write to config file
# /etc/sysctl.conf          — traditional config file
# /etc/sysctl.d/*.conf      — recommended (loaded in alphabetical order)

Config File Load Order

Files in /etc/sysctl.d/ are loaded in alphabetical order:
  00-default.conf        default values
  50-network.conf        network parameters
  99-custom.conf         custom parameters (loaded last, overrides earlier)
  
Finally loads /etc/sysctl.conf (if it exists)

Parameter Namespaces

kernel.*    — general kernel parameters
vm.*        — virtual memory parameters
fs.*        — filesystem parameters
net.*       — network parameters
net.ipv4.*  — IPv4-specific parameters
net.ipv6.*  — IPv6-specific parameters
net.core.*  — network core parameters
dev.*       — device parameters
abi.*       — ABI parameters
user.*      — user namespace parameters

Network Parameters

# TCP SYN queue length (half-connection queue)
$ sysctl net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_max_syn_backlog = 4096

# Accept queue length
# Controlled by net.core.somaxconn
$ sysctl net.core.somaxconn
net.core.somaxconn = 4096

# SYN/ACK retry count (SYN Flood defense)
$ sysctl net.ipv4.tcp_synack_retries
net.ipv4.tcp_synack_retries = 2  # Default 5, recommend 2

# SYN retry count
$ sysctl net.ipv4.tcp_syn_retries
net.ipv4.tcp_syn_retries = 3     # Default 6, recommend 3
ParameterDefaultProduction RecommendationDescription
tcp_max_syn_backlog10248192Half-connection queue length
somaxconn1284096Accept queue length
tcp_synack_retries52SYN/ACK retry count
tcp_syn_retries63SYN retry count

TCP Buffers

# TCP read buffer (min/default/max)
$ sysctl net.ipv4.tcp_rmem
net.ipv4.tcp_rmem = 4096 87380 6291456

# TCP write buffer (min/default/max)
$ sysctl net.ipv4.tcp_wmem
net.ipv4.tcp_wmem = 4096 16384 4194304

# Network stack read/write buffer max
$ sysctl net.core.rmem_max
net.core.rmem_max = 212992
$ sysctl net.core.wmem_max
net.core.wmem_max = 212992

# Network stack default buffers
$ sysctl net.core.rmem_default
net.core.rmem_default = 212992
$ sysctl net.core.wmem_default
net.core.wmem_default = 212992

Production recommended:

net.core.rmem_max = 16777216      # 16MB
net.core.wmem_max = 16777216      # 16MB
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

TCP Keepalive

# Keepalive idle time (seconds)
$ sysctl net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_time = 7200   # 2 hours

# Keepalive probe interval
$ sysctl net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_intvl = 75

# Keepalive probe count
$ sysctl net.ipv4.tcp_keepalive_probes
net.ipv4.tcp_keepalive_probes = 9
# Production recommended (fast dead connection detection)
net.ipv4.tcp_keepalive_time = 600      # 10 minutes
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

TIME_WAIT Optimization

# Maximum number of TIME_WAIT connections
$ sysctl net.ipv4.tcp_max_tw_buckets
net.ipv4.tcp_max_tw_buckets = 5000

# Enable TIME_WAIT fast recycling (dangerous! disable in NAT environments)
$ sysctl net.ipv4.tcp_tw_recycle
net.ipv4.tcp_tw_recycle = 0  # Removed in 4.x kernels

# Allow socket reuse in TIME_WAIT state
$ sysctl net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_reuse = 1   # Recommended

Important: tcp_tw_recycle was removed after kernel 4.12. Enabling it in NAT environments causes packet drops — do not use.

TCP Fast Open

# TCP Fast Open (saves one RTT)
$ sysctl net.ipv4.tcp_fastopen
net.ipv4.tcp_fastopen = 0   # Disabled by default

# Enable (client + server)
$ sysctl -w net.ipv4.tcp_fastopen=3
# 1 = client
# 2 = server
# 3 = client + server

Congestion Control Algorithms

# View available congestion control algorithms
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic

# Current algorithm
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic

# Load BBR
$ modprobe tcp_bbr
$ sysctl -w net.ipv4.tcp_congestion_control=bbr

# Verify module loaded successfully
$ sysctl net.ipv4.tcp_available_congestion_control
reno cubic bbr
AlgorithmCharacteristicsUse Case
renoClassic algorithmConservative environments
cubicDefault, loss-basedGeneral purpose
bbrBandwidth and delay-basedHigh-latency/lossy networks
westwoodBandwidth estimationWireless networks
vegasDelay-basedLow-latency LANs

Network Stack Core Parameters

# NIC receive queue length
$ sysctl net.core.netdev_max_backlog
net.core.netdev_max_backlog = 1000
# Production recommendation: 8192

# Local port range
$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 60999
# Production recommendation: 1024 65535

# ICMP rate limit
$ sysctl net.ipv4.icmp_ratelimit
net.ipv4.icmp_ratelimit = 1000

# ARP table size
$ sysctl net.ipv4.neigh.default.gc_thresh3
net.ipv4.neigh.default.gc_thresh3 = 1024
# Production recommendation: 8192

Production Network Tuning Template

# /etc/sysctl.d/99-network-tuning.conf

# === Connection Queues ===
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# === Buffers ===
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# === Keepalive ===
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

# === TIME_WAIT ===
net.ipv4.tcp_max_tw_buckets = 32768
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

# === SYN ===
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3

# === NIC Queue ===
net.core.netdev_max_backlog = 8192

# === Port Range ===
net.ipv4.ip_local_port_range = 1024 65535

# === Congestion Control ===
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# === Fast Open ===
net.ipv4.tcp_fastopen = 3

# === MTU Probing ===
net.ipv4.tcp_mtu_probing = 1

# === ARP ===
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 6144
net.ipv4.neigh.default.gc_thresh3 = 8192

File Descriptors

System-Level Limits

# System-wide maximum file descriptors
$ sysctl fs.file-max
fs.file-max = 1886960

# View current usage
$ cat /proc/sys/fs/file-nr
1234   0  1886960
# Allocated  Unused  Maximum

Process-Level Limits

# ulimit
$ ulimit -n
1024

# View soft and hard limits
$ ulimit -Sn  # Soft limit
$ ulimit -Hn  # Hard limit

# Temporary modification
$ ulimit -n 65535

# Permanent: /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535

# Or /etc/security/limits.d/*.conf
# /etc/security/limits.d/99-nofile.conf
* soft nofile 65535
* hard nofile 65535

systemd Service File Descriptor Limits

# systemd services are not controlled by limits.conf; configure in unit file
# /etc/systemd/system/myservice.service
[Service]
LimitNOFILE=65535

# Or create an override
$ systemctl edit myservice
[Service]
LimitNOFILE=65535

# View service limits
$ systemctl show myservice | grep LimitNOFILE

inotify Limits

# Maximum watched files
$ sysctl fs.inotify.max_user_watches
fs.inotify.max_user_watches = 8192

# Maximum inotify instances
$ sysctl fs.inotify.max_user_instances
fs.inotify.max_user_instances = 128

# Production recommendation (for file monitoring services like Promtail)
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512

File Descriptor Tuning Template

# /etc/sysctl.d/99-fd-tuning.conf
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512
fs.nr_open = 1048576  # Max fd per process

# /etc/security/limits.d/99-nofile.conf
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535

Memory Parameters

Swap Control

# swappiness (0-100)
$ sysctl vm.swappiness
vm.swappiness = 60

# Production recommendations
# Database: 1
# Container host: 10
# General: 10-20

# vfs_cache_pressure
$ sysctl vm.vfs_cache_pressure
vm.vfs_cache_pressure = 100

# Production recommendation: 50-100
# Too high: frequent dentry/inode cache reclaim
# Too low: slab consumes too much memory

Dirty Page Control

# Dirty page ratio of memory
$ sysctl vm.dirty_ratio
vm.dirty_ratio = 20

$ sysctl vm.dirty_background_ratio
vm.dirty_background_ratio = 10

# Production recommendation (use bytes for large memory servers)
vm.dirty_background_bytes = 268435456   # 256MB
vm.dirty_bytes = 1073741824             # 1GB

Overcommit

# Memory overcommit policy
$ sysctl vm.overcommit_memory
vm.overcommit_memory = 0

# 0 = Heuristic (default, reasonable)
# 1 = Always allow (Redis recommends but dangerous)
# 2 = Strict check (no exceeding swap + ratio×RAM)

$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50

# When overcommit_memory=2:
# Available memory = swap + overcommit_ratio% × RAM

HugePages

# Transparent HugePages
$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

# Database recommendation: disable THP
$ echo never > /sys/kernel/mm/transparent_hugepage/enabled

# Static HugePages
$ sysctl vm.nr_hugepages
vm.nr_hugepages = 0

# Configure 100 x 2MB huge pages
$ sysctl -w vm.nr_hugepages=100

Memory Tuning Template

# /etc/sysctl.d/99-memory-tuning.conf

# Swap
vm.swappiness = 10
vm.vfs_cache_pressure = 50

# Dirty pages
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500

# Overcommit
vm.overcommit_memory = 0
vm.overcommit_ratio = 90

# Memory reclaim
vm.min_free_kbytes = 262144    # 256MB (for 64GB server)
vm.watermark_scale_factor = 10

# NUMA
vm.zone_reclaim_mode = 0

Security Parameters

Network Security

# IP forwarding
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
# Routers/container hosts need to set to 1

# ICMP redirects
$ sysctl net.ipv4.conf.all.send_redirects
net.ipv4.conf.all.send_redirects = 0

$ sysctl net.ipv4.conf.all.accept_redirects
net.ipv4.conf.all.accept_redirects = 0

# Source routing
$ sysctl net.ipv4.conf.all.accept_source_route
net.ipv4.conf.all.accept_source_route = 0

# Reverse path filtering
$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1

# ICMP broadcast
$ sysctl net.ipv4.icmp_echo_ignore_broadcasts
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Martian packet logging
$ sysctl net.ipv4.conf.all.log_martians
net.ipv4.conf.all.log_martians = 1

# TCP SYN Cookies (SYN Flood defense)
$ sysctl net.ipv4.tcp_syncookies
net.ipv4.tcp_syncookies = 1

Kernel Security

# Kernel address space layout randomization
$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 2
# 0 = Disabled
# 1 = Shared library randomization
# 2 = Full randomization (default)

# dmesg restriction
$ sysctl kernel.dmesg_restrict
kernel.dmesg_restrict = 1
# Non-root cannot read kernel logs

# kptr_restrict
$ sysctl kernel.kptr_restrict
kernel.kptr_restrict = 2
# Hide kernel pointers

# ptrace restriction
$ sysctl kernel.yama.ptrace_scope
kernel.yama.ptrace_scope = 1
# 0 = Any process can ptrace
# 1 = Only child processes can be ptraced
# 2 = Only root can ptrace
# 3 = Fully disabled

# Core dump path
$ sysctl kernel.core_pattern
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

Security Parameters Template

# /etc/sysctl.d/99-security-hardening.conf

# Network security
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.log_martians = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Kernel security
kernel.randomize_va_space = 2
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.yama.ptrace_scope = 1

# User space
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2

Production Tuning Templates

Database Server

# /etc/sysctl.d/99-database.conf

# Network
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_max_tw_buckets = 32768
net.ipv4.tcp_tw_reuse = 1

# Memory
vm.swappiness = 1
vm.vfs_cache_pressure = 50
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824
vm.overcommit_memory = 0
vm.min_free_kbytes = 524288

# File descriptors
fs.file-max = 2097152
fs.aio-max-nr = 1048576

# THP disabled
# Set via systemd or rc.local

Web Server

# /etc/sysctl.d/99-webserver.conf

# Network (high concurrency)
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_max_tw_buckets = 32768
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.core.netdev_max_backlog = 8192
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2

# Buffers
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

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

# File descriptors
fs.file-max = 2097152

Container Host

# /etc/sysctl.d/99-container-host.conf

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

# Connection tracking
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.netfilter.nf_conntrack_udp_timeout = 30

# Bridging
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

# Network
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535

# Memory
vm.swappiness = 10
vm.overcommit_memory = 1

# File descriptors
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512

General Server Baseline

# /etc/sysctl.d/99-general-baseline.conf

# Network
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_max_tw_buckets = 32768
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3
net.core.netdev_max_backlog = 4096
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# Memory
vm.swappiness = 10
vm.vfs_cache_pressure = 50
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10

# File descriptors
fs.file-max = 1048576
fs.inotify.max_user_watches = 524288

# Security
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.accept_source_route = 0
kernel.randomize_va_space = 2
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

Parameter Validation Methods

Network Parameter Validation

# 1. Verify SYN queue
$ ss -lnt | awk '{print $2}'  # Recv-Q near somaxconn means queue full
$ ss -lnt | awk 'NR>1{print $2}' | sort -rn | head

# 2. Verify TCP connection count
$ ss -s
# Total: 12345
# TCP:   8765 (estab 5432, closed 2100, orphaned 0, timewait 2000)

# 3. Verify TIME_WAIT count
$ ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
#    5432 ESTAB
#    2100 TIME-WAIT

# 4. Verify conntrack
$ cat /proc/sys/net/netfilter/nf_conntrack_count
# Near nf_conntrack_max means need to increase

# 5. Verify port range
$ cat /proc/sys/net/ipv4/ip_local_port_range
# Confirm range is sufficient

# 6. Use ss to check queue status
$ ss -lnt state listening
# Recv-Q = 0 means queue not full
# Recv-Q > 0 means queue backlog

Memory Parameter Validation

# 1. Verify swappiness
$ cat /proc/sys/vm/swappiness

# 2. View swap usage
$ free -h
$ swapon --show

# 3. View dirty pages
$ cat /proc/meminfo | grep -E "Dirty|Writeback"
$ grep -E "dirty|writeback" /proc/vmstat

# 4. View slab
$ cat /proc/meminfo | grep -E "Slab|SReclaimable|SUnreclaim"

# 5. View overcommit
$ cat /proc/meminfo | grep -E "CommitLimit|Committed_AS"
# CommitLimit = swap + overcommit_ratio% × RAM
# Committed_AS = currently allocated virtual memory
# Committed_AS > CommitLimit means overcommitted

File Descriptor Validation

# 1. System-level
$ cat /proc/sys/fs/file-nr
# Currently allocated  Unused  Maximum

# 2. Process-level
$ cat /proc/$PID/limits | grep "Max open files"
Max open files  65535  65535  files

# 3. Actual process usage
$ ls /proc/$PID/fd | wc -l

# 4. View processes with most fd usage
$ lsof -n | awk '{print $2}' | sort | uniq -c | sort -rn | head -10

Stress Testing Validation

# TCP connection stress test
$ sysbench --threads=256 --time=60 memory run

# Network stress test
$ iperf3 -c target -P 10 -t 60

# File descriptor stress test
$ python3 -c "
import resource
resource.setrlimit(resource.RLIMIT_NOFILE, (65535, 65535))
fds = []
try:
    while True:
        fds.append(open('/dev/null'))
except IOError:
    print(f'Opened {len(fds)} file descriptors')
"

# Web stress test with wrk
$ wrk -t12 -c10000 -d60s http://localhost:8080

Monitoring Parameter Effects

# Continuous monitoring with sar
$ sar -n SOCK 1 60       # Socket statistics
$ sar -n TCP 1 60        # TCP statistics
$ sar -r 1 60            # Memory statistics
$ sar -B 1 60            # Paging statistics

# Monitor TCP states with ss
$ watch -n 1 'ss -ant | awk "{print \$1}" | sort | uniq -c | sort -rn'

# View kernel network statistics with nstat
$ nstat -az | grep -E "TcpExt|TcpInSegs|TcpOutSegs"

Common Issue Troubleshooting

Issue 1: Connection Queue Full

# Symptom: Connection timeout, connection refused
# Troubleshooting:
$ ss -lnt state listening
# Recv-Q > 0 indicates accept queue backlog
$ ss -ant state syn-recv | wc -l
# Count near tcp_max_syn_backlog indicates SYN queue full

# Solution:
$ sysctl -w net.core.somaxconn=65535
$ sysctl -w net.ipv4.tcp_max_syn_backlog=65535
# Also adjust application listen backlog

Issue 2: Too Many Open Files

# Symptom: Application reports "Too many open files"
# Troubleshooting:
$ cat /proc/sys/fs/file-nr
$ cat /proc/$PID/limits | grep "Max open files"
$ ls /proc/$PID/fd | wc -l

# Solution:
# 1. Increase system limit
$ sysctl -w fs.file-max=2097152
# 2. Increase process limit (limits.conf or systemd)
# 3. Check for fd leaks
$ ls -la /proc/$PID/fd | head -50
$ lsof -p $PID | awk '{print $5}' | sort | uniq -c | sort -rn

Issue 3: conntrack Table Full

# Symptom: Logs report "nf_conntrack: table full, dropping packet"
# Troubleshooting:
$ cat /proc/sys/net/netfilter/nf_conntrack_count
$ cat /proc/sys/net/netfilter/nf_conntrack_max
# count near max means table full

# Solution:
$ sysctl -w net.netfilter.nf_conntrack_max=1048576
# Also shorten timeouts
$ sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400

Issue 4: BBR Not Effective

# Troubleshooting:
$ sysctl net.ipv4.tcp_congestion_control
# If not bbr:
$ modprobe tcp_bbr
$ sysctl -w net.ipv4.tcp_congestion_control=bbr

# Confirm module loaded
$ lsmod | grep tcp_bbr
# If not present, add to /etc/modules-load.d/
$ echo "tcp_bbr" > /etc/modules-load.d/bbr.conf

Summary

Kernel parameter tuning is a foundational aspect of system optimization, but it requires a scientific approach. Key takeaways:

  1. Measure before tuning: Collect baseline data with sar/ss/sysctl to identify bottlenecks, rather than blindly applying templates.
  2. Network parameters have the highest impact: somaxconn/tcp_max_syn_backlog/tcp_tw_reuse/BBR are must-tune items for high-concurrency services.
  3. File descriptors are a common bottleneck: Both system-level fs.file-max and process-level nofile need adjustment; systemd services need configuration in unit files.
  4. Memory parameters vary by scenario: Database swappiness=1, container swappiness=10, large memory servers use dirty_bytes instead of dirty_ratio.
  5. Security parameters are baseline requirements: Reverse path filtering, disabling ICMP redirects, restricting dmesg/ptrace are basic production requirements.
  6. Use /etc/sysctl.d/ for config files: Organize by function, use consistent naming (99-xxx.conf), for easier maintenance and auditing.
  7. Validate after changes: Use ss/free/sar to verify parameters are effective and results meet expectations.
  8. BBR is a standard for network tuning: Significant improvement for high-latency, lossy networks, but requires pairing with fq queue scheduling.

Ultimate principle of kernel tuning: do not tune parameters you don’t understand. Every parameter has its design intent and side effects. Understand its meaning before tuning, and validate the results after.