Linux sysctl es la interfaz principal para leer y modificar parámetros del kernel en tiempo de ejecución sin necesidad de reiniciar. Ya sea que ejecutes un servidor web de alto tráfico, un host de base de datos o una carga de trabajo en contenedores, ajustar el kernel con sysctl puede mejorar drásticamente el rendimiento, reducir la latencia y evitar el agotamiento de recursos. En esta guía aprenderás qué parámetros importan más, cómo aplicarlos de forma segura y cómo hacerlos persistentes tras los reinicios usando /etc/sysctl.conf y archivos de configuración drop-in bajo /etc/sysctl.d/.
Requisitos Previos
- Un sistema Linux con kernel 4.x o superior (Ubuntu 20.04+, Debian 11+, RHEL 8+ o equivalente)
- Acceso
sudoo root - Familiaridad básica con la línea de comandos y un editor de texto (
nano,vimovi) - Conocimiento del tipo de carga que maneja el servidor (web, bases de datos, uso general)
Comprender la interfaz sysctl
El comando sysctl es una capa delgada sobre el pseudo-sistema de archivos /proc/sys/. Cada parámetro ajustable tiene un archivo correspondiente bajo esa ruta. Por ejemplo, el parámetro net.ipv4.tcp_fin_timeout se mapea a /proc/sys/net/ipv4/tcp_fin_timeout. Puedes leerlo directamente con cat o mediante sysctl:
# Ambos comandos devuelven el mismo resultado
sysctl net.ipv4.tcp_fin_timeout
cat /proc/sys/net/ipv4/tcp_fin_timeout
Escribir en estos archivos equivale a ejecutar sysctl -w, pero los cambios realizados de cualquier forma son temporales — desaparecen al reiniciar. El flujo de trabajo estándar es: probar con -w primero y luego persistir en un archivo de configuración una vez satisfecho con el resultado.
Para ver todos los parámetros ajustables a la vez:
sysctl -a
Para filtrar por espacio de nombres:
sysctl -a | grep net.ipv4.tcp
Parámetros de gestión de memoria
vm.swappiness
vm.swappiness controla qué tan agresivamente el kernel mueve páginas de memoria de la RAM al espacio de intercambio (swap). La escala va de 0 (evitar el intercambio al máximo) a 200 (intercambiar de forma agresiva). El valor predeterminado del kernel es 60.
Para servidores de aplicaciones y bases de datos que necesitan que los datos permanezcan en RAM:
sudo sysctl -w vm.swappiness=10
Para sistemas de escritorio donde la capacidad de respuesta importa más que mantener los cachés activos, 60 o incluso un valor mayor puede ser adecuado. En sistemas sin swap, establecer este valor en 0 evita cualquier actividad de intercambio.
vm.dirty_ratio y vm.dirty_background_ratio
Estos parámetros controlan cuánta memoria sucia (no escrita) tolera el sistema antes de forzar un vaciado al disco.
vm.dirty_background_ratio(predeterminado10) — porcentaje de memoria total en el que comienza la escritura en segundo planovm.dirty_ratio(predeterminado20) — porcentaje en el que los procesos se bloquean hasta que las páginas sucias se escriben
Para servidores con SSD rápidos o cargas de trabajo de escritura intensa, valores más bajos reducen el riesgo de grandes pausas de escritura:
sudo sysctl -w vm.dirty_background_ratio=5
sudo sysctl -w vm.dirty_ratio=10
vm.vfs_cache_pressure
Este parámetro controla qué tan agresivamente el kernel recupera memoria usada para cachear objetos de directorio e inodo. El valor predeterminado es 100. Reducirlo (por ejemplo, a 50) hace que el kernel mantenga los metadatos del sistema de archivos en caché por más tiempo, lo que beneficia las cargas de trabajo con muchos archivos pequeños:
sudo sysctl -w vm.vfs_cache_pressure=50
Ajuste de la pila de red con net.core y net.ipv4
net.core.somaxconn
net.core.somaxconn establece la longitud máxima de la cola de escucha para aceptar nuevas conexiones TCP. El valor predeterminado del kernel es 128, que es demasiado bajo para cualquier servicio expuesto a la web. Nginx, Apache y Node.js se benefician de un valor mucho mayor:
sudo sysctl -w net.core.somaxconn=65535
La aplicación también debe llamar a listen() con un backlog grande. Para Nginx, agrega listen 80 backlog=65535; en el bloque server.
net.core.netdev_max_backlog
Controla cuántos paquetes puede encolar la tarjeta de red antes de que el kernel los descarte. Bajo cargas de alto ancho de banda, el valor predeterminado de 1000 puede causar pérdida de paquetes:
sudo sysctl -w net.core.netdev_max_backlog=5000
Tamaños de búfer TCP
El kernel usa búferes de recepción y envío por socket para almacenar datos en tránsito. Búferes más grandes mejoran el rendimiento en enlaces de alta latencia (redes largas y con mucho tráfico):
# Mínimo, predeterminado, máximo del búfer de recepción (bytes)
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
# Mínimo, predeterminado, máximo del búfer de envío (bytes)
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
# Máximo global para búferes de socket
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
TIME_WAIT y reutilización de conexiones
Los servidores de alto tráfico crean miles de conexiones de corta duración. Sin ajuste, los sockets permanecen en TIME_WAIT hasta dos minutos y agotan los puertos efímeros:
# Reutilizar sockets TIME_WAIT para nuevas conexiones salientes
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
# Acortar la duración de TIME_WAIT (predeterminado 60 segundos)
sudo sysctl -w net.ipv4.tcp_fin_timeout=30
# Ampliar el rango de puertos locales para conexiones salientes
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65535"
Protección contra inundaciones SYN
Habilita las cookies SYN para protegerte contra ataques de inundación SYN sin descartar conexiones legítimas:
sudo sysctl -w net.ipv4.tcp_syncookies=1
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048
Límites de descriptores de archivo y procesos
Los servidores de alta concurrencia (servidores web, brokers de mensajes, agentes de monitoreo) abren miles de descriptores de archivo simultáneamente. El límite a nivel del kernel en todo el sistema está controlado por fs.file-max:
# Ver el máximo actual a nivel del sistema
sysctl fs.file-max
# Elevar a 2 millones para servidores con carga intensa
sudo sysctl -w fs.file-max=2000000
Ten en cuenta que fs.file-max es el límite máximo del kernel. También debes elevar los límites por proceso mediante /etc/security/limits.conf o la directiva LimitNOFILE de la unidad systemd para que los procesos individuales puedan aprovechar el nuevo espacio.
Persistir los ajustes: sysctl.conf vs archivos drop-in
El enfoque tradicional: /etc/sysctl.conf
Agrega los parámetros directamente a /etc/sysctl.conf:
# Ajuste de memoria
vm.swappiness = 10
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
vm.vfs_cache_pressure = 50
# Ajuste de red
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
# Límite de descriptores de archivo
fs.file-max = 2000000
Aplica sin reiniciar:
sudo sysctl -p
El enfoque moderno: archivos drop-in en /etc/sysctl.d/
Los archivos drop-in bajo /etc/sysctl.d/ son el enfoque preferido en distribuciones basadas en systemd. Permiten que los paquetes, las herramientas de gestión de configuración (Ansible, Puppet, Chef) y los scripts personalizados gestionen cada uno su propio conjunto de parámetros sin editar un archivo compartido.
Crea un archivo dedicado:
sudo nano /etc/sysctl.d/99-webserver-tuning.conf
Agrega tus parámetros en el mismo formato clave = valor. Recarga todos los archivos drop-in y /etc/sysctl.conf con:
sudo sysctl --system
Los archivos se procesan en orden lexicográfico. El prefijo 99- garantiza que tu archivo se cargue al final, sobrescribiendo cualquier valor predeterminado conflictivo establecido por los paquetes del sistema operativo.
Comparación: parámetros predeterminados vs recomendados
| Parámetro | Predeterminado del kernel | Recomendado (servidor web) | Notas |
|---|---|---|---|
vm.swappiness | 60 | 10 | Mantiene los datos de la aplicación en RAM |
vm.dirty_background_ratio | 10 | 5 | Vacía las páginas sucias antes |
vm.dirty_ratio | 20 | 10 | Reduce el riesgo de pausas de escritura |
vm.vfs_cache_pressure | 100 | 50 | Mantiene en caché los metadatos del sistema de archivos por más tiempo |
net.core.somaxconn | 128 | 65535 | Soporta alta concurrencia de conexiones |
net.core.netdev_max_backlog | 1000 | 5000 | Evita la pérdida de paquetes bajo carga |
net.ipv4.tcp_fin_timeout | 60 | 30 | Libera sockets más rápido |
net.ipv4.tcp_tw_reuse | 0 | 1 | Reutiliza sockets en TIME_WAIT |
net.ipv4.ip_local_port_range | 32768–60999 | 1024–65535 | Más puertos efímeros disponibles |
fs.file-max | ~100000 | 2000000 | Soporta un alto número de archivos abiertos |
Escenario real
Tienes un servidor Nginx en producción que maneja 5.000 conexiones HTTP concurrentes. Los usuarios ven intermitentemente errores 502 Bad Gateway y tiempos de espera agotados durante las horas pico. Ejecutas ss -s y ves miles de sockets atascados en TIME_WAIT, y dmesg muestra TCP: request_sock_TCP: Possible SYN flooding on port 443. El servidor tiene 16 GB de RAM y apenas toca el swap, pero free -h muestra un uso bajo de búfer/caché.
Esta es la secuencia de ajuste que aplicas:
# Paso 1: Diagnóstico
ss -s
sysctl net.core.somaxconn net.ipv4.tcp_fin_timeout fs.file-max
# Paso 2: Aplicar correcciones en tiempo de ejecución
sudo sysctl -w net.core.somaxconn=65535
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
sudo sysctl -w net.ipv4.tcp_fin_timeout=30
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sudo sysctl -w net.ipv4.tcp_syncookies=1
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048
sudo sysctl -w vm.swappiness=10
sudo sysctl -w fs.file-max=2000000
# Paso 3: Monitorear durante 15 minutos
watch -n 5 ss -s
# Paso 4: Si mejoró, persistir los ajustes
sudo tee /etc/sysctl.d/99-webserver-tuning.conf <<'EOF'
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
vm.swappiness = 10
fs.file-max = 2000000
EOF
sudo sysctl --system
El recuento de TIME_WAIT cae de varios miles a unos pocos cientos en minutos, y los errores 502 desaparecen.
Errores Comunes y Casos Especiales
Los cambios no son heredados por los procesos en ejecución. Cuando elevas fs.file-max, los trabajadores de Nginx ya en ejecución siguen operando bajo el límite por proceso anterior. También debes actualizar /etc/security/limits.conf y reiniciar el servicio, o establecer LimitNOFILE en el archivo de unidad systemd.
tcp_tw_reuse solo aplica a conexiones salientes. Permite que la pila local reutilice un socket en TIME_WAIT como origen de una nueva conexión saliente. No afecta las conexiones entrantes de los clientes. No lo confundas con tcp_tw_recycle, que fue eliminado en el kernel 4.12 y causaba fallos de conexión detrás de NAT.
net.core.somaxconn es un límite máximo, no mínimo. Si tu aplicación llama a listen() con un backlog menor, el kernel usa el valor más bajo. Ajusta tanto el parámetro del kernel como la configuración de la aplicación.
Los contenedores heredan el espacio de nombres del kernel del host. Los parámetros sysctl establecidos en /etc/sysctl.d/ del host se aplican a todos los contenedores. Algunos parámetros se pueden establecer por espacio de nombres de red usando docker run --sysctl o los contextos de seguridad de pods de Kubernetes, pero la mayoría requiere acceso a nivel del host.
Hacer pruebas con cargas de trabajo poco realistas es peligroso. Siempre realiza pruebas de rendimiento con tráfico que refleje la producción. Un parámetro que mejora el rendimiento en una prueba de laboratorio puede degradar la latencia en producción si las características de la carga de trabajo difieren.
Solución de Problemas
Permiso denegado al escribir un parámetro: Algunos parámetros son de solo lectura (marcados en /proc/sys/ como modo 444) y no se pueden cambiar en tiempo de ejecución. Otros requieren una opción de compilación específica del kernel. Revisa dmesg en busca de mensajes de error tras intentar una escritura.
El ajuste no sobrevive al reinicio: Verifica que el archivo esté bajo /etc/sysctl.d/ con extensión .conf y que no contenga errores de sintaxis. Ejecuta sudo sysctl --system y revisa la salida para confirmar que aparece “Applying /etc/sysctl.d/99-custom.conf”.
Error de parámetro no encontrado (sysctl: cannot stat /proc/sys/...): El parámetro requiere un módulo del kernel que no está cargado. Carga el módulo primero (por ejemplo, modprobe nf_conntrack) y vuelve a intentarlo.
Valores inesperadamente bajos tras aplicar los ajustes: Otro archivo de configuración cargado después está sobrescribiendo el tuyo. Revisa el orden de salida de sysctl --system y cambia el nombre de tu archivo a un prefijo numérico más alto (por ejemplo, 99- en lugar de 10-).
Resumen
sysctllee y escribe parámetros del kernel expuestos mediante/proc/sys/en tiempo de ejecución sin reiniciar- Usa
sysctl -wpara pruebas temporales y luego persiste los valores que funcionan en/etc/sysctl.d/99-custom.conf - Usa
sudo sysctl --systempara recargar todos los archivos de configuración; usasudo sysctl -ppara recargar solo/etc/sysctl.conf vm.swappiness=10mantiene los datos de las aplicaciones en RAM en servidores con memoria suficientenet.core.somaxconn=65535ynet.ipv4.tcp_tw_reuse=1son los cambios de mayor impacto para la concurrencia de servidores webfs.file-maxestablece el límite máximo del kernel para archivos abiertos — también debes elevar los límites por proceso en la aplicación o la unidad systemd- Los archivos drop-in bajo
/etc/sysctl.d/son preferibles a editar directamente/etc/sysctl.conf - Aplica siempre los cambios en tiempo de ejecución primero, monitorea bajo carga y persiste solo lo que demuestre ser beneficioso