Instalación de Ubuntu Server: mínima y realmente segura

¿Te fue útil?

Quieres una instalación pequeña de Ubuntu Server porque el exceso es una responsabilidad. También la quieres segura porque Internet es un incendio y tu servidor es el montón de neumáticos más cercano.

La trampa es pensar que “mínimo” significa automáticamente “seguro”. Un sistema pequeño con SSH descuidado, actualizaciones laxas y una disposición de disco que no pretendías crear sigue siendo un sistema pequeño listo para ser comprometido—o para despertarte a las 03:17 porque /var se llenó y se llevó journald con él.

Qué debe significar “mínimo” en producción

Mínimo no es “la ISO más pequeña”. Mínimo es un conjunto de restricciones deliberadas:

  • Superficie de ataque pequeña: menos demonios expuestos a la red, menos analizadores, menos dependencias.
  • Actualizaciones predecibles: las actualizaciones de seguridad llegan automáticamente; las actualizaciones de funciones se planifican.
  • Estado auditable: puedes explicar por qué existe un paquete y qué abrió ese puerto.
  • Almacenamiento recuperable: tu diseño de discos puede sobrevivir picos de logs, volcados de memoria y errores humanos.
  • Ergonomía operativa: journald funciona, la sincronización de tiempo funciona, DNS funciona y puedes diagnosticar problemas sin adivinar.

“Seguro” tampoco es una casilla de verificación. Es una postura: valores predeterminados sensatos, acceso remoto estricto, mínimo privilegio, parcheo puntual y suficiente observabilidad para detectar cosas antes que los clientes.

Una de mis verdades favoritas de producción es una idea parafraseada atribuida a menudo al mundo SRE: idea parafraseada: la esperanza no es una estrategia; la fiabilidad viene de bucles de retroalimentación diseñados — atribuida a la comunidad de operaciones/fiabilidad alrededor del pensamiento Google SRE.

Broma #1: La seguridad es como usar hilo dental: todos coinciden en que es bueno, y la mayoría lo hace solo después de que algo empieza a sangrar.

Hechos y contexto histórico que puedes usar a las 2 a.m.

Contexto corto y concreto te ayuda a tomar mejores decisiones bajo presión:

  1. Cadencia de Ubuntu LTS: las versiones LTS salen cada dos años; operativamente, ese ritmo se convirtió en estándar corporativo porque coincide con los ciclos presupuestarios y el control de cambios.
  2. systemd no “ganó” de la noche a la mañana: reemplazó un parcheado de scripts init con un modelo unificado (units, dependencias, watchdogs). Esa unificación es la razón por la que el diagnóstico Linux moderno es tan rápido—si aprendes las herramientas.
  3. Los valores por defecto de OpenSSH se endurecieron con el tiempo: la criptografía antigua se eliminó, no “se deprecó para siempre”. Si tu cliente antiguo falla, es una pista, no que Ubuntu sea antipático.
  4. UFW existe porque los humanos necesitan protecciones: iptables/nftables son poderosos, pero un modelo de políticas simple evita el incidente “accidentalmente permití que todo el mundo hablara con Redis”.
  5. journald reemplazó logs dispersos: metadatos estructurados (unit, PID, boot ID) son la razón de que “¿qué pasó desde el último reinicio?” sea ahora un comando.
  6. ext4 se volvió aburrido a propósito: se ganó esa reputación por fallar de forma predecible. Muchos equipos de producción lo eligen no porque sea emocionante, sino porque no los sorprende.
  7. LUKS se hizo habitual en portátiles y luego en servidores: el cifrado de disco pasó de “paranoico” a “mínimo de cumplimiento” cuando las leyes de reporte de brechas y los snapshots en la nube hicieron real el dato en reposo.
  8. Los secretos respaldados por TPM no son solo para escritorios: los servidores modernos esperan cada vez más raíces de confianza hardware; las herramientas de Ubuntu han seguido esa tendencia.
  9. Las actualizaciones automáticas de seguridad se normalizaron tras las eras de gusanos: la cultura operativa cambió cuando “Patch Tuesday” se convirtió en “parchear ahora o reconstruir después”.

Decisiones del instalador que no puedes deshacer fácilmente

1) Elige la ISO y el modo de instalación adecuados

Usa el instalador oficial de Ubuntu Server 24.04 LTS. Si instalas en hardware físico, prefiere la ISO estándar de servidor. Si lo vas a provisionar en la nube, tu “instalador” es mayoritariamente cloud-init más la selección de imagen.

Configuración mínima significa: sin GUI, sin roles de servidor “útiles” al instalar, sin snaps extras a menos que sepas por qué.

2) Red: DHCP primero, estática después (a menos que seas router)

Si este servidor no es tu infraestructura de red, empieza con DHCP para poder finalizar la instalación y obtener acceso remoto. Luego configura una reserva estática en DHCP o pasa a una configuración netplan estática una vez que conozcas el nombre de la interfaz y los DNS correctos.

El modo de fallo: te inventas una IP estática, tecleas mal la puerta de enlace y ahora tu única vía de gestión es un crash cart. Eso no es “seguro”, es simplemente solitario.

3) Usuarios: crea un usuario admin, sin cuentas compartidas

Crea un usuario inicial único con sudo. No habilites el inicio de sesión root por SSH. Trata las cuentas compartidas “admin” como un fallo de auditoría esperando ocurrir.

4) SSH: solo claves, y hazlo temprano

Si el instalador ofrece importar claves SSH (por ejemplo, desde una identidad alojada), hazlo. Si no, añade tu clave pública justo después del primer arranque. El inicio de sesión por contraseña sobre SSH es una responsabilidad que no necesitas.

5) Actualizaciones: automáticas para seguridad, reinicios deliberados

Habilita las actualizaciones de seguridad automáticas. No estás demostrando fortaleza rechazando aprobar manualmente cada CVE de OpenSSL. Solo estás creando una acumulación de riesgo.

6) Almacenamiento: decide tu radio de impacto

Tus elecciones de almacenamiento determinan cómo falla la máquina. Un único sistema de archivos raíz es simple hasta que los logs se disparan, los contenedores crecen o alguien deja una copia de seguridad en /var/tmp.

Para un enfoque mínimo-pero-seguro, apuntas a:

  • Una configuración EFI limpia (en hardware moderno).
  • Un /boot separado solo si lo necesitas (por ejemplo, algunas configuraciones de root cifrado).
  • Root cifrado si el modelo de amenazas incluye discos robados, unidades desechadas, manos remotas o cumplimiento.
  • Espacio separado para /var o al menos una retención de logs sensata. Si ejecutas contenedores, trata /var/lib como su propia zona de crecimiento.

Diseño de almacenamiento: elecciones aburridas, menos interrupciones

Seamos directos: el almacenamiento es donde “mínimo” con más frecuencia se vuelve “frágil”. Tu CPU te perdonará. Tu disco no.

Diseños base recomendados

Opción A (simple, fuerte por defecto): ext4 + LUKS en un solo disco

Bueno para: servidores generales, VMs, nodos de disco único, cualquier cosa que quieras recuperar con facilidad.

  • EFI System Partition (ESP): ~512 MiB
  • /boot (opcional): 1 GiB (sin cifrar si es necesario)
  • Contenedor LUKS que alberga LVM o ext4 simple para /

Por qué: ext4 es estable, LUKS te da protección en reposo y la recuperación no requiere un doctorado.

Opción B (control de crecimiento): ext4 + /var separado

Bueno para: cualquier cosa con logs, bases de datos, contenedores, runners de CI.

  • / (root): tamaño moderado (por ejemplo, 20–40 GiB)
  • /var: más grande, porque crecerá
  • /home: pequeño o ninguno (los servidores no deberían ser almacenamiento personal)

Por qué: root permanece sano incluso cuando /var se ensucia. Cuando /var se llena, aún puedes iniciar sesión y arreglarlo.

Opción C (especializada): ZFS en root

Bueno para: equipos que ya conocen operacionalmente ZFS. No es bueno para “escuché que ZFS está genial.” ZFS es un sistema, no solo un sistema de archivos.

Si eliges ZFS, comprométete a monitorizar la presión del ARC, los cronogramas de scrub y las interacciones con el cargador de arranque. Si no quieres esa tarea, usa ext4 y sigue adelante.

Opciones de montaje que reducen daños

Algunas opciones de montaje son ganancias baratas:

  • nodev en particiones que no deberían contener archivos de dispositivo (a menudo /home, /var/tmp).
  • nosuid donde no quieres que funcionen binarios setuid (a menudo /tmp, /var/tmp).
  • noexec puede ayudar en /tmp, pero cuidado: puede romper instaladores y herramientas. Úsalo con intención.

Esto no “te hace seguro” por sí solo. Reduce el radio de impacto de un mal día.

Línea base post-instalación: cuentas, SSH, firewall, actualizaciones

Paquetes: instala menos, elimina más

Empieza con lo que te da la imagen de servidor. Añade solo lo que tu función necesite. Si necesitas una herramienta para un rescate puntual, instálala, úsala y considera eliminarla después. Un servidor de producción no es tu portátil.

Endurecimiento SSH: autenticación por claves, superficie mínima, valores fuertes

Estado objetivo:

  • Autenticación basada en claves
  • No permitir login root por SSH
  • Usuarios o grupos restringidos permitidos para SSH
  • Tiempos de espera razonables por inactividad
  • Logs útiles sin ser ruidosos

Firewall: denegar entrantes por defecto, permitir solo lo que sirves

Si esto es un servidor, no debería aceptar tráfico entrante salvo que lo hayas decidido explícitamente. Ese es todo el punto de un firewall.

Actualizaciones de seguridad automáticas

Habilita unattended upgrades para parches de seguridad. Luego decide cómo manejar reinicios. Para muchas flotas: actualizaciones automáticas de seguridad más ventanas de reinicio programadas es el punto óptimo.

Sincronización de tiempo: porque los logs sin tiempo son fanfiction

systemd-timesyncd (o chrony si lo prefieres) asegura que tu TLS, logs y líneas de tiempo de incidentes no sean basura.

Broma #2: Nada te hace envejecer más rápido que depurar fallos “aleatorios” que en realidad eran deriva de tiempo.

Tareas prácticas (comandos, salidas, decisiones)

A continuación están las tareas reales que ejecutarás en una instalación fresca de Ubuntu Server 24.04. Cada una incluye: el comando, qué significa una salida típica y la decisión que tomas a continuación. Ejecútalas como tu usuario admin con sudo cuando haga falta.

Task 1: Confirmar lo que realmente instalaste

cr0x@server:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:        24.04
Codename:       noble

Qué significa: Estás en la versión LTS y codename correctos. Sin adivinanzas, sin “pensé que instalé 24.04”.

Decisión: Si esto no es 24.04 LTS, detente y corrige tu pipeline de imágenes antes de endurecer algo equivocado.

Task 2: Verificar kernel y modo de arranque (EFI vs legacy)

cr0x@server:~$ uname -r
6.8.0-31-generic
cr0x@server:~$ test -d /sys/firmware/efi && echo "UEFI boot" || echo "Legacy boot"
UEFI boot

Qué significa: La línea del kernel confirma lo que estás ejecutando. La presencia de UEFI importa para el particionado de discos y el comportamiento del gestor de arranque.

Decisión: Si esperabas UEFI y obtuviste legacy, ajusta la configuración del firmware ahora. Entornos mixtos causan recuperaciones de arranque raras más tarde.

Task 3: Ver tus discos, particiones y sistemas de archivos claramente

cr0x@server:~$ lsblk -e7 -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL
NAME        SIZE TYPE FSTYPE      MOUNTPOINTS MODEL
nvme0n1   476.9G disk                       Samsung SSD 980
├─nvme0n1p1  512M part vfat        /boot/efi
├─nvme0n1p2    1G part ext4        /boot
└─nvme0n1p3 475.4G part crypto_LUKS          
cr0x@server:~$ sudo cryptsetup status luks-root
/dev/mapper/luks-root is active and is in use.
  type:    LUKS2
  cipher:  aes-xts-plain64
  keysize: 512 bits
  device:  /dev/nvme0n1p3
  sector size:  512
  offset:  32768 sectors
  size:    997638144 sectors
  mode:    read/write

Qué significa: Puedes ver el mapa real de dispositivos. LUKS2 activo indica que el cifrado funciona.

Decisión: Si el cifrado era obligatorio y no ves crypto_LUKS, estás fuera de cumplimiento. Reinstala o migra correctamente; no lo “arregles después”.

Task 4: Comprobar uso de sistemas de archivos antes de que sea sorpresa

cr0x@server:~$ df -hT
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg0-root ext4    40G  3.2G   35G   9% /
/dev/nvme0n1p2 ext4  1007M  220M  720M  24% /boot
/dev/nvme0n1p1 vfat   511M  6.1M  505M   2% /boot/efi
tmpfs          tmpfs  3.1G     0  3.1G   0% /run/user/1000

Qué significa: Verificas que root no sea diminuto y que /boot tenga espacio para actualizaciones de kernel.

Decisión: Si /boot tiene menos de ~300–400 MiB libres, eventualmente fallarás al actualizar kernels. Arregla el tamaño de la partición o poda kernels antiguos intencionadamente.

Task 5: Confirmar qué está escuchando en la red

cr0x@server:~$ sudo ss -tulpen
Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
tcp   LISTEN 0      4096   0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=1020,fd=3)) uid:0 ino:27360 sk:3 cgroup:/system.slice/ssh.service

Qué significa: Solo SSH está escuchando. Esa es una línea base limpia.

Decisión: Si ves escuchas inesperadas (base de datos, servidor web, servicios RPC), desinstálalas/desactívalas o justifícalas. “No sabía que estaba corriendo” no es defensa.

Task 6: Establecer políticas de firewall (UFW)

cr0x@server:~$ sudo ufw status verbose
Status: inactive
cr0x@server:~$ sudo ufw default deny incoming
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
cr0x@server:~$ sudo ufw default allow outgoing
Default outgoing policy changed to 'allow'
(be sure to update your rules accordingly)
cr0x@server:~$ sudo ufw allow 22/tcp
Rule added
Rule added (v6)
cr0x@server:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
cr0x@server:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
22/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)

Qué significa: Has restringido el tráfico entrante a SSH solamente.

Decisión: Antes de habilitar UFW remotamente, asegúrate de que SSH esté permitido y de tener acceso por consola si la cagas. Regla de producción: nunca te cortes el acceso a una máquina que no puedes alcanzar físicamente.

Task 7: Endurecer la configuración SSH y validarla con seguridad

cr0x@server:~$ sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
cr0x@server:~$ sudoedit /etc/ssh/sshd_config

Líneas de endurecimiento mínimas de ejemplo a establecer (ajusta nombres de usuario/grupos):

cr0x@server:~$ sudo grep -nE '^(PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|AllowUsers|AllowGroups|X11Forwarding|ClientAliveInterval|ClientAliveCountMax)' /etc/ssh/sshd_config
33:PermitRootLogin no
57:PasswordAuthentication no
58:KbdInteractiveAuthentication no
89:X11Forwarding no
101:ClientAliveInterval 300
102:ClientAliveCountMax 2
cr0x@server:~$ sudo sshd -t
cr0x@server:~$ sudo systemctl reload ssh

Qué significa: sshd -t sin salida es éxito. Reload aplica cambios sin cerrar sesiones existentes.

Decisión: Si sshd -t imprime errores, no recargues. Arregla la configuración primero. Los errores de sintaxis son un clásico auto-golpe.

Task 8: Confirmar métodos de autenticación SSH desde logs

cr0x@server:~$ sudo journalctl -u ssh -n 20 --no-pager
Aug 01 10:12:44 server sshd[1442]: Accepted publickey for cr0x from 10.0.0.50 port 50192 ssh2: ED25519 SHA256:Qm...
Aug 01 10:13:02 server sshd[1461]: Connection closed by authenticating user ubuntu 10.0.0.51 port 55322 [preauth]

Qué significa: Ves inicios de sesión exitosos por clave pública. También puedes detectar intentos sospechosos o nombres de usuario inesperados.

Decisión: Si aún ves aceptación por contraseña, tu configuración SSH no está aplicada o estás editando el archivo sshd equivocado. Arregla eso ahora.

Task 9: Habilitar unattended-upgrades y verificar comportamiento

cr0x@server:~$ sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease
Reading package lists... Done
Building dependency tree... Done
All packages are up to date.
cr0x@server:~$ sudo apt install -y unattended-upgrades
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  unattended-upgrades
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
cr0x@server:~$ sudo systemctl status unattended-upgrades --no-pager
● unattended-upgrades.service - Unattended Upgrades Shutdown
     Loaded: loaded (/usr/lib/systemd/system/unattended-upgrades.service; enabled)
     Active: inactive (dead)

Qué significa: El servicio se ejecuta mediante timers y hooks de apagado; “inactive” puede ser normal.

Decisión: Asegúrate de que el timer esté habilitado y confirma que solo los repositorios de seguridad están seleccionados si quieres cambios mínimos.

Task 10: Comprobar timers de apt y último estado de ejecución

cr0x@server:~$ systemctl list-timers --all | grep -E 'apt|unattended'
Fri 2026-02-06 06:12:21 UTC  10h left   Thu 2026-02-05 06:13:02 UTC  13h ago  apt-daily.timer             apt-daily.service
Fri 2026-02-06 06:45:10 UTC  10h left   Thu 2026-02-05 06:45:22 UTC  13h ago  apt-daily-upgrade.timer     apt-daily-upgrade.service
cr0x@server:~$ sudo tail -n 30 /var/log/unattended-upgrades/unattended-upgrades.log
2026-02-05 06:45:23,121 INFO Starting unattended upgrades script
2026-02-05 06:45:23,210 INFO No packages found that can be upgraded unattended

Qué significa: Los timers están programados y se ejecutaron. Los logs muestran si ocurrieron actualizaciones.

Decisión: Si faltan timers, puede que estés en una imagen recortada o timers deshabilitados por política—corrige eso intencionalmente, no accidentalmente.

Task 11: Confirmar estado de sincronización de tiempo

cr0x@server:~$ timedatectl
               Local time: Thu 2026-02-05 20:10:17 UTC
           Universal time: Thu 2026-02-05 20:10:17 UTC
                 RTC time: Thu 2026-02-05 20:10:17
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Qué significa: El reloj está sincronizado y NTP está activo. UTC es un valor por defecto sensato para servidores.

Decisión: Si la sincronización es “no”, arregla el tiempo antes de depurar cualquier otra cosa. TLS y sistemas de clúster se comportan mal con deriva.

Task 12: Comprobar DNS y enrutamiento rápidamente (salud de red)

cr0x@server:~$ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp1s0           UP             10.0.10.25/24 fe80::a00:27ff:fe4e:66a1/64
cr0x@server:~$ ip r
default via 10.0.10.1 dev enp1s0
10.0.10.0/24 dev enp1s0 proto kernel scope link src 10.0.10.25
cr0x@server:~$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.0.10.2
       DNS Servers: 10.0.10.2 10.0.10.3

Qué significa: La interfaz está arriba, existe ruta por defecto y los servidores DNS están configurados.

Decisión: Si el DNS está mal, ajusta netplan o las opciones DHCP; no “trabajes alrededor” con hacks aleatorios en /etc/hosts salvo que sea un mapeo de servicio deliberado.

Task 13: Confirmar qué paquetes están instalados (detecta bloat accidental)

cr0x@server:~$ apt list --installed | head -n 15
Listing... Done
adduser/noble,now 3.137ubuntu1 all [installed]
apt/noble-updates,now 2.7.14 amd64 [installed]
base-files/noble,now 13ubuntu10 amd64 [installed]
bash/noble,now 5.2.21-2ubuntu4 amd64 [installed]
bsdutils/noble,now 1:2.39.3-9ubuntu6 amd64 [installed]

Qué significa: Puedes ver rápidamente el universo de paquetes que mantienes.

Decisión: Si ves roles de servidor que no pretendías (base de datos, pila de correo), elimínalos o reconstruye. Los demonios ocultos se vuelven “puertos misteriosos”.

Task 14: Confirmar que AppArmor está activo

cr0x@server:~$ sudo aa-status
apparmor module is loaded.
45 profiles are loaded.
45 profiles are in enforce mode.
0 profiles are in complain mode.
0 processes are unconfined but have a profile defined.

Qué significa: Control de acceso obligatorio está presente y en modo enforcement para perfiles conocidos.

Decisión: Si AppArmor está deshabilitado, estás eligiendo una línea base más débil. Vuelve a habilitar salvo que tengas una incompatibilidad probada y un plan de mitigación.

Task 15: Verificar privilegios de usuario y eliminar valores predeterminados riesgosos

cr0x@server:~$ id
uid=1000(cr0x) gid=1000(cr0x) groups=1000(cr0x),27(sudo)
cr0x@server:~$ sudo -l
Matching Defaults entries for cr0x on server:
    env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

User cr0x may run the following commands on server:
    (ALL : ALL) ALL

Qué significa: Tu usuario admin puede escalar, y la política sudo es la predeterminada.

Decisión: Para entornos corporativos, prefiere mínimo privilegio mediante políticas de sudoers por grupo. Para un servidor de propósito único, limita administradores y hazlos trazables.

Task 16: Detectar problemas de salud del disco antes de que sean “caídas aleatorias”

cr0x@server:~$ sudo apt install -y smartmontools
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  smartmontools
cr0x@server:~$ sudo smartctl -a /dev/nvme0n1 | head -n 20
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.8.0-31-generic] (local build)
=== START OF INFORMATION SECTION ===
Model Number:                       Samsung SSD 980
Serial Number:                      S64...
Firmware Version:                   2B4QFXO7
NVMe Version:                       1.4
Total NVM Capacity:                 500,107,862,016 [500 GB]

Qué significa: Puedes confirmar el dispositivo, el firmware y luego revisar contadores de errores.

Decisión: Si los datos SMART muestran errores de medio o advertencias críticas, reemplaza el disco. No discutas con la física.

Guion de diagnóstico rápido (encuentra el cuello de botella rápido)

Este es el playbook de “el servidor se siente lento” que funciona en operaciones reales. El objetivo es identificar el recurso limitante en minutos, no coleccionar trivia.

Primero: confirma que no sea la red o el DNS

  • Comprueba rutas y enlace: ip -br a, ip r
  • Comprueba DNS: resolvectl status
  • Comprueba backlog de sockets/escuchas: ss -s, ss -tulpen

Si el DNS está roto, todo parece lento. Instalaciones de paquetes, handshakes TLS, llamadas a API—dolor por todas partes.

Segundo: encuentra el proceso caliente y en qué espera

  • Vista de alto nivel: top o htop (si está instalado)
  • Presión del sistema: uptime (load average), vmstat 1
  • IO por proceso: pidstat -d 1 (de sysstat) si lo necesitas

Busca: CPU al 100% (cómputo), carga alta con CPU baja (a menudo espera de IO), presión de memoria (swap) o una estampida de procesos.

Tercero: determina si el almacenamiento es el cuello de botella

  • Espera de IO y dispositivos de bloque: iostat -xz 1 (sysstat)
  • Sistemas de archivos llenos o casi: df -hT
  • Errores de disco: dmesg -T | tail, journalctl -k -n 200

Signo clásico: load average alto, CPU inactiva considerable y tiempos de respuesta pésimos. A menudo es latencia de almacenamiento.

Cuarto: confirma que la memoria no esté siendo aplastada sigilosamente

  • Resumen de memoria: free -h
  • Pruebas OOM: journalctl -k | grep -i oom

Si el kernel está matando procesos, trata eso como un problema de capacidad o fuga, no como “caídas aleatorias”.

Quinto: revisa systemd por unidades fallidas y servicios que hacen flapping

  • Servicios fallidos: systemctl --failed
  • Errores recientes: journalctl -p err..alert -b

Los demonios que hacen flapping pueden crear carga, tormentas de logs, agotamiento de puertos y falsos síntomas. systemd te lo dirá si preguntas directamente.

Errores comunes: síntomas → causa raíz → solución

1) “Habilité UFW y me quedé fuera”

Síntomas: SSH cae, reconectar falla, la consola aún funciona.

Causa raíz: Firewall habilitado antes de permitir SSH, o permitiste la interfaz/puerto equivocado.

Solución: Desde la consola: sudo ufw disable. Luego reaplica en el orden correcto: permitir SSH primero, confirmar, luego habilitar. En entornos con puertos SSH no estándar, permite explícitamente ese puerto y verifica con ss -tulpen antes de activar.

2) “Las actualizaciones de kernel fallan con /boot lleno”

Síntomas: errores en apt upgrade, fallos DKMS, paquetes de kernel antiguos repetidos.

Causa raíz: partición /boot demasiado pequeña o kernels antiguos no limpiados.

Solución: Elimina kernels antiguos con cuidado: dpkg -l 'linux-image-*', luego purga versiones antiguas (no la que está en ejecución). A largo plazo: asigna un /boot más grande o evita un /boot separado salvo que sea necesario.

3) “Las claves SSH no funcionan; aún pide contraseña”

Síntomas: la autenticación por clave falla, el servidor pide contraseña, los logs muestran Failed publickey.

Causa raíz: permisos incorrectos en ~/.ssh o authorized_keys, usuario equivocado o editaste un include de sshd que no está activo.

Solución: Asegura que ~/.ssh sea 700, authorized_keys sea 600 y propiedad del usuario. Valida la config con sshd -T y sshd -t. Luego recarga ssh.

4) “Apt se cuelga aleatoriamente”

Síntomas: apt update se atasca, especialmente en búsquedas DNS o acceso a mirrors.

Causa raíz: DNS roto, proxy cautivo o problemas en la ruta IPv6.

Solución: Comprueba resolvectl status y el enrutamiento. Prueba resolución de nombres con getent hosts archive.ubuntu.com. Si IPv6 está roto, arregla la red correctamente en lugar de deshabilitar IPv6 a ciegas (deshabilitar puede romper entornos modernos también).

5) “El disco se llena de la noche a la mañana y la máquina parece embrujada”

Síntomas: los servicios fallan al arrancar, SSH lento, los logs se detienen, journald se queja.

Causa raíz: crecimiento de /var (logs, capas de contenedores, volcados) en un único filesystem raíz sin cuotas ni separación.

Solución: Identifica a los responsables (du -xh --max-depth=1 /var). Añade retención de logs, separa /var en la próxima reconstrucción y considera ajustar el espacio reservado del sistema de archivos. Si ejecutas contenedores, trata /var/lib como un dominio de capacidad dedicado.

6) “La caja está lenta, pero la CPU está inactiva”

Síntomas: alta carga promedio, CPU con tiempo inactivo, tiempos de respuesta pobres.

Causa raíz: latencia de almacenamiento, espera de IO, o un proceso atrapado en IO (por ejemplo, fsync sincrónico de una base de datos).

Solución: Usa iostat -xz 1 y revisa la utilización y tiempos de espera del disco. Busca errores en journalctl -k. Si es una VM, revisa el almacenamiento del host y vecinos ruidosos también.

7) “Unattended upgrades rompió mi servicio”

Síntomas: el servicio falla después de actualizaciones nocturnas; problemas de compatibilidad.

Causa raíz: permitiste más que actualizaciones de seguridad (o la actualización de seguridad incluyó un cambio de comportamiento).

Solución: Restringe unattended-upgrades a pockets de seguridad solamente y estratifica actualizaciones en un entorno canario. Si un servicio es extremadamente sensible, gestiona ese paquete con control de cambios explícito—pero mantén el resto parchado.

Tres mini-historias corporativas desde las trincheras

Mini-historia 1: El incidente causado por una suposición equivocada

La compañía tenía una imagen estándar “Ubuntu mínima”. Arrancaba rápido, ejecutaba una aplicación y pasó el escaneo de seguridad. Todos se felicitaron y siguieron adelante, lo que es la señal de que la siguiente página está por venir.

Un equipo desplegó un nuevo lote de servidores y habilitó cifrado de disco completo. Asumieron que el layout del instalador mantendría root seguro. No separaron /var, no pusieron límites en journald y no validaron las suposiciones sobre el volumen de logs. La aplicación tenía un bug que aumentaba la verbosidad de logs bajo una condición de error transitoria. Ya puedes imaginar lo que pasó después.

En horas, los discos se llenaron. Cuando / quedó lleno, la falla se propagó: journald no pudo escribir, los servicios no podían crear archivos temporales, los gestores de paquetes no podían ejecutarse e incluso los inicios de sesión SSH se volvieron erráticos porque la autenticación también escribe en disco. El ingeniero on-call vivió la experiencia clásica de intentar arreglar un sistema que no podía registrar que estaba roto.

El postmortem no fue sobre el bug de la app; esos pasan. La verdadera suposición equivocada fue “imagen mínima significa riesgo mínimo”. Lo que necesitaban era un layout que aislara el crecimiento (separar /var) y una política de logs que trate el disco como un recurso finito, no una sugerencia.

La solución fue aburrida: guía de particionado, límites de logs y una prueba pre-deploy que intencionalmente spammea logs para demostrar que el servidor sigue recuperable. Esa prueba ahora es la razón por la que su imagen “mínima” merece el nombre.

Mini-historia 2: La optimización que se volvió en su contra

Un grupo orientado al rendimiento decidió que “el cifrado es overhead” y quitaron LUKS de una flota de servidores en NVMe rápidos. Midieron un benchmark que mejoró ligeramente. La presentación quedó convincente. Siempre lo está.

Meses después, un flujo de trabajo de desmantelamiento envió discos a un reciclador tercero. Un lote no fue borrado correctamente; fue una brecha de proceso, no intención maliciosa. Pero la intención no importa cuando un disco con datos de clientes sale del edificio. La respuesta al incidente fue brutal: legal, cumplimiento, comunicaciones con clientes y reuniones internas donde cada frase se convierte en evidencia.

Técnicamente, el resultado no fue una intrusión de hackers. Fue peor de otra manera: fue evitable. El cifrado habría convertido ese evento en un no-evento, suponiendo que las claves se gestionaran correctamente y no estuvieran pegadas a la carcasa.

El contragolpe no fue solo “perdimos seguridad”. Fue fricción operativa. Tuvieron que implementar controles de borrado de emergencia, volver a auditar manejo de activos y retrofitar cifrado en un entorno ya lleno de datos. Retrofitear a escala siempre es más difícil que hacerlo en la instalación.

La lección quedó clara: optimiza donde importa y donde puedes demostrar seguridad. Si la optimización ahorra 2% y crea un precipicio de cumplimiento, no es una optimización. Es un incidente futuro con mejor marketing.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

Otra organización tenía una política poco glamorosa: cada construcción de servidor debía pasar una “prueba de escucha” y una “prueba de parches”. La prueba de escucha es simplemente: lista todos los puertos escuchando y explica cada uno. La prueba de parches es: demuestra que las actualizaciones de seguridad están habilitadas y programadas, y muestra la última ejecución exitosa.

La gente puso los ojos en blanco. Sonaba como trabajo administrativo. También tomaba unos tres minutos cuando estaba automatizado correctamente, que es menos tiempo que discutirlo.

Un día una nueva imagen base incluyó accidentalmente un agente de telemetría que abría una interfaz web local enlazada a 0.0.0.0. Nadie pretendía exponerla; simplemente se empaquetó así. En muchos entornos, eso habría llegado a producción y esperado a que un escáner lo encontrara.

La prueba de escucha falló inmediatamente. El ingeniero pudo señalar ss -tulpen, identificar el proceso y bloquear el lanzamiento. Eliminaron el agente, reconstruyeron la imagen y siguieron adelante. Sin incidente. Sin comunicado. Sin maratón nocturna de parches.

Ese es el triunfo silencioso: un hábito gris que atrapa problemas agudos. Las mejores caídas son las que nunca tienes que documentar.

Listas de comprobación / plan paso a paso

Fase 0: Antes de arrancar el instalador (10 minutos que previenen arrepentimientos)

  • Decide: ¿se requiere cifrado de disco? Si sí, planifica la entrada/recuperación de claves en tu entorno (consola, KVM remoto o integración TPM si aplica).
  • Decide: ¿necesitas /var separado (recomendado para la mayoría de servidores)? Si sí, dimensiona basado en logs + datos de la app + crecimiento de contenedores.
  • Decide: ¿cómo accederás al servidor si la red falla? IPMI/iDRAC/iLO, consola virtual o acceso físico.
  • Prepara claves SSH para el usuario admin inicial.
  • Apunta: hostname, estrategia IP prevista (DHCP/estática), servidores DNS, expectativas NTP.

Fase 1: Opciones del instalador (mantenlo mínimo, mantenlo recuperable)

  1. Instala Ubuntu Server 24.04 LTS (sin GUI).
  2. Crea un usuario admin (con sudo habilitado).
  3. Importa o añade soporte de claves SSH durante la instalación si se ofrece.
  4. Selecciona almacenamiento:
    • Usa LUKS si es requerido.
    • Prefiere ext4 a menos que ya tengas un modelo operativo ZFS.
    • Considera seriamente /var separado para servidores con cualquier carga de escritura.
  5. Evita roles de servidor adicionales salvo que sea una instalación de propósito dedicado y sepas exactamente por qué los necesitas.

Fase 2: Primer arranque, línea base (el mínimo seguro)

  1. Actualiza listas de paquetes: sudo apt update.
  2. Instala automatización de seguridad: sudo apt install unattended-upgrades; confirma timers.
  3. Endurece SSH: deshabilita auth por contraseña, deshabilita login root, recarga ssh, confirma que el login por clave funciona.
  4. Habilita UFW con denegar entrantes por defecto; permite solo puertos requeridos.
  5. Confirma sincronización de tiempo: timedatectl muestra sincronizado.
  6. Confirma escuchas: sudo ss -tulpen es exactamente lo que pretendías.
  7. Registra el estado: captura salidas de lsblk, df -hT, systemctl --failed.

Fase 3: Endurecimiento sin autoboicot

  • Aplica opciones de montaje para /tmp y /var/tmp de forma reflexiva. Prueba tu software; no rompas instaladores en silencio.
  • Limita la retención de journald para que los logs no se coman los discos: limita por tamaño y tiempo según tu entorno.
  • Usa hardening de systemd para tus unidades de aplicación (NoNewPrivileges, ProtectSystem, PrivateTmp). Hazlo incrementalmente y prueba.
  • Decide la política de reinicios: ventana de mantenimiento programada o reinicios automáticos cuando sea necesario. Sea cual sea, sé explícito.

Fase 4: Operabilidad (porque “seguro” y “diagnosticable” son amigos)

  • Configura ganchos básicos de monitorización: uso de disco, salud SMART/NVMe, unidades systemd fallidas, estado de actualizaciones.
  • Asegura que los logs sean accesibles remotamente (centralización de logs) si ejecutas más de un servidor.
  • Ejecuta un simulacro de fallo: llena /var (de forma segura, en staging), verifica que el servidor siga recuperable y que alerten las alarmas.

Preguntas frecuentes

¿Realmente necesito un firewall si solo SSH está escuchando?

Sí. “Solo SSH está escuchando” es una fotografía, no una garantía. El firewall es la red de seguridad para futuras instalaciones de paquetes, servicios accidentales y errores humanos.

¿Siempre es correcto deshabilitar la autenticación por contraseña SSH?

Para servidores accesibles por Internet: sí, casi siempre. Para redes de laboratorio aisladas: igualmente recomendado. Si debes mantener contraseñas (cumplimiento o legado), aplica MFA mediante un método soportado y limita agresivamente el ritmo de intentos. Pero reconoce que estás pagando en riesgo.

¿Debería cambiar el puerto SSH?

Reduce el ruido de escaneos, no a atacantes reales. Si lo haces, hazlo por higiene de logs, no como “seguridad”. La seguridad real son claves, control de acceso y parcheo.

¿Necesito Fail2ban?

No como requisito inicial si has deshabilitado auth por contraseña y restringido usuarios SSH. Puede ser útil para reducir ruido y ralentizar intentos de fuerza bruta, pero no sustituye una política de autenticación correcta.

¿Vale la pena el cifrado de disco completo en servidores?

Sí cuando el modelo de amenazas incluye unidades perdidas, manos remotas, riesgo de colocation, errores de desmantelamiento o snapshots fuera de tu control. El coste operativo es la gestión de claves y desbloqueo en arranque. Planifica esa parte, no la improvises durante un incidente.

¿ext4 o XFS para una configuración mínima y segura?

ext4 es la opción conservadora por defecto y fácil de recuperar. XFS está bien para sistemas de archivos grandes y ciertas cargas, pero ext4 gana en “aburrido y predecible” para servidores generales.

¿Cómo evito que los logs llenen el disco?

Usa dos palancas: límites de journald y logrotate (para logs tradicionales). También aísla el crecimiento: /var separado o al menos monitorización. Si ejecutas aplicaciones muy ruidosas, arregla el logging de la aplicación también.

¿Debo instalar un montón de herramientas de troubleshooting desde el inicio?

No. Instala una línea base mínima más lo que necesites para tu modelo operativo (a menudo: smartmontools, quizá sysstat). Todo paquete extra es código extra que parchearás para siempre.

¿Cuál es el conjunto mínimo de “pruebas” que debo capturar tras la instalación?

Como mínimo: versión del SO, diseño de discos, uso de sistema de archivos, puertos escuchando, reglas de firewall, estado de timers de actualizaciones, estado de sincronización de tiempo y unidades systemd fallidas. Eso demuestra tanto postura de seguridad como operabilidad.

¿Cómo sé si mi sistema es lo suficientemente seguro?

Haz preguntas concretas: ¿Puede cualquiera forzar por contraseña SSH? ¿Están restringidos los puertos entrantes? ¿Las actualizaciones de seguridad son automáticas? ¿AppArmor está en modo enforce? ¿Puede un llenado de disco tumbar la máquina entera? Si puedes responder con comandos y configuraciones, estás haciendo seguridad real.

Siguientes pasos que deberías hacer de verdad

Aquí está la lista práctica de cierre—la parte que separa “instalado” de “listo para producción”:

  1. Bloquea SSH y pruébalo desde una segunda sesión antes de desconectar la actual.
  2. Activa UFW con denegar entrantes por defecto y permisos explícitos solo.
  3. Habilita actualizaciones de seguridad automáticas y confirma que los timers se ejecutaron al menos una vez.
  4. Verifica el diseño de almacenamiento con lsblk y df -hT; asegura que /boot y /var no te sorprenderán.
  5. Configura retención de journald a un cupo sensato según el tamaño de disco y necesidad de logs.
  6. Documenta la “lista de escucha”: qué puertos están abiertos y por qué. Trata cualquier escucha desconocida como bloqueo de liberación.
  7. Ejecuta el playbook de diagnóstico rápido una vez en un sistema sano para saber qué es “normal”.
  8. Decide tu estrategia de reinicios antes de que la primera actualización de kernel empuje la discusión en el peor momento posible.

Mínimo es una disciplina. Seguro es un hábito. Ubuntu Server 24.04 LTS te da buenos primitivos—pero aún tienes que conducir el coche.

← Anterior
Docker Desktop vs Docker en WSL: ¿Cuál es realmente más rápido?
Siguiente →
Proxmox: la opción ‘Ballooning’ que crea presión de memoria artificial

Deja un comentario