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 Connection-Related
# 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
| Parameter | Default | Production Recommendation | Description |
|---|---|---|---|
tcp_max_syn_backlog | 1024 | 8192 | Half-connection queue length |
somaxconn | 128 | 4096 | Accept queue length |
tcp_synack_retries | 5 | 2 | SYN/ACK retry count |
tcp_syn_retries | 6 | 3 | SYN 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_recyclewas 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
| Algorithm | Characteristics | Use Case |
|---|---|---|
| reno | Classic algorithm | Conservative environments |
| cubic | Default, loss-based | General purpose |
| bbr | Bandwidth and delay-based | High-latency/lossy networks |
| westwood | Bandwidth estimation | Wireless networks |
| vegas | Delay-based | Low-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:
- Measure before tuning: Collect baseline data with
sar/ss/sysctlto identify bottlenecks, rather than blindly applying templates. - Network parameters have the highest impact:
somaxconn/tcp_max_syn_backlog/tcp_tw_reuse/BBR are must-tune items for high-concurrency services. - File descriptors are a common bottleneck: Both system-level
fs.file-maxand process-levelnofileneed adjustment; systemd services need configuration in unit files. - Memory parameters vary by scenario: Database
swappiness=1, containerswappiness=10, large memory servers usedirty_bytesinstead ofdirty_ratio. - Security parameters are baseline requirements: Reverse path filtering, disabling ICMP redirects, restricting dmesg/ptrace are basic production requirements.
- Use
/etc/sysctl.d/for config files: Organize by function, use consistent naming (99-xxx.conf), for easier maintenance and auditing. - Validate after changes: Use
ss/free/sarto verify parameters are effective and results meet expectations. - BBR is a standard for network tuning: Significant improvement for high-latency, lossy networks, but requires pairing with
fqqueue 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.