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 sudo o root
  • Familiaridad básica con la línea de comandos y un editor de texto (nano, vim o vi)
  • 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 (predeterminado 10) — porcentaje de memoria total en el que comienza la escritura en segundo plano
  • vm.dirty_ratio (predeterminado 20) — 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ámetroPredeterminado del kernelRecomendado (servidor web)Notas
vm.swappiness6010Mantiene los datos de la aplicación en RAM
vm.dirty_background_ratio105Vacía las páginas sucias antes
vm.dirty_ratio2010Reduce el riesgo de pausas de escritura
vm.vfs_cache_pressure10050Mantiene en caché los metadatos del sistema de archivos por más tiempo
net.core.somaxconn12865535Soporta alta concurrencia de conexiones
net.core.netdev_max_backlog10005000Evita la pérdida de paquetes bajo carga
net.ipv4.tcp_fin_timeout6030Libera sockets más rápido
net.ipv4.tcp_tw_reuse01Reutiliza sockets en TIME_WAIT
net.ipv4.ip_local_port_range32768–609991024–65535Más puertos efímeros disponibles
fs.file-max~1000002000000Soporta 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

  • sysctl lee y escribe parámetros del kernel expuestos mediante /proc/sys/ en tiempo de ejecución sin reiniciar
  • Usa sysctl -w para pruebas temporales y luego persiste los valores que funcionan en /etc/sysctl.d/99-custom.conf
  • Usa sudo sysctl --system para recargar todos los archivos de configuración; usa sudo sysctl -p para recargar solo /etc/sysctl.conf
  • vm.swappiness=10 mantiene los datos de las aplicaciones en RAM en servidores con memoria suficiente
  • net.core.somaxconn=65535 y net.ipv4.tcp_tw_reuse=1 son los cambios de mayor impacto para la concurrencia de servidores web
  • fs.file-max establece 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

Artículos Relacionados