Conoces el momento: el servidor arranca, SSH funciona, la aplicación se despliega y todos declaran la victoria. Luego, dos semanas después, está “misteriosamente lento”, las copias de seguridad “llegarán pronto”, la hora está mal y el sistema de archivos root está al 97% porque los logs encontraron religión.
Esta es la lista de comprobación que evita esas reuniones. No es romántica. No es “cloud native”. Es el conjunto poco glamoroso de comprobaciones que te permite dormir, migrar y depurar sin realizar arqueología forense sobre tu propia instalación.
La mentalidad: establecer una base y luego construir
Una instalación nueva es la única vez en la vida de un sistema en la que todo está limpio, determinista y todavía obediente. Una vez que llega tráfico de producción, aparece la entropía: los paquetes derivan, los archivos de configuración se editan “temporalmente” y la única persona que recuerda por qué se cambió un parámetro del kernel está de vacaciones para siempre.
Tu objetivo en los primeros 20 minutos no es “terminar la configuración”. Tu objetivo es capturar una línea base y fijar rieles de seguridad:
- Línea base: Identificar el hardware y el entorno virtual que realmente recibiste (no lo que prometió compras).
- Confirmar invariantes: Hora, DNS, enrutamiento, diseño de almacenamiento y canales de actualización.
- Hacer que el futuro sea barato: snapshots, backups, un lugar para los logs y una forma de depurar sin adivinar.
Una cita para pegar en tu monitor. Es una idea parafraseada de John Allspaw (operaciones y confiabilidad): parafraseado: Los sistemas fallan de maneras sorprendentes; tu trabajo es hacer que sea seguro aprender y recuperarse rápidamente.
Haz las comprobaciones aburridas ahora. O házlas a las 02:00 mientras alguien pregunta si el problema es “la base de datos”.
Hechos y contexto interesantes (por qué esto sigue pasando)
- Las cicatrices de la sincronización de tiempo en Unix son antiguas. Los ancestros de NTP datan de décadas; los bugs de sincronización de tiempo todavía causan fallos de autenticación, errores TLS y líneas de tiempo “imposibles” en los logs.
- Los sistemas de ficheros tienen historia, y se nota. ext4 es conservador porque heredó una línea que aprendió lecciones duras de cortes de corriente y discos defectuosos.
- El journaling fue una revolución. Antes de que los sistemas de ficheros con journaling fueran comunes, los fallos podían convertir reinicios en eventos de fsck de varias horas. Muchos “predeterminados raros” de hoy existen para evitar que esa era vuelva.
- RAID nunca fue una copia de seguridad. La frase es más antigua que la mayoría de las rotaciones on-call y todavía se ignora semanalmente; RAID protege contra ciertos fallos de disco, no contra borrados o corrupción.
- Los fallos de DNS son un villano recurrente. Internet ha tenido múltiples outages de alto perfil causados por errores de DNS; dentro de las empresas, el mismo patrón se repite con split-horizon y resolvers obsoletos.
- Los valores por defecto de OpenSSH evolucionaron por una razón. Alejarse de algoritmos débiles y moverse hacia autenticación por llave no fue moda; fue el residuo acumulado de incidentes.
- cgroups y systemd cambiaron las operaciones Linux. Mejoraron el control de recursos y la supervisión de servicios, pero también introdujeron modos de fallo que solo verás si revisas las salidas de estado correctas.
- “Funciona en mi máquina” empeoró con la virtualización. Deriva del reloj, vecinos ruidosos, I/O sobresuscrito y banderas de CPU desajustadas pueden hacer que dos VMs “idénticas” se comporten como especies diferentes.
Esto no es trivia. Es por lo que una lista de comprobación para instalaciones nuevas no es paranoia. Es interés compuesto.
Listas de comprobación / plan paso a paso (la rutina de 20 minutos)
Minuto 0–3: Identidad y acceso (antes de tocar cualquier otra cosa)
- Confirma hostname, versión de OS, kernel y contexto de virtualización.
- Confirma que puedes entrar de forma segura: claves SSH, sudo y un segundo camino (consola, fuera de banda o serial de VM).
- Registra el estado inicial: orígenes de paquetes, kernel cmdline, diseño de discos.
Minuto 3–8: Diseño de almacenamiento que no odiarás después
- Verifica qué discos tienes, cómo se llaman y si son NVMe, SATA o almacenamiento en red.
- Confirma particionado y puntos de montaje. Asegúrate de que logs y datos no compartan accidentalmente un pequeño root.
- Confirma comportamiento TRIM/discard para SSDs donde importe.
Minuto 8–12: Comprobación de la realidad de la red
- Verifica IPs, rutas y resolvers DNS.
- Verifica MTU y latencia básica. Revisa agujeros PMTU temprano.
- Verifica alcance saliente a tus mirrors de paquetes y endpoints de monitorización.
Minuto 12–16: Tiempo, actualizaciones y supervisor de servicios
- Confirma sincronización de tiempo y zona horaria (y que se mantenga sincronizada).
- Confirma la política de actualizaciones automáticas (o tu proceso de parches). “Lo haremos después” es una mentira que la gente se dice a sí misma.
- Confirma salud de systemd y persistencia de logs.
Minuto 16–20: Observabilidad + backups (prueba que funcionan)
- Instala un agente mínimo de métricas/envío de logs o al menos habilita logs persistentes.
- Crea un primer snapshot (VM o sistema de ficheros) una vez que el sistema sea “conocido-bueno”.
- Ejecuta un trabajo de backup y luego intenta una pequeña restauración. Sí, inmediatamente.
Broma corta #1: Las copias de seguridad son como paracaídas: si descubres que no funcionan durante el salto, tu postmortem será breve.
Tareas prácticas con comandos, salidas y decisiones
El objetivo de los comandos no es coleccionar trivia. Cada comando debe responder: “¿Qué es verdadero?” y “¿Qué hago después?”. Abajo hay tareas prácticas que puedes ejecutar en la mayoría de distribuciones Linux modernas. Ajusta rutas y herramientas según sea necesario, pero mantiene la intención.
Tarea 1: Confirma OS, kernel y arquitectura
cr0x@server:~$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
ID=ubuntu
cr0x@server:~$ uname -r
6.8.0-31-generic
cr0x@server:~$ uname -m
x86_64
Qué significa la salida: Tienes la release exacta de la distro, la línea de kernel y la arquitectura CPU. Esto afecta la disponibilidad de paquetes, valores por defecto del kernel (planificadores I/O, cgroups) y comportamiento de drivers.
Decisión: Confirma que esto coincide con tu política de soporte. Si necesitas un kernel específico o un LTS menor para drivers (HBA/NIC), decide ahora—antes de que existan datos de producción.
Tarea 2: Confirma virtualización / entorno cloud
cr0x@server:~$ systemd-detect-virt
kvm
cr0x@server:~$ cat /sys/class/dmi/id/product_name
KVM
Qué significa: Estás en KVM. El nombre de discos, comportamiento del reloj y techos de I/O pueden diferir del metal desnudo.
Decisión: Si esperabas metal desnudo, detente y escala. Si esperabas una VM, revisa tus suposiciones de rendimiento de almacenamiento (los dispositivos de bloque respaldados por red pueden estar “bien” hasta que no lo estén).
Tarea 3: Registra CPU y memoria básicas (captura la subprovisión)
cr0x@server:~$ lscpu | sed -n '1,12p'
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Vendor ID: GenuineIntel
Model name: Intel(R) Xeon(R)
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
Virtualization: VT-x
L1d cache: 64 KiB
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 7.7Gi 420Mi 6.6Gi 4.0Mi 720Mi 7.1Gi
Swap: 0B 0B 0B
Qué significa: Tienes 4 vCPUs, ~8 GiB RAM y no hay swap configurado.
Decisión: Decide explícitamente sobre swap. Para muchas cargas de servidor, un swap pequeño puede prevenir el caos del OOM-killer; para cargas sensibles a latencia, quizá prefieras no tener swap y establecer límites de memoria estrictos. No dejes que la configuración por defecto derive accidentalmente.
Tarea 4: Confirma discos, modelos y transporte
cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MODEL,TRAN,ROTA,MOUNTPOINTS
NAME TYPE SIZE MODEL TRAN ROTA MOUNTPOINTS
vda disk 120G Virtio Block Dev virtio 1
├─vda1 part 1G 1 /boot
└─vda2 part 119G 1 /
Qué significa: Un disco virtio, rotational=1 (a menudo sin sentido en VMs pero sigue siendo una pista). Root y boot comparten el mismo disco.
Decisión: Si esto alojará bases de datos, colas o logs intensos, planifica volúmenes o puntos de montaje separados ahora (o muévelo a LVM/ZFS). Un único root en un disco es la forma en que obtienes outages por “disco lleno” debido a logs parlanchines.
Tarea 5: Verifica tipo de sistema de ficheros y opciones de montaje
cr0x@server:~$ findmnt -no SOURCE,FSTYPE,OPTIONS /
/dev/vda2 ext4 rw,relatime,errors=remount-ro
cr0x@server:~$ findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS /boot
/boot /dev/vda1 ext4 rw,relatime
Qué significa: ext4 con valores por defecto razonables. errors=remount-ro puede salvarte de corrupción silenciosa a costa de convertir errores en dolor inmediato. Es un buen trade-off.
Decisión: Mantén valores sensatos a menos que tengas una razón medida. Si usas SSDs y te importa la amplificación de escritura, revisa noatime vs relatime y tus necesidades de monitorización.
Tarea 6: Revisa espacio libre y margen de inodos
cr0x@server:~$ df -hT /
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda2 ext4 117G 6.1G 105G 6% /
cr0x@server:~$ df -ihT /
Filesystem Type Inodes IUsed IFree IUse% Mounted on
/dev/vda2 ext4 7.5M 132K 7.4M 2% /
Qué significa: Espacio e inodos están saludables. El agotamiento de inodos es una trampa clásica de “disco lleno pero no realmente” con archivos pequeños (caches, colas de mail, capas de contenedores).
Decisión: Si esperas muchos archivos pequeños, considera sistemas de ficheros separados con ratios de inodos a medida, o mueve esas cargas a object storage o a una base de datos diseñada para eso.
Tarea 7: Establece una línea base rápida de I/O (la latencia importa más que MB/s)
cr0x@server:~$ sudo apt-get update -y
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 http://security.ubuntu.com/ubuntu noble-security InRelease [110 kB]
Fetched 110 kB in 1s (160 kB/s)
Reading package lists... Done
cr0x@server:~$ sudo apt-get install -y fio
Setting up fio (3.36-1) ...
cr0x@server:~$ fio --name=randread --filename=/tmp/fio.test --size=1G --rw=randread --bs=4k --iodepth=32 --numjobs=1 --direct=1 --runtime=20 --time_based --group_reporting
randread: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=32
fio-3.36
randread: (groupid=0, jobs=1): err= 0: pid=2176: Thu Feb 5 10:11:02 2026
read: IOPS=18.4k, BW=71.9MiB/s (75.4MB/s)(1.40GiB/20001msec)
slat (usec): min=3, max=140, avg=9.12, stdev=2.88
clat (usec): min=179, max=4112, avg=1726.44, stdev=312.20
lat (usec): min=188, max=4124, avg=1735.81, stdev=312.34
Qué significa: IOPS de lectura aleatoria y, más importante, la distribución de latencia. Un avg ~1.7ms puede estar bien para cargas generales; puede ser mortal para una base de datos sensible a latencia de cola larga.
Decisión: Si la latencia es mayor de lo esperado, investiga el backend de almacenamiento (virtio en bloque respaldado por red, caching del host, overhead de cifrado). No “optimices” la aplicación hasta saber que el disco no está silenciosamente ardiendo.
Tarea 8: Revisa interfaces de red, direcciones y estado de enlace
cr0x@server:~$ ip -br addr
lo UNKNOWN 127.0.0.1/8 ::1/128
ens3 UP 10.20.14.37/24 fe80::5054:ff:fe2a:1b2c/64
cr0x@server:~$ ip route
default via 10.20.14.1 dev ens3 proto dhcp src 10.20.14.37 metric 100
10.20.14.0/24 dev ens3 proto kernel scope link src 10.20.14.37
Qué significa: La interfaz está UP, tiene una IP y hay una ruta por defecto.
Decisión: Si esto es producción, decide si DHCP es aceptable. Para servidores, la direccionamiento estático (o reservas DHCP con inventario estricto) suele valer la pena.
Tarea 9: Verifica resolución DNS y configuración de resolvers
cr0x@server:~$ resolvectl status | sed -n '1,25p'
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.20.0.53
DNS Servers: 10.20.0.53 10.20.0.54
cr0x@server:~$ getent hosts archive.ubuntu.com
2620:2d:4000:1::19 archive.ubuntu.com
91.189.91.83 archive.ubuntu.com
Qué significa: Sabes qué resolvers estás usando y la resolución de nombres funciona.
Decisión: Si los resolvers son “IPs misteriosas”, arréglalo ahora. También decide si necesitas DNS dividido, dominios de búsqueda o validación DNSSEC (raro internamente, pero conoce la elección).
Tarea 10: Revisa MTU y salud básica de la ruta
cr0x@server:~$ ip link show ens3 | sed -n '1,2p'
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:2a:1b:2c brd ff:ff:ff:ff:ff:ff
cr0x@server:~$ ping -c 3 10.20.14.1
PING 10.20.14.1 (10.20.14.1) 56(84) bytes of data.
64 bytes from 10.20.14.1: icmp_seq=1 ttl=64 time=0.335 ms
64 bytes from 10.20.14.1: icmp_seq=2 ttl=64 time=0.284 ms
64 bytes from 10.20.14.1: icmp_seq=3 ttl=64 time=0.290 ms
cr0x@server:~$ ping -M do -s 1472 -c 2 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 1472(1500) bytes of data.
1472 bytes from 8.8.8.8: icmp_seq=1 ttl=115 time=2.31 ms
1472 bytes from 8.8.8.8: icmp_seq=2 ttl=115 time=2.28 ms
Qué significa: MTU es 1500 y puedes pasar un paquete de tamaño completo sin problemas de fragmentación.
Decisión: Si se esperan jumbo frames (MTU 9000), confirma extremo a extremo. MTUs mixtos crean tickets de “todo funciona excepto lo importante”.
Tarea 11: Confirma sincronización de tiempo y salud del reloj
cr0x@server:~$ timedatectl
Local time: Thu 2026-02-05 10:14:21 UTC
Universal time: Thu 2026-02-05 10:14:21 UTC
RTC time: Thu 2026-02-05 10:14:22
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
cr0x@server:~$ chronyc tracking
Reference ID : 0A140035 (10.20.0.53)
Stratum : 3
Last offset : -0.000021 seconds
RMS offset : 0.000110 seconds
Frequency : 11.432 ppm fast
Skew : 0.221 ppm
Root delay : 0.001234 seconds
Root dispersion : 0.000532 seconds
Update interval : 64.2 seconds
Leap status : Normal
Qué significa: La sincronización de tiempo está activa y estable. El offset es mínimo. Bien.
Decisión: Si el tiempo no está sincronizado, arréglalo antes de desplegar cualquier cosa con TLS, Kerberos, JWTs o correlación de logs. Es decir: todo.
Tarea 12: Revisa systemd por unidades fallidas (captura roturas silenciosas)
cr0x@server:~$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
0 loaded units listed.
Qué significa: No hay unidades fallidas. Esa es la línea base que quieres preservar.
Decisión: Si algo está fallado, lee logs ahora, no durante un outage. Una unidad “failed” podría ser tu agente de monitorización, tu timer de backup o la red.
Tarea 13: Confirma persistencia de logs y controles de uso de disco
cr0x@server:~$ sudo grep -E '^(Storage|SystemMaxUse|RuntimeMaxUse)=' /etc/systemd/journald.conf | grep -v '^#' || true
cr0x@server:~$ journalctl --disk-usage
Archived and active journals take up 64.0M in the file system.
Qué significa: journald está usando valores por defecto; la persistencia puede ser solo en runtime dependiendo de la distro y la presencia del directorio.
Decisión: Decide si los logs deben sobrevivir al reboot. Para depuración en producción, hazlos persistentes y limita el uso para que los logs no se coman el filesystem root.
Tarea 14: Confirma el estado del firewall (y no finjas que “security group” es suficiente)
cr0x@server:~$ sudo nft list ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Qué significa: La política del firewall está ampliamente abierta.
Decisión: Si este host es accesible más allá de una red estrechamente controlada, ciérralo. Incluso en redes “privadas”, el movimiento lateral existe. Establece deny por defecto para inbound, permite lo que necesites y registra los drops a una tasa sensata.
Tarea 15: Confirma configuración SSH y acceso solo por llave
cr0x@server:~$ sudo sshd -T | egrep '^(port|passwordauthentication|permitrootlogin|pubkeyauthentication|kexalgorithms|macs|ciphers)'
port 22
passwordauthentication no
permitrootlogin prohibit-password
pubkeyauthentication yes
kexalgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
macs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
Qué significa: La autenticación por contraseña está deshabilitada, el login root está restringido y el cifrado moderno está habilitado.
Decisión: Si la autenticación por contraseña está activada, apágala una vez confirmes llaves y acceso break-glass. Si el login root está permitido, arréglalo salvo que tengas una excepción estrictamente gestionada.
Tarea 16: Confirma la política de actualizaciones (los parches de seguridad no son opcionales)
cr0x@server:~$ apt-cache policy | sed -n '1,20p'
Package files:
100 /var/lib/dpkg/status
release a=now
Pinned packages:
cr0x@server:~$ systemctl status unattended-upgrades --no-pager
● unattended-upgrades.service - Unattended Upgrades Shutdown
Loaded: loaded (/lib/systemd/system/unattended-upgrades.service; enabled)
Active: inactive (dead)
Qué significa: Unattended upgrades está instalado/habilitado (común en Ubuntu). La unidad puede mostrarse inactiva porque corre periódicamente vía timers.
Decisión: Elige: actualizaciones de seguridad automáticas, o una ventana programada de parches con monitorización y enforcement. Lo que no eliges es “esperanza”.
Tarea 17: Confirma la línea de comandos del kernel (captura flags accidentales)
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.0-31-generic root=/dev/vda2 ro quiet splash
Qué significa: Nada exótico. Bien.
Decisión: Si ves flags de tuning que no pusiste (deshabilitar mitigaciones, cambiar IOMMU, forzar nombres legacy), documenta por qué. Flags de kernel desconocidos son cómo heredas riesgo.
Tarea 18: Confirma los mayores consumidores rápido (CPU, memoria, I/O) después de desplegar cualquier cosa
cr0x@server:~$ top -b -n 1 | sed -n '1,20p'
top - 10:17:02 up 1:21, 1 user, load average: 0.08, 0.04, 0.01
Tasks: 115 total, 1 running, 114 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.2 us, 0.8 sy, 0.0 ni, 97.8 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 7872.4 total, 6760.8 free, 430.7 used, 680.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 7441.7 avail Mem
Qué significa: La carga es baja, CPU idle alta, iowait cero. Esta es una línea base “tranquila”.
Decisión: Captura esta salida una vez. Luego, cuando alguien diga “está lento”, tendrás un ancla antes/después.
Almacenamiento: particionado, sistemas de ficheros y el “tú del futuro”
La mayoría de outages que he visto que empiezan con “la app está lenta” terminan con “el disco se llenó”, “el disco miente” o “construimos el almacenamiento sobre una suposición”. El almacenamiento es silencioso hasta que no lo es. Y cuando no lo es, lo lleva todo abajo.
Particionado: elige dominios de fallo a propósito
Las particiones root únicas están bien para VMs de corta vida y servicios sin estado. Son una trampa para cualquier cosa que emita logs, almacene archivos de cola, caches, capas de contenedores o datos de bases de datos.
Qué hacer:
- Separa
/var(o al menos/var/log) si esperas logs ruidosos o churn de paquetes. - Separa datos de aplicación (p. ej.,
/srvo/var/lib/<service>) del OS. - Si debes mantener un solo sistema de ficheros, aplica retención de logs y establece cuotas/límites donde sea posible.
Elección de sistema de ficheros: lo aburrido es una característica
ext4 y XFS son “aburridos” en el mejor sentido: modos de fallo entendidos, herramientas predecibles y rutas de recuperación maduras.
ZFS es fantástico cuando necesitas snapshots, checksums, replicación e integridad de datos con una historia administrativa coherente. Pero ZFS requiere que respetes RAM, recordsize, ashift y el hecho de que es una plataforma de almacenamiento, no una opción de montaje.
Comportamiento de SSD: TRIM y el mito de IOPS infinitos
Para almacenamiento respaldado por SSD, asegura que TRIM/discard sea apropiado. El discard continuo puede ser bueno o dañino dependiendo del backend; TRIM programado (fstrim timer) es un compromiso común.
Además: los SSD son rápidos en muchas cosas y sorprendentemente malos en otras. La latencia de escritura aleatoria bajo carga sostenida puede pasar de “agradable” a “por qué estamos haciendo swap al CEO” si el dispositivo o backend está saturado.
Cifrado: decide, mide y luego estandariza
El cifrado de disco (LUKS) a menudo es obligatorio, a veces opcional y siempre algo que deberías benchmarkear. La aceleración por hardware suele hacerlo barato. Flags de CPU malas o ausencia de aceleración lo hacen menos barato.
Haz la decisión explícita: ¿cifrar disco OS? ¿cifrar discos de datos? ¿quién guarda las claves? ¿cómo haces arranques desatendidos en una VM? Si no puedes responder eso claramente, no has terminado.
Red: verifica la realidad, no los diagramas
Las redes son sistemas políticos con paquetes. Tu checklist de instalación necesita confirmar lo que es verdadero: rutas, resolvers, MTU y qué límite de seguridad realmente aplica la política.
DNS: la dependencia de tu dependencia
Verifica los resolvers, y verifica que sean los correctos para tu entorno. Las configuraciones de DNS más comunes que veo tras instalaciones:
- Usar un resolver por defecto que no puede resolver zonas internas.
- Dominios de búsqueda que causan búsquedas lentas y colisiones raras de nombres.
- Dos resolvers listados, uno muerto; la mitad de tus consultas cuelgan en timeouts.
MTU: un ajuste pequeño, gran radio de impacto
Cuando hay desajustes de MTU, parte del tráfico funciona. Entonces tu VPN falla, la replicación de base de datos se detiene o tu overlay de contenedores empieza a perder paquetes grandes. Verifica temprano con pings “no fragmentar” a destinos representativos.
Egreso importa
Un servidor que no puede alcanzar repositorios de paquetes, servidores de tiempo, endpoints de certificados o la ingesta de monitorización es un servidor que se pudre silenciosamente. Confirma el egress ahora. Si estás en un entorno cerrado, documenta los destinos y puertos exactos requeridos para que los cambios de firewall no se conviertan en folklore.
Seguridad: endurecer sin romper las operaciones
El endurecimiento de seguridad falla de dos maneras: no haces nada y te comprometen, o haces “todo” y bloqueas a las personas que deben arreglar producción.
SSH: llaves, exposición mínima, acceso predecible
- Usa autenticación por llave. Deshabilita password auth tras verificar que tienes llaves funcionales.
- No permitas login directo de root. Usa sudo con auditoría.
- Restringe SSH a redes de gestión cuando sea posible.
Firewall: deny por defecto inbound, permitir explícitamente
Si tu entorno ya usa controles de seguridad de red, genial. Aún así, establece un firewall de host salvo que exista una razón estricta para no hacerlo (algunos appliances, algunos balanceadores, hosts de routing especializados). Defensa en profundidad no es un slogan; es cómo sobrevives a una regla upstream mal aplicada.
Menor privilegio: usuarios y servicios
Crea cuentas de servicio. Evita ejecutar procesos de aplicación como root. Si necesitas puertos privilegiados o acceso a nivel kernel, sé explícito con capabilities, hardening de unidades systemd y documentación.
Broma corta #2: La excepción de firewall “temporal” es el empleado más permanente en la mayoría de empresas.
Observabilidad: logs, métricas y tiempo
Las instalaciones nuevas son cuando decides si depurar será ingeniería o sesión de espiritismo.
La sincronización de tiempo es el esqueleto de la observabilidad
Si las marcas temporales derivan, la línea de tiempo del incidente se vuelve fan fiction. Mantén sistemas en UTC a menos que tengas una razón sólida para no hacerlo. Configura NTP/chrony, confirma sincronización y móntoreala.
Logs: hazlos persistentes, acotados y buscables
Como mínimo:
- Asegura persistencia de journald (
/var/log/journal) o configura rsyslog para almacenar en disco. - Limita el almacenamiento de logs para que no consuma el filesystem root.
- Envía logs centralmente si ejecutas más de un servidor. “SSH y grep” no escala más allá del primer outage estresante.
Métricas: captura las aburridas
CPU, memoria, latencia de disco, uso de filesystem, errores de red y conteos de procesos no son “observabilidad avanzada”. Son el mínimo. Captúralos desde el día uno para poder responder: “¿Esto es nuevo o normal?”
Core dumps: decide la política antes de necesitarlos
Los core dumps pueden ahorrar días al depurar un crash. También pueden filtrar secretos y consumir disco. Decide:
- Habilita core dumps para servicios específicos en ubicaciones controladas.
- Deshabilítalos o limítalos en sistemas sensibles donde la política lo prohíba.
- Siempre limita tamaño y ubicación de almacenamiento, y trata los dumps como artefactos sensibles.
Copias de seguridad: demuestra la restauración, no la intención
Las copias de seguridad fallan de maneras previsibles: no se ejecutan, se ejecutan pero almacenan datos vacíos, almacenan datos que no puedes descifrar, o almacenan datos que no puedes restaurar lo suficientemente rápido como para importar.
Diseño mínimo viable de backup
- Define alcance: ¿El OS es reconstruible? Entonces no pierdas tiempo haciendo backup del OS; haz backup de la config y los datos.
- Define RPO/RTO: cuánto dato puede perderse y qué tan rápido debes recuperarte.
- Haz de la restauración una prueba de primera clase: cada host nuevo debería tener un drill de restauración.
Qué hacer inmediatamente después de instalar
- Crea un snapshot inicial (a nivel VM o sistema de ficheros) una vez que las comprobaciones base pasen.
- Ejecuta un trabajo de backup y restaura un archivo o directorio pequeño a una ruta distinta. Verifica el contenido.
- Verifica que credenciales y claves de cifrado estén en tu secret manager y accesibles bajo procedimientos de break-glass.
Si tu solución de backup es “tenemos RAID”, para. Vuelve a leer esa frase y luego arregla tu vida.
Guion de diagnóstico rápido: encuentra el cuello de botella rápido
Cuando una instalación nueva “se siente lenta”, no empieces con tuning de la aplicación. Empieza con las rutas críticas del sistema. Este guion está ordenado: las primeras comprobaciones capturan los modos de fallo más comunes y de mayor impacto.
Primero: ¿la máquina está hambrienta o enferma?
- Revisa carga y saturación: CPU, iowait, presión de memoria.
- Revisa servicios fallidos: red, sincronización de tiempo, mounts de almacenamiento, fallos de agentes.
- Revisa disco lleno / inodos agotados: es el clásico porque funciona.
cr0x@server:~$ uptime
10:20:11 up 1:24, 1 user, load average: 0.12, 0.06, 0.02
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 6758208 88240 650240 0 0 1 4 75 98 1 1 98 0 0
0 0 0 6758120 88240 650240 0 0 0 0 70 90 0 0 100 0 0
1 0 0 6758020 88240 650240 0 0 0 12 88 120 2 1 97 0 0
0 0 0 6757908 88240 650240 0 0 0 0 66 85 0 0 100 0 0
0 0 0 6757800 88240 650240 0 0 0 0 69 89 0 0 100 0 0
Interpretación: Un wa alto significa espera de I/O; un r en aumento significa procesos ejecutables acumulándose; si/so distinto de cero significa swapping. Decide si estás limitado por CPU, I/O o memoria.
Segundo: ¿es el almacenamiento el factor limitante?
- Revisa latencia y utilización del dispositivo.
- Revisa errores de sistema de ficheros y estado de montaje.
- Revisa culpables de amplificación de escritura (logs, journaling, servicios parlanchines).
cr0x@server:~$ iostat -xz 1 3
Linux 6.8.0-31-generic (server) 02/05/2026 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
1.21 0.00 0.62 0.05 0.00 98.12
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await r_await w_await
vda 5.00 8.00 80.0 120.0 0.00 0.50 2.10 1.10 0.90 1.25
Interpretación: await incrementándose y %util cerca de 100 indica saturación. Si la latencia es alta antes de tener carga real, tu backend está constreñido.
Tercero: ¿es la red el cuello de botella?
- Revisa pérdida de paquetes y RTT hacia dependencias clave.
- Revisa latencia y fallos DNS.
- Revisa retransmisiones y errores de interfaz.
cr0x@server:~$ ip -s link show ens3 | sed -n '1,12p'
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:2a:1b:2c brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
1283942 9321 0 0 0 0
TX: bytes packets errors dropped carrier collsns
902211 8010 0 0 0 0
cr0x@server:~$ dig +stats +time=2 +tries=1 archive.ubuntu.com A | tail -n 5
;; Query time: 21 msec
;; SERVER: 10.20.0.53#53(10.20.0.53)
;; WHEN: Thu Feb 05 10:22:01 UTC 2026
;; MSG SIZE rcvd: 79
Interpretación: La interfaz no tiene errores/drops; DNS es rápido. Si el tiempo de consulta son cientos/miles de ms, DNS es tu generador de latencia aleatoria.
Cuarto: valida las dependencias de la app, no solo la app
Bases de datos, brokers, object storage, proveedores de auth y servidores de licencias pueden ser el cuello de botella. Un diagnóstico rápido significa identificar qué dependencia es lenta y luego qué capa (red vs almacenamiento vs CPU) la está causando.
Errores comunes: síntomas → causa raíz → solución
1) Síntoma: el disco se llena durante la noche
Causa raíz: Logs por defecto demasiado verbosos, journald sin límites o una app que escribe logs de debug en /var/log sin rotación.
Solución: Limita journald, configura logrotate y separa /var o /var/log si el host tiene muchos logs. Verifica con journalctl --disk-usage y df -h.
2) Síntoma: SSH funciona, pero instalaciones de paquetes cuelgan aleatoriamente
Causa raíz: Resolver DNS parcialmente roto; un resolver hace timeout, causando demoras intermitentes.
Solución: Usa resolvectl status para identificar servidores, elimina resolvers muertos y confirma tiempos de consulta con dig +stats. Si usas systemd-resolved en modo stub, asegúrate de que los upstreams sean correctos.
3) Síntoma: errores TLS, “certificate not yet valid”, fallos de auth raros
Causa raíz: Tiempo no sincronizado; chrony/NTP deshabilitado o bloqueado.
Solución: Habilita sincronización de tiempo, asegura que UDP 123 a fuentes NTP esté permitido (o lo que use tu entorno), verifica con timedatectl y chronyc tracking.
4) Síntoma: “el servidor está lento” solo durante backups
Causa raíz: El job de backup satura I/O de disco o red; sin limitación de ancho de banda; los snapshots causan amplificación copy-on-write en ciertos sistemas de ficheros.
Solución: Mide con iostat -xz durante el backup, establece límites de tasa, prográmalo fuera de pico y considera diseños amigables con snapshots. Prueba también la velocidad de restauración, no solo la de backup.
5) Síntoma: el reboot tarda una eternidad y luego los servicios faltan datos
Causa raíz: fscks o montajes fallando; volumen de datos no montado; el sistema continúa con directorios vacíos.
Solución: Usa systemctl --failed, journalctl -b y findmnt. Añade x-systemd.automount o dependencias si procede, pero no enmascares la falla. Asegura que los puntos de montaje no se creen silenciosamente en root.
6) Síntoma: regresiones de rendimiento después de “tunear”
Causa raíz: Cambiar parámetros de kernel/sysctl sin mediciones base; usar una guía de tuning escrita para kernels o almacenamiento diferentes.
Solución: Captura una base (fio, iostat, vmstat) antes de tunear. Cambia una variable a la vez, registra resultados y estate dispuesto a revertir. Producción no es tu laboratorio.
7) Síntoma: resets de conexión intermitentes bajo carga
Causa raíz: Desajuste de MTU o PMTU discovery bloqueado; a veces solo fallan paquetes grandes.
Solución: Valida con ping -M do y prueba entre nodos clave. Corrige MTU de forma consistente a lo largo del path, o permite fragmentación/ICMP según la política.
8) Síntoma: no se puede entrar durante un incidente; solo un admin tiene acceso
Causa raíz: No hay camino break-glass, no hay llave administrativa secundaria, no hay acceso a consola documentado.
Solución: Añade al menos dos llaves admin, confirma que sudo funciona, documenta acceso a consola/fuera de banda y pruébalo. “Creo que funciona” no es un control.
Tres micro-historias corporativas desde las trincheras
Micro-historia #1: El incidente causado por una suposición errónea
La Compañía A desplegó un nuevo lote de servidores de aplicación. El build era “estándar” y el equipo estaba orgulloso: aprovisionamiento automatizado, paquetes consistentes, tipos de instancia idénticos. Incluso tenían una checklist, pero era más una lista de compras: instalar agente, instalar app, listo.
Dos semanas después, tuvieron una oleada de errores intermitentes: timeouts de base de datos y picos de recuperación. Las gráficas de CPU parecían bien. La memoria parecía bien. El equipo de base de datos insistía en que no era culpa suya, lo cual era técnicamente cierto y culturalmente sospechoso.
El culpable fue una suposición errónea: que el almacenamiento que respaldaba los discos VM era SSD local. No lo era. Un cambio en el clúster de virtualización había movido esas VMs a una clase de almacenamiento por bloques respaldada por red con caching agresivo y latencias tail impredecibles. Bajo carga normal, parecía OK. Bajo ráfagas, la latencia de escritura aleatoria se disparó, la cola local de la app se llenó y todo lo downstream pareció culpable.
La solución fue poco glamorosa: añadieron una simple comprobación fio a la pipeline de provisioning, registraron percentiles de latencia y fallaron el build si caía en la clase de almacenamiento equivocada. También separaron el directorio de cola en un volumen dedicado con rendimiento predecible. El incidente no les enseñó a “optimizar”. Les enseñó a verificar lo que pagaron.
Micro-historia #2: La optimización que salió mal
La Compañía B tenía un problema que parecía de almacenamiento: volumen alto de logs de un servicio parlanchín. Alguien sugirió una “victoria rápida”: montar el filesystem de logs con opciones más agresivas para reducir escrituras. Cambiaron opciones de montaje y retocaron algunos sysctls encontrados en un post de tuning. La máquina parecía bien la primera hora. Todos felices se fueron a casa.
Luego llegó el revés. Tras un reboot no limpio (mantenimiento del host, nada exótico), el filesystem necesitó recuperación. El tiempo de arranque se disparó. Peor aún, el servicio reanudó con pérdida de datos sutil en su directorio de estado local porque asumía ciertas semánticas fsync que se habían debilitado con la “optimización”. La app no estaba diseñada para eso. La mayoría no lo está.
Lo que lo hizo doloroso no fue solo la regresión. Fue la falta de medición. Sin números base de I/O. Sin nota de exactamente qué cambió. Sin plan rápido de rollback. El equipo gastó más tiempo probando causalidad que arreglando el problema.
Eventualmente revirtieron a valores seguros, movieron logs a un volumen separado con rotación estricta y redujeron la verbosidad de logs en origen. La lección a largo plazo: si no puedes explicar el tuning en una frase y validarlo con una medición antes/después, no es tuning. Es cargo cult.
Micro-historia #3: La práctica aburrida pero correcta que salvó el día
La Compañía C operaba una flota de servicios internos poco glamorosos: schedulers, APIs glue, pequeñas bases de datos. Nada para conferencias. El equipo tenía un hábito que parecía excesivamente cauteloso: después de cada instalación nueva, ejecutaban una prueba de restauración.
No un drill anual. No un “validamos el sistema de backups”. Una restauración literal de un subconjunto pequeño de datos desde el target de backup a un directorio alternativo en el host nuevo. Cada vez. El ritual fue tan consistente que se convirtió en parte de la definición de hecho del aprovisionamiento.
Un día rotaron credenciales para el target de backup. Las nuevas credenciales se desplegaron en la mayoría de hosts, pero no en todos. La monitorización mostró backups “corriendo”, pero un subconjunto fallaba con errores de auth. Los fallos estaban enmascarados por un loop de reintentos que registraba warnings que nadie leía porque, claro, los logs eran ruidosos.
La prueba de restauración lo detectó inmediatamente en hosts nuevos. El equipo arregló el rollout de credenciales antes de que la brecha se convirtiera en desastre. Sin heroicidades, sin war room, sin reconstrucción de fin de semana. Solo una práctica aburrida con alta relación señal/ruido.
Preguntas frecuentes
1) ¿Qué tan estricta debe ser esta checklist para entornos de dev?
Más estricta de lo que crees. Los sistemas de dev son donde nacen malos valores por defecto, que luego se promueven a producción vía “funcionó en staging”. Puedes omitir algo de hardening, pero no omitas líneas base, sincronización de tiempo y saneamiento del layout de disco.
2) ¿Debo usar ext4, XFS o ZFS?
Usa ext4 o XFS cuando quieras operaciones predecibles y bien entendidas y no necesites features avanzadas de snapshot/replicación. Usa ZFS cuando realmente vayas a usar sus fortalezas (checksums, snapshots, replicación) y puedas operarlo con disciplina.
3) ¿Swap sigue siendo cosa en servidores?
Sí. La respuesta correcta depende de la carga y de la tolerancia a fallos. Un swap pequeño puede suavizar picos y prevenir OOM kills. Pero el swapping no controlado puede destruir la latencia. Decide explícitamente, monitorea y prueba bajo carga.
4) ¿Realmente necesito un firewall de host si mi red tiene security groups?
Normalmente sí. Los security groups se aplican mal, se duplican o se abren temporalmente. Un firewall de host es una segunda cerradura. También documenta la intención directamente en la máquina.
5) ¿Cuál es la observabilidad mínima para un solo servidor?
Logs persistentes con rotación/caps, métricas de CPU/memoria/disco/red y monitorización de sincronización de tiempo. Si no puedes responder “¿qué cambió?” tras un incidente, estás poco instrumentado.
6) ¿Cómo evito incidentes de “disco lleno” sin sobreingeniería del almacenamiento?
Separa /var o al menos /var/log cuando sea factible, limita el uso de journald, configura logrotate y monitorea uso de filesystem con alertas que disparen antes del 95%.
7) ¿Cuándo debo benchmarkear disco con fio?
Una vez en un sistema limpio para establecer la línea base, y de nuevo tras cualquier cambio de backend de almacenamiento (nuevo host VM, nuevo tipo de volumen, cambios de cifrado). Mantén las pruebas pequeñas y controladas—no hagas arder discos de producción.
8) ¿Cuál es lo primero que revisar cuando “la app está lenta” en un host nuevo?
Latencia de disco (iostat), presión de memoria (vmstat) y latencia DNS (dig +stats). Esos tres se hacen pasar por problemas de aplicación constantemente.
9) ¿Cómo aseguro que los mounts no fallen silenciosamente?
Usa findmnt en health checks, asegura que unidades systemd dependan de mounts cuando sea necesario y vigila los logs de arranque. Evita diseños donde un mount faltante resulte en que la app escriba en root sin notarlo.
10) ¿Qué debo documentar desde una instalación nueva?
Versiones OS/kernel, layout de discos y tipos de sistemas de ficheros, config de red (IPs/rutas/DNS), fuentes de sincronización de tiempo, política de firewall, política de actualizaciones y resultados de verificación de backup/restauración. Si no está escrito, no sucedió.
Conclusión: próximos pasos que realmente perduran
Una lista de comprobación para instalaciones nuevas no es burocracia. Es reducción de latencia para tus incidentes futuros. Los minutos que pases ahora te compran velocidad después: diagnóstico más rápido, cambios más seguros, menos sorpresas de “cómo llegamos aquí?”.
Haz esto a continuación:
- Convierte esto en un runbook que tu equipo pueda ejecutar sin ti. Guárdalo con tu código de infraestructura.
- Automatiza las comprobaciones que se puedan automatizar: unidades failed, uso de disco, sincronización de tiempo, test base fio (donde sea seguro) y cheques de política de firewall/SSH.
- Requiere prueba para backups: una prueba de restauración por host nuevo, registrada como artefacto.
- Captura líneas base (CPU/memoria/disco/red) y almacénalas. Sin líneas base, solo tienes opiniones.
Si no haces nada más, recuerda la tesis: no estás instalando un servidor. Estás instalando una respuesta a incidentes futura. Haz que sea amable contigo.