Ubuntu 24.04 → 26.04 en servidores
La ruta de actualización se abre el 27 de agosto con la 26.04.1. Seis valores por defecto han cambiado bajo tus pies, dos condiciones hacen que el actualizador se niegue en seco, y las notas de publicación esconden dos regresiones de servidor muy reales.
- Ubuntu
- Linux
- systemd
- Actualizaciones
El jueves 27 de agosto de 2026 Canonical publica Ubuntu 26.04.1 y, con ella, se abre para todo el mundo la ruta de actualización LTS a LTS desde 24.04.[schedule] Todas las guías que encuentres esa semana te llevarán de la mano hasta do-release-upgrade y ahí se detendrán. Ese comando no es la parte difícil. La parte difícil es que, entre Noble Numbat y Resolute Raccoon, Ubuntu ha sustituido seis piezas del sistema base de las que depende en silencio tu automatización de servidores, ha añadido dos condiciones bajo las cuales el actualizador se niega directamente a ejecutarse, y ha publicado dos regresiones conocidas de servidor que están documentadas y que casi nadie menciona.

Esta es la checklist que uso en máquinas reales. Está escrita para quien usa Ubuntu como servidor: sin escritorio, sin GNOME, sin tienda de snaps. Todo lo factual sale de las notas de publicación de Canonical y de los proyectos upstream, y donde las notas oficiales no dan un número de versión —OpenSSL es el caso interesante— no me lo he inventado. Los comandos no escriben nada salvo que el comentario diga lo contrario.
Por qué el 27 de agosto es la fecha que importa
Ubuntu no te ofrece la siguiente LTS el día que sale. Espera a su primera point release, que llega unos cuatro meses después y absorbe lo peor de las regresiones tempranas. Para 26.04 esa versión es la 26.04.1, el 27 de agosto de 2026. Hasta entonces, un servidor 24.04 con la política estándar Prompt=lts te dirá correctamente que no hay nada a lo que actualizar; eso no es un fallo, y no es algo que haya que esquivar.[schedule][upgradedoc]
# Ubuntu does NOT offer one LTS to the next until the first point release.
# For 26.04 that is 26.04.1, scheduled for Thursday 27 August 2026. Before that
# date `do-release-upgrade` on a 24.04 box correctly answers "No new release".
lsb_release -a
# Description: Ubuntu 24.04.4 LTS
# Codename: noble
# The policy that decides what you are offered. On servers it should be `lts`.
grep -v '^#' /etc/update-manager/release-upgrades
# [DEFAULT]
# Prompt=lts
# Prompt=lts -> next LTS, but only after ITS point release. Correct for servers.
# Prompt=normal -> every 6-month interim release. Wrong for almost all servers.
# Prompt=never -> never offered. Use this to pin a fleet during a change freeze.
sudo do-release-upgrade -c # -c = check only, changes nothing
# Checking for a new Ubuntu release
# No new release found.
# You CAN force it before 27 August with `-d`, which targets the development
# upgrade path. Do not do this on a production server: -d is how you end up
# being the person who finds the release-upgrader bug, and the point release
# exists precisely to absorb the first four months of regressions.Por eso mismo el calendario es menos urgente de lo que parece. Ubuntu 24.04 LTS tiene mantenimiento de seguridad estándar hasta abril de 2029. El 27 de agosto no te empujan por un precipicio: te abren una puerta. La única fecha límite real es la que te pongas tú, y la sensata es antes de que llegue la siguiente versión, no la semana en que te lo pregunte quien audita tu cumplimiento normativo.[releasecycle]
Si necesitas más tiempo, Ubuntu Pro extiende 24.04 con mantenimiento de seguridad ampliado hasta abril de 2034. Es una estrategia legítima para un parque que congelas a propósito: un appliance, una instalación aislada, algo que vas a retirar. Es una mala estrategia para un parque sobre el que sigues desarrollando, porque tu cadena de herramientas avanza y acabas retroportándolo todo tú.[pro]
| Situación | Qué significa el 27 de agosto para ti | Movimiento razonable |
|---|---|---|
Servidor 24.04 estándar, Prompt=lts | La actualización pasa a estar disponible. No se te empuja nada. | Planifícala. Septiembre u octubre, después de un piloto. |
| Parque bajo congelación de cambios | No cambia nada, pero puede que alguien empiece a actualizar máquinas de test. | Pon Prompt=never de forma explícita en lugar de fiarte de la inercia. |
| Appliance o instalación aislada | Irrelevante. 24.04 está soportada hasta abril de 2029. | Quédate. Valora Ubuntu Pro con ESM hasta 2034 si la congelación es larga. |
| Instancia cloud de generación anterior | No puedes actualizar en absoluto hasta migrar la instancia. | Cambia primero a una familia actual. Esto es independiente del sistema operativo. |
| Ya estás en 22.04 | No hay ruta directa. 22.04 → 24.04 → 26.04, en ese orden. | Haz ya el primer salto; es el menos interesante de los dos. |
El inventario previo, y por qué no toca nada
Todo lo que viene ahora se ejecuta en la máquina 24.04, antes de tocar nada. No escribe nada. El objetivo no es producir un informe bonito: es producir una salida que puedas comparar con la del mismo script después de la actualización, para que «volvió a arrancar» pase a ser una afirmación que puedes comprobar.
#!/usr/bin/env bash
# noble-preflight.sh - read-only. Run it BEFORE the upgrade, save the output,
# and diff it against the same script run afterwards. Nothing here changes state.
set -uo pipefail
echo "=== identity ==="
lsb_release -ds; uname -r; systemctl --version | head -1
echo "=== 1. third-party repositories (the usual cause of a stuck upgrade) ==="
# do-release-upgrade disables these and does NOT re-enable them for you.
grep -rhs --include='*.list' -E '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/
grep -rhs --include='*.sources' -E '^URIs' /etc/apt/sources.list.d/
echo "=== 2. packages not from the Ubuntu archive ==="
# Do NOT filter on the suite name: Docker's repo suite is literally `noble` and
# PGDG's is `noble-pgdg`, so grepping the codename hides exactly the two vendors
# you care about. Ask apt-cache policy where each package actually came from -
# in ONE invocation, because per-package calls reload the cache each time and
# turn this section into several minutes on a normal server.
#
# Set MIRROR to your own archive host if you run a local mirror, otherwise
# every package on the box gets reported as third-party and the output is noise.
# [.] rather than \. - awk processes escapes in a -v assignment and would warn.
MIRROR='archive[.]ubuntu[.]com|security[.]ubuntu[.]com|ports[.]ubuntu[.]com|archive[.]canonical[.]com'
apt-cache policy $(dpkg-query -f '${binary:Package} ' -W) 2>/dev/null | awk -v m="$MIRROR" '
/^[a-zA-Z0-9]/ { pkg = $0; sub(/:$/, "", pkg) }
/\*\*\*/ { getline; if ($2 !~ m && $2 != "/var/lib/dpkg/status")
printf "%-40s %s\n", pkg, $2 }'
echo "=== 3. held and manually installed packages ==="
apt-mark showhold
apt-mark showmanual | wc -l
echo "=== 4. locally modified config files you will be asked about ==="
# Every one of these produces a "keep or replace?" prompt mid-upgrade. Decide
# NOW, in writing, not at 02:00 with the package manager waiting on you.
debsums -ec 2>/dev/null || echo "install debsums to get this list"
echo "=== 5. services that must come back up ==="
systemctl list-unit-files --state=enabled --type=service --no-pager --no-legend | awk '{print $1}'
echo "=== 6. disk headroom - /boot is the one that bites ==="
df -h / /boot /var 2>/dev/null
echo "=== 7. cgroup hierarchy - a HARD upgrade blocker (see the cgroup section) ==="
stat -fc %T /sys/fs/cgroup/
# The parameter is a systemd boolean: 0/false/no/off all mean v1. Do not match
# only [01] or you will report "fine" on a host that is explicitly forced to v1.
grep -o 'systemd.unified_cgroup_hierarchy=[^ ]*' /proc/cmdline || echo "cmdline: default (v2)"
echo "=== 8. CPU capability for the AMD64v3 cloud images ==="
for f in avx avx2 bmi1 bmi2 f16c fma abm movbe osxsave; do
grep -qw "$f" /proc/cpuinfo || echo " MISSING: $f"
done
echo "=== 9. anything still using System V init scripts ==="
ls -1 /etc/init.d/ | grep -v READMECuatro de esas secciones se ganan su sitio porque son las que convierten una actualización de 40 minutos en una mala noche:
- Repositorios de terceros.
do-release-upgradedesactiva todos los repositorios que no son de Ubuntu antes de empezar, y no los vuelve a activar después. Es el comportamiento correcto, y significa que todo lo que instalaste desde un repositorio de proveedor —Docker, el PGDG de PostgreSQL, Node, un agente de APM— deja de recibir actualizaciones en cuanto terminas, en silencio, hasta que vayas a reapuntarlo a la suiteresolute. - Ficheros de configuración modificados localmente. Cada uno genera una pregunta interactiva de mantener o reemplazar en mitad de la transacción. Decídelo por adelantado y por escrito. La respuesta por defecto conserva tu versión, que es la opción segura para configuración de aplicación y la equivocada para cualquier cosa relevante para la seguridad que lleve dos años de endurecimiento upstream.
- Espacio libre en disco.
/necesita varios gigabytes libres; un/bootpequeño y separado es el fallo clásico, porque dracut y varios kernels lo llenan y la actualización se cae a medio camino con un sistema medio configurado. - La jerarquía de cgroups y los flags de CPU. Ambas cosas están detalladas más abajo. Ambas son cosas que quieres descubrir ahora, no desde una consola serie.
Qué se ha movido de verdad entre las dos versiones
Primero los números de titular, porque marcan las expectativas de todo lo demás. Dos años de desarrollo de Ubuntu es un salto largo: esto no es un service pack.[ltssummary]
| Componente | Ubuntu 24.04 LTS | Ubuntu 26.04 LTS | Por qué importa en un servidor |
|---|---|---|---|
| Kernel Linux | 6.8 | 7.0 | Soporte de hardware nuevo; revisa módulos fuera del árbol y compilaciones DKMS. |
| systemd | 255 | 259 | cgroup v1 eliminado; última versión con soporte de scripts System V. |
| OpenSSH | 9.6p1 | 10.2p1 | Acuerdo de claves post-cuántico por defecto; DSA retirado por completo. |
| Python | 3.12 | 3.14 | Cruza la 3.13 y sus diecinueve módulos de stdlib eliminados. |
| APT | 2.7 | 3.1 | apt-key eliminado; nuevo resolutor; TLS vía OpenSSL. |
| glibc / GCC | 2.39 / 14 | 2.43 / 15.2 | Recompila todo lo que compilaste localmente contra la cadena antigua. |
| PostgreSQL | 16 | 18 | Salto de versión mayor: pg_upgrade obligatorio, no automático. |
| MySQL | 8.0 | 8.4 LTS | Opciones obsoletas eliminadas; sin servidor de 32 bits. |
| PHP | 8.3 | 8.5 | Dos versiones mayores de cambios de lenguaje para todo lo que alojes. |
| OpenJDK por defecto | 21 | 25 | Los JDK LTS anteriores siguen disponibles si los fijas explícitamente. |
Una de esas filas es, discretamente, la más interesante. Cruzar de OpenSSH 9.6 a 10.2 significa que el acuerdo de claves híbrido post-cuántico mlkem768x25519-sha256 está disponible y es el preferido por defecto —no garantizado, porque un par en 9.6 sigue negociando un intercambio clásico— y que el soporte de DSA ha desaparecido por completo. OpenSSL en 26.04 incorpora ML-KEM, ML-DSA y SLH-DSA, los estándares del NIST. Si llevabas tiempo aplazando la conversación post-cuántica, esta actualización trae buena parte de esa migración incluida, la hubieras planificado o no.[openssh][openssl35][fips203]
Seis valores por defecto que han cambiado bajo tus pies
Esta es la sección que falta en todas las demás guías, y es la razón de que este artículo exista. Ubuntu no se ha limitado a subir versiones: ha sustituido la implementación que hay detrás de seis cosas que escribes o usas todos los días. La mayoría son mejoras. Solo una de ellas detiene la actualización en seco. Las demás se limitarán a confundir a alguien de tu equipo a las tres de la mañana si nadie las dejó escritas.[ltssummary]
| Lo que escribes | 24.04 te da | 26.04 te da | Qué hacer al respecto |
|---|---|---|---|
sudo | sudo (Todd C. Miller) | sudo-rs | Audita sudoers: las directivas no soportadas fallan en cerrado. Para revertir, sudo.ws más update-alternatives. |
ls, sort, date | GNU coreutils | rust-coreutils | Prueba los scripts que parsean salida. GNU disponible como gnuls y demás. cp, mv y rm siguen siendo GNU. |
| Sincronización horaria | systemd-timesyncd | chrony (solo instalaciones nuevas) | Los hosts actualizados conservan timesyncd. Migra a mano o diverge del valor por defecto a sabiendas. |
| initramfs | initramfs-tools | dracut es ahora el valor por defecto | Los dos siguen soportados. Comprueba cuál tienes de verdad; la configuración pasa a /etc/dracut.conf.d/. |
| Claves de repositorio | apt-key | solo Signed-By | Reescribe todos los scripts de aprovisionamiento que llamen a apt-key add. |
| Jerarquía de cgroups | v2 por defecto, v1 todavía posible | solo v2 | A un host en v1 se le rechaza la actualización. Quita antes el parámetro de kernel en 24.04. |
sudo ahora es sudo-rs
La línea más sorprendente de las notas de 26.04: sudo-rs es ahora el proveedor de sudo por defecto, y el sudo original de Todd C. Miller pasa a llamarse paquete sudo.ws. sudo-rs es una reimplementación segura en memoria que cubre el subconjunto de sudoers que usa prácticamente todo el mundo. Su comportamiento documentado ante algo que no soporta es fallar en cerrado, con un error claro, no ignorarlo. Esa es la dirección correcta, y es también la razón para auditar antes y no después: una directiva no soportada deja sudo sin funcionar, en una máquina donde sudo es precisamente cómo arreglas las cosas. Sí hay en cambio un conjunto corto y enumerado que se acepta y se ignora —env_reset, visiblepw, verifypw, mail_badpass, always_set_home, log_denied y un par más—, y ninguno de ellos relaja el acceso.[sudors]
# 26.04 makes sudo-rs the default sudo provider. The original sudo by
# Todd C. Miller is still packaged, renamed to `sudo.ws`.
sudo --version
update-alternatives --display sudo # which implementation is actually selected
# sudo-rs implements the sudoers subset that essentially everyone uses:
# user/group specs, host specs, NOPASSWD, Cmnd_Alias, %group, includedir.
# Its documented behaviour on something it does NOT support is to fail closed
# with a clear error, not to ignore it. That is the safe direction - but it
# means an unsupported directive stops sudo from working rather than quietly
# degrading it, so you want to find those directives before the upgrade, not
# from a locked-out root account afterwards. A short enumerated set is accepted
# and ignored instead (env_reset, visiblepw, verifypw, mail_badpass,
# always_set_home, log_denied among them); none of those loosen access.
# Resource limits and umask move to PAM; sendmail integration is simply gone.
grep -rEn 'Defaults.*(umask|rlimit|mailto|mailerpath|env_keep|logfile|SELinux|role|type)' \
/etc/sudoers /etc/sudoers.d/ 2>/dev/null
# Whatever you change, validate with the checker that matches your provider.
# visudo uses it automatically; run it by hand after any scripted edit.
sudo visudo -c
# --- If you find something sudo-rs will not honour ---
# Both implementations coexist; the provider is chosen through alternatives,
# so installing the package is only half the job:
sudo apt install sudo.ws
sudo update-alternatives --config sudo
# Treat this as a migration window rather than a destination: fix the sudoers
# file so you do not depend on the fallback staying available.
# --- One removal has no fallback ---
# The `sudo-ldap` package is gone. If your sudoers rules live in LDAP you must
# move that authorisation to PAM before upgrading, not after:
dpkg -l sudo-ldap 2>/dev/null | grep '^ii' && echo "ACTION REQUIRED: sudo-ldap is removed in 26.04"Dos notas prácticas. Primera: las dos implementaciones conviven y el proveedor se selecciona mediante update-alternatives, así que instalar sudo.ws es solo la mitad de una vuelta atrás. Segunda: hay una eliminación sin ninguna alternativa, el paquete sudo-ldap ya no existe. Si tus reglas de autorización de sudo viven en LDAP, eso tiene que moverse a autenticación LDAP vía PAM antes de actualizar; si no, aterrizas en un sistema donde las reglas simplemente no están y, según cómo tengas cableadas las rutas de escalado, quizá en uno que no puedas arreglar sin acceso por consola.
ls, sort y date ahora son Rust
Segunda sorpresa: las utilidades básicas vienen ahora de la implementación en Rust rust-coreutils. Los binarios de GNU siguen instalados con el prefijo gnu: gnuls, gnudate, gnusort. Ojo a un detalle: cp, mv y rm siguen siendo los de GNU dentro del paquete Rust, retenidos por errores sin resolver. Es la decisión correcta, y significa que las utilidades con más capacidad de destruir datos son justo las que no han cambiado. Conviene saber otra cosa antes de formarse una opinión: las notas de publicación de 26.04 revelan veinte CVE conocidos contra rust-coreutils. Que estén publicados es mucho mejor que que estén escondidos, y nada de esto es motivo de alarma; pero sí significa que las utilidades básicas pasan a tu radar de parcheo en lugar de a la categoría mental de cosas que nunca se mueven.[uutils]
# Core utilities now come from rust-coreutils (the uutils project). The GNU
# binaries are still installed, prefixed with `gnu`: gnuls, gnudate, gnusort...
ls --version | head -1 # uutils
gnuls --version | head -1 # GNU
# Worth knowing before you decide: the 26.04 release notes ship a list of
# twenty known CVEs against rust-coreutils (CVE-2026-35341 through -35377).
# That is disclosed, not hidden, and none of it is a reason to panic - but it
# is a reason to keep this package on your patching radar rather than assuming
# core utilities are the boring part of the system.
# cp, mv and rm are STILL the GNU implementations inside rust-coreutils, held
# back over unresolved bugs. So the utilities most likely to destroy data are
# the ones that did not change - which is the right call, and worth knowing
# before you go hunting for a regression in the wrong place.
# Where this actually bites: scripts that parse output, or lean on a GNU-only
# flag. Behaviour is close, not identical, and error text differs.
# Test the parsers, not the interactive use:
sort --help | grep -c . ; date --help | grep -c .
# --- Reverting, if a script you cannot change depends on GNU behaviour ---
sudo apt install coreutils-from-gnu --allow-remove-essential
# ...and back again:
sudo apt install coreutils-from-uutils --allow-remove-essential
# `--allow-remove-essential` is required because coreutils is Essential:yes.
# Read that flag as the warning it is: run it from a console you can recover,
# not over the SSH session you are about to need.chrony sustituye a systemd-timesyncd, pero no en tu máquina
Tercero, y el que veo pasar por alto más veces: chrony es ahora el demonio de tiempo por defecto en lugar de systemd-timesyncd, solo en instalaciones nuevas. Tu servidor actualizado conserva timesyncd, sigue funcionando y, sin hacer ruido, deja de coincidir con la documentación, con las guías de endurecimiento y con cualquier runbook escrito contra 26.04. Canonical documenta la migración manual; nadie la ejecuta por ti.[chrony]
# Chrony replaces systemd-timesyncd as the default time daemon - but ONLY for
# fresh installs. An upgraded 24.04 server keeps timesyncd and will not tell
# you it is now off the default path. This is the change most likely to be
# missed, because nothing breaks: you just quietly stop matching the docs.
timedatectl show --property=NTP --property=NTPSynchronized
systemctl is-active systemd-timesyncd chrony 2>/dev/null
# --- The migration Canonical documents for upgraded systems ---
sudo apt-mark auto systemd-timesyncd # demote it to an automatic dependency
sudo apt install chrony # installing chrony displaces timesyncd
# Verify you have exactly one time daemon running, not zero and not two:
systemctl is-active chrony
chronyc tracking
chronyc sources -v
# --- The trap, if you had ever edited chrony.conf ---
# Ubuntu's NTS-authenticated pool now lives in a separate drop-in file. If your
# old chrony.conf still lists servers, you will poll the same pool twice.
grep -E '^(server|pool)' /etc/chrony/chrony.conf
cat /etc/chrony/sources.d/ubuntu-ntp-pools.sources
# Keep the drop-in, comment out the duplicates in chrony.conf, then:
sudo systemctl restart chrony && chronyc sources -vLa migración tiene una trampa al otro lado. El pool de Ubuntu autenticado con NTS vive ahora en
/etc/chrony/sources.d/ubuntu-ntp-pools.sources. Si alguna vez editastechrony.confy dejaste ahí líneaspooloserver, vas a consultar los mismos servidores dos veces; no es fatal, pero es de esas cosas que producen una salida confusa de chronyc seis meses después, cuando alguien investigue una desviación de reloj.
dracut sustituye a initramfs-tools
Cuarto: dracut es ahora la infraestructura de initramfs por defecto, en lugar de initramfs-tools. Las notas de publicación son cuidadosas aquí y nosotros deberíamos serlo también: initramfs-tools sigue soportado, y puedes cambiar entre las dos implementaciones. Con cuál acaba realmente un host actualizado no es algo que debas dar por supuesto a partir de una entrada de blog, esta incluida. Compruébalo y actúa según lo que encuentres:[dracut][dracutconf]
- Pregúntaselo a la máquina, no lo deduzcas.
dpkg -l dracut initramfs-toolste dice qué hay instalado ydracut --versionsi es utilizable. Ojo:lsinitrdno tiene opción--version, así que la línea obvia para detectar dracut devuelve la respuesta equivocada; usadracut --versionen su lugar. - La configuración está en otro sitio. Si te mueves,
/etc/initramfs-tools/deja de ser el lugar: dracut lee/etc/dracut.conf.d/, y cualquier hook propio, lista de módulos o driver forzado hay que reescribirlo para él. Esa reescritura es el trabajo de verdad, y no se hace sola. - Inspecciona la imagen, no la regeneres. Lista su contenido y confirma que están tus drivers de almacenamiento y de red: NVMe, virtio, megaraid, mpt3sas, lo que pida tu hardware o tu hipervisor. Regenerar el initramfs justo después de una actualización de versión, en un host que todavía no has reiniciado dos veces, es lo más arriesgado que podrías hacer de todo lo que aparece en esta página.
cgroup v1 ya no existe, y bloquea la actualización
systemd 259 en 26.04 no tiene cgroup v1 en absoluto. Upstream eliminó las jerarquías legacy e híbrida en systemd 258; en el arranque solo se monta cgroup v2. Canonical convirtió eso en una puerta cerrada en lugar de en una sorpresa: en sus palabras, «las instalaciones de Ubuntu que ejecuten cgroup v1 no tendrán permitido actualizar a Ubuntu 26.04 LTS». Así que el modo de fallo aquí es una actualización rechazada, no un host inservible. Ese es el buen desenlace, y merece la pena ser preciso al respecto, porque buena parte de lo que se ha escrito sobre este cambio da a entender lo contrario.[systemd258][cgroupv2]
# systemd 259 in 26.04 has NO cgroup v1. The legacy and hybrid hierarchies
# were removed upstream in systemd 258; only cgroup v2 is mounted at boot.
#
# Canonical turned that into a hard gate rather than a surprise: "Ubuntu
# installations running cgroup v1 will not be allowed to upgrade to Ubuntu
# 26.04 LTS." So the failure mode is a REFUSED upgrade, not a bricked host -
# which is the good outcome, and the reason to check now is that you would
# otherwise discover it inside your maintenance window.
stat -fc %T /sys/fs/cgroup/
# cgroup2fs -> v2, the upgrade will proceed
# tmpfs -> v1 or hybrid, the upgrader will refuse. Fix it first.
# The parameter is a systemd boolean: 0, false, no and off all select v1.
grep -o 'systemd.unified_cgroup_hierarchy=[^ ]*' /proc/cmdline
grep -o 'systemd.legacy_systemd_cgroup_controller=[^ ]*' /proc/cmdline
# --- Fix it on 24.04, reboot, and confirm the workload still works ---
sudoedit /etc/default/grub
# remove systemd.unified_cgroup_hierarchy=0 from GRUB_CMDLINE_LINUX*
sudo update-grub && sudo reboot
# after the reboot:
stat -fc %T /sys/fs/cgroup/ # must print cgroup2fs
# Two related consequences that are easy to miss, both from the release notes:
# - a 26.04 CONTAINER will not run on a host still booted with cgroup v1
# - a 26.04 HOST will not run containers that require v1 (e.g. images based
# on Ubuntu older than 18.04). Check your base images, not just your hosts.
# --- The other systemd deadline, and it is closer than you think ---
# 26.04 is the LAST release that runs System V init scripts. systemd 260 has
# already dropped the support upstream, so the release that loses it is 26.10
# - October 2026, not some comfortable date in 2028.
ls -1 /etc/init.d/ | grep -v README
systemctl list-units --type=service --no-pager | grep -i 'LSB:'El patrón que hay que buscar es un parámetro en la línea de comandos del kernel, normalmente systemd.unified_cgroup_hierarchy=0, añadido hace años para tener contento a un Docker viejo, a un nodo de Kubernetes antiguo o a un agente de monitorización de JVM, y nunca retirado porque nada le recordó a nadie que estaba ahí. La razón para encontrarlo ahora y no la noche de la actualización es sencilla: un rechazo dentro de tu ventana de mantenimiento te cuesta igualmente la ventana. Hay dos efectos colaterales fáciles de pasar por alto: un contenedor 26.04 no funcionará sobre un host arrancado todavía con cgroup v1, y un host 26.04 no ejecutará contenedores que exijan v1, por ejemplo cualquier imagen basada en un Ubuntu anterior a 18.04. Revisa tus imágenes base, no solo tus hosts. Aparte, 26.04 es la última versión que ejecuta scripts de init System V, y esa fecha está más cerca de lo que parece: systemd 260 ya ha retirado el soporte upstream, así que la versión que lo pierde es la 26.10, en octubre de 2026, y no una fecha cómoda de 2028.[since2510][mobycgroup][systemd260]
APT 3 y la retirada de apt-key
APT pasa de 2.7 a 3.1, y el cambio que rompe la automatización es la retirada de apt-key. Lleva años obsoleto y no hay capa de compatibilidad: la verificación de firmas va ahora directamente a gpgv, y cada repositorio tiene que declarar su propia clave. Cualquier script de aprovisionamiento que siga llamando a apt-key add falla en 26.04, y como esa llamada suele estar al principio del bootstrap, falla antes de que haya pasado nada útil.[aptsecure][aptsources]
# APT 3 in 26.04 removes `apt-key` entirely. Verification goes straight to
# gpgv, and every repository must name its key explicitly.
apt --version # apt 3.1.x
command -v apt-key || echo "apt-key: gone, as expected"
# Find repositories that still rely on the deleted trusted keyring. These are
# what break: not the tool, the repositories that assumed it.
ls -l /etc/apt/trusted.gpg /etc/apt/trusted.gpg.d/ 2>/dev/null
# --- The replacement: one key per repository, referenced by path ---
# Create the directory explicitly. It exists on a normal install and does NOT
# on a minimal container image, which is exactly where bootstrap scripts run.
sudo install -m 0755 -d /etc/apt/keyrings
# Dearmor the key into its own file (note .gpg for binary, .asc for armoured):
curl -fsSL https://example.com/repo.asc \
| sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
sudo chmod 0644 /etc/apt/keyrings/example.gpg
# Then point the repository at it. Modern deb822 format, /etc/apt/sources.list.d/example.sources:
# Types: deb
# URIs: https://example.com/apt
# Suites: resolute
# Components: main
# Signed-By: /etc/apt/keyrings/example.gpg
#
# Or the one-line form, if you still use it:
# deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/apt resolute main
sudo apt update # any repo you missed fails loudly here
# --- Worth knowing about, not worth planning around ---
# APT 3 adds transaction history. It replays package operations; it does not
# restore data, and it cannot undo a release upgrade.
apt history-list
sudo apt history-undo <ID>APT 3 también trae un nuevo resolutor de dependencias, que entra automáticamente cuando el clásico no encuentra solución, y un histórico de transacciones con apt history-undo y apt history-rollback. Lee con calma esa función de histórico antes de confiar en ella: reproduce operaciones de paquetes. No restaura datos, no sabe nada de tu base de datos y no puede deshacer una actualización de versión.
Python 3.12 → 3.14 cruza las pilas gastadas
Ubuntu 24.04 trae Python 3.12; 26.04 trae 3.14. Eso significa que esta actualización cruza la 3.13, la versión que eliminó diecinueve módulos de la biblioteca estándar bajo la PEP 594. Ya no queda ningún aviso de obsolescencia que cazar, porque el periodo de aviso fueron 3.11 y 3.12. Lo que te queda es un ImportError en tiempo de ejecución, en el cron, el hook o el manejador de peticiones que llegue antes a ese import.[py313][pep594]
# 24.04 shipped Python 3.12. 26.04 ships 3.14 as the system interpreter - so
# this upgrade crosses 3.13, the release that deleted nineteen standard-library
# modules under PEP 594. Nothing warns you: the import simply fails at runtime,
# in whichever cron job or handler happens to reach that line first.
python3 --version # Python 3.14.x
# Scan everything you own for the removed modules, before the upgrade. Note
# the module name is matched anywhere on an import line, not just directly
# after the keyword - otherwise `import os, cgi` slips straight through.
grep -rInE '^[[:space:]]*(import|from)[[:space:]].*\b(aifc|audioop|cgi|cgitb|chunk|crypt|imghdr|mailcap|msilib|nis|nntplib|ossaudiodev|pipes|sndhdr|spwd|sunau|telnetlib|uu|xdrlib)\b' \
--include='*.py' /opt /srv /usr/local/lib /home 2>/dev/null
# The three that actually turn up on servers, and what to do about each:
# cgi / cgitb -> old WSGI shims and form parsing. Move to the framework's
# parser, or `pip install standard-cgi` as a stopgap.
# crypt -> /etc/shadow hashing in provisioning scripts.
# Replace with `passlib` or a libxcrypt binding.
# telnetlib -> network-device automation. Replace with `netmiko`/`pexpect`,
# or better, stop using telnet.
# Pure-Python removals are republished on PyPI under `standard-*` names, which
# buys you a release cycle. It does not fix the code.
# Do not forget the interpreter under your virtualenvs: a venv created against
# 3.12 keeps pointing at a binary the upgrade removes. -xdev keeps this out of
# /proc, /sys and network mounts; -print0 survives paths with spaces.
find / -xdev -name pyvenv.cfg -print0 2>/dev/null \
| xargs -0 -r grep -H 'version' # rebuild every one of these afterwardsTres de los diecinueve aparecen en servidores con una regularidad notable: cgi y cgitb en shims WSGI antiguos y en ayudantes de parseo de formularios, crypt en scripts de aprovisionamiento que escriben hashes en /etc/shadow, y telnetlib en automatización de equipos de red. Los que eran Python puro se republicaron en PyPI con nombres prefijados con standard-, lo que te compra un ciclo de versión para arreglar el código como toca. Y no te olvides de los virtualenvs: uno creado contra el binario 3.12 sigue apuntando a un intérprete que la actualización elimina.[py314]
Puede que tu instancia cloud ya no esté soportada
Las imágenes cloud de Ubuntu 26.04 para AMD64 están compiladas para el nivel de microarquitectura x86-64-v3. Lee esa palabra con atención, porque mucha de la cobertura no lo hace: lo que se ha movido son las imágenes preconstruidas, no el archivo. x86-64-v3 es la base v2 más AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE y OSXSAVE; una CPU sin esas extensiones no puede ejecutar esas instrucciones en absoluto, así que no hay parámetro de kernel que lo suavice.[ltssummary][x86levels]
# Ubuntu 26.04 cloud IMAGES for AMD64 are built for the x86-64-v3
# microarchitecture level. Read that word carefully: it is the prebuilt images
# that moved, not the archive. The archive stays baseline x86-64, so an
# in-place upgrade still pulls baseline packages. What you lose on an old
# instance family is SUPPORT and a launchable image - not, by itself, the boot.
# That is a smaller problem than "it will not come back", and still one you
# want to solve before you build anything else on top of it.
# x86-64-v3 is the v2 baseline plus AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT,
# MOVBE and OSXSAVE. AVX2 is a decent proxy; the loop is the real check.
# Note `abm`: Linux exposes LZCNT under that capflag, and there is no `lzcnt`
# string in /proc/cpuinfo - grep for the obvious name and every host on earth
# reports a missing feature it actually has.
for f in avx avx2 bmi1 bmi2 f16c fma abm movbe osxsave; do
grep -qw "$f" /proc/cpuinfo && echo " $f yes" || echo " $f MISSING"
done
# --- AWS: previous-generation families are out ---
# M1 M2 M3 M4 / C1 C3 C4 / R3 R4 / I2 / G3 / P2 P3 P3dn are no longer supported
# from 26.04. Note the [a-z]* before the dot: without it you miss p3dn and g3s,
# which are precisely two of the families you are hunting for.
aws ec2 describe-instances \
--query 'Reservations[].Instances[].{Id:InstanceId,Type:InstanceType}' \
--output text | grep -E '^\S+[[:space:]]+(m[1-4]|c[134]|r[34]|i2|g3|p[23])[a-z]*\.'
# The fix is a migration, not a config change: resize onto a current family
# (m6i/m7i, c6i/c7i, r6i/r7i) FIRST, then upgrade the OS.
# --- Google Cloud: N1 on Sandy Bridge or Ivy Bridge is out ---
gcloud compute instances list --format='table(name,zone,machineType,cpuPlatform)'
# --- Bare metal / on-prem: opt in only after you have checked every host ---
# The archive itself stays baseline x86-64; the v3 build is opt-in:
echo 'APT::Architecture-Variants "amd64v3";' | sudo tee /etc/apt/apt.conf.d/99enable-amd64v3
sudo apt update && sudo apt upgrade| Plataforma | Ya no soportado a partir de 26.04 | Acción necesaria |
|---|---|---|
| AWS EC2 | M1, M2, M3, M4; C1, C3, C4; R3, R4; I2; G3; P2, P3, P3dn | No se construye ninguna imagen 26.04 para ellas. Migra primero a una familia actual (m6i/m7i, c6i/c7i, r6i/r7i). |
| Google Compute Engine | N1 sobre plataformas de CPU Intel Sandy Bridge e Intel Ivy Bridge | Mueve primero la instancia a una plataforma de CPU o tipo de máquina más reciente. |
| Bare metal / on-premise | Nada: el archivo se mantiene en x86-64 base | Sin acción. La compilación AMD64v3 es opcional, con una sola línea en apt.conf.d. |
| IBM Z (s390x) | Generación z14 (LinuxONE II) y anteriores | z15 es el nuevo mínimo, y ubuntu-release-upgrader bloquea la actualización directamente. |
| RISC-V | Todo lo que esté por debajo del perfil de ISA RVA23S64 | 24.04 sigue siendo la versión para placas RVA20. |
Lo que eso significa en la práctica es más estrecho que la versión alarmista, y aun así merece que actúes. Las familias de generación anterior de AWS dejan de estar soportadas a partir de 26.04, y no se construye ninguna imagen 26.04 para ellas. Un do-release-upgrade in situ tira de paquetes amd64 base del archivo, así que es un problema de soporte y no automáticamente un problema de arranque; pero ejecutar una combinación no soportada bajo carga de producción, sobre hardware contra el que nadie está probando, no es una posición que se elija a propósito. Si tienes una M3 corriendo algo importante —y hay más gente de la que parece en esa situación, porque lleva una década funcionando bien—, cambia primero a una familia actual y actualiza después. En bare metal nada te obliga a nada: el archivo se mantiene en x86-64 base y la compilación v3 es estrictamente opcional.[awsprev]
Servicio a servicio: los que tienen migración de verdad
Los saltos de versión suelen ser tranquilos. Estos son aquellos en los que quien mantiene el proyecto ha cambiado algo que te obliga a actuar, ordenados más o menos por lo mal que sale si no lo haces:
| Servicio | Cambio | Esfuerzo |
|---|---|---|
| RabbitMQ | No es directamente actualizable en este salto por las feature flags. | Alto: pasos manuales, planifícalo como mantenimiento propio. |
| Dovecot | 2.4 reescribió el formato de configuración. | Alto: trata la migración de configuración como un proyecto aparte. |
| Samba AD/DC | El paquete samba-ad-dc debe instalarse antes de la actualización. | Alto: irreversible en la práctica si se olvida. Compruébalo hoy. |
| PostgreSQL | 16 → 18 necesita pg_upgrade; y una regresión con Linux 7.0 salvo con huge_pages=on. | Alto: la regresión es silenciosa. Dimensiona el pool de huge pages antes de activarlo. |
| apache2 + mod-php | MemoryDenyWriteExecute=yes en la unidad rompe el JIT de PHP. | Medio: pásate a php-fpm, o anula la directiva a sabiendas. |
| HAProxy | 2.x → 3.2: parseo de URI más estricto, enabled rechazado, tune.ocsp-update renombrado. | Medio: retoques de configuración, fáciles de probar por adelantado. |
| Squid | 7.2 eliminó client_delay_access, ftp_epsv y las directivas de conexión persistente. | Medio: una directiva eliminada impide que arranque el demonio. |
| MySQL | 8.0 → 8.4 LTS. Opciones obsoletas eliminadas; sin servidor de 32 bits. | Medio: revisa la configuración antes, no después. |
| SSSD | Ahora se ejecuta como el usuario sssd, no como root. | Bajo: verifica el acceso a secretos y keytabs. |
| Postfix | Ya no se instala en un chroot por defecto. | Bajo, pero revisa las rutas si personalizaste el chroot. |
| OpenSSH | 9.6 → 10.2: DSA fuera, acuerdo de claves post-cuántico por defecto. | Bajo: normalmente no hay nada que hacer. Verifica que ningún cliente necesite DSA. |
RabbitMQ se gana la primera fila por méritos propios: por las feature flags no es directamente actualizable en este salto, y Canonical documenta pasos manuales. Dovecot 2.4 reescribió el formato de configuración de arriba abajo; planifícalo como un cambio en sí mismo, no como un efecto colateral de actualizar el sistema. HAProxy pasa de la serie 2.x a 3.2, que rechaza la palabra clave enabled en servidores dinámicos, parsea URIs no estándar con más rigor y renombra tune.ssl.ocsp-update a tune.ocsp-update.[rabbitmq][dovecot24][haproxy32]
El resto son casos ordinarios, pero no automáticos. PostgreSQL 18 necesita pg_upgrade desde 16; MySQL 8.0 a 8.4 LTS elimina opciones obsoletas desde hace mucho y retira el servidor de 32 bits. SSSD se ejecuta ahora como el usuario sin privilegios sssd en lugar de root, así que verifica que sigue pudiendo leer sus secretos y sus keytabs. Postfix ya no va en chroot por defecto. Y si tienes un controlador de dominio de Active Directory con Samba sin el paquete samba-ad-dc instalado explícitamente, instálalo antes de actualizar; si no, la funcionalidad de controlador de dominio no sobrevive, y los componentes que necesitas para arreglarlo son justo los que no se instalaron.[postgres18][mysql84][sssd]
Los dos problemas conocidos que muerden de verdad en servidores
Canonical publica una lista de problemas conocidos junto a las notas de publicación, y dos de sus entradas son más concretas que casi todo lo que se ha escrito sobre 26.04. Ninguna de las dos bloquea la actualización. Las dos cambian cómo se comporta tu servidor después, en silencio, de una forma que atribuirás a otra cosa si no sabes que hay que mirarla. La primera es apache2: su unidad de systemd pone ahora MemoryDenyWriteExecute=yes como medida de endurecimiento, lo que prohíbe memoria que sea escribible y ejecutable a la vez, que es exactamente lo que necesita un compilador JIT. Con libapache2-mod-php eso rompe el JIT de PHP, con Allocation of JIT memory failed en tus logs y una caída de rendimiento que nadie relaciona con una actualización del sistema operativo.[since2510][apachebug]
# Both of these are in Canonical's own known-issues list for 26.04, and both
# are more concrete than most of what gets written about this release. Neither
# stops the upgrade; both change how your server behaves afterwards.
# --- 1. apache2 + mod-php: the PHP JIT stops working ---
# The apache2 systemd unit now sets MemoryDenyWriteExecute=yes as hardening.
# That forbids memory that is writable and executable at once, which is exactly
# what a JIT needs. Symptom:
# Warning: preg_match(): Allocation of JIT memory failed, PCRE JIT will be disabled.
dpkg -l 'libapache2-mod-php*' 2>/dev/null | grep '^ii'
# Recommended fix: move to php-fpm, which is not affected. Note the a2dismod -
# without it apache2 keeps loading mod_php and the JIT stays broken, which is
# the most common way this "fix" gets applied and then reported as not working.
sudo apt install php-fpm
sudo a2dismod php8.5 && sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif && sudo a2enconf php8.5-fpm
sudo systemctl restart apache2 php8.5-fpm
# If you must stay on mod-php, override the hardening deliberately - and
# understand that you are turning off a mitigation, not fixing a bug:
sudo systemctl edit apache2
# [Service]
# MemoryDenyWriteExecute=no
sudo systemctl restart apache2
# --- 2. PostgreSQL on the 7.0 kernel: throughput and latency regression ---
# A Linux 7.0 change can cost PostgreSQL significant throughput and latency.
# Systems using huge pages are NOT affected, so this is a configuration
# question rather than a wait-for-a-patch question.
sudo -u postgres psql -tAc 'SHOW huge_pages;' # want: on
# huge_pages=try (the default) silently falls back to normal pages, which is
# how you end up affected without any error telling you so.
#
# Size the pool FIRST. PostgreSQL will compute the number for you - no
# arithmetic, no guessing at shared_buffers overhead:
sudo -u postgres postgres -D /var/lib/postgresql/18/main \
-C shared_memory_size_in_huge_pages
# 3170
grep -E 'Hugepagesize|HugePages_Total' /proc/meminfo
sudo sysctl -w vm.nr_hugepages=3170 # use YOUR number, then
# persist it in /etc/sysctl.d/
# ...and only now turn it on:
sudo -u postgres psql -c "ALTER SYSTEM SET huge_pages = 'on';"
sudo systemctl restart postgresql
# huge_pages=on means PostgreSQL REFUSES TO START if the pages are not
# available. That is the point - it fails loudly instead of quietly slowly -
# but it means you size the pool before you flip the setting, not after.La segunda es PostgreSQL, y es la que yo apostaría a que se diagnostica mal. Un cambio en Linux 7.0 puede provocar una regresión notable de rendimiento y de latencia; pero los sistemas que usan huge pages no se ven afectados, lo que convierte esto en una cuestión de configuración y no en una de esperar a un parche. La trampa está en que el valor por defecto de PostgreSQL, huge_pages=try, cae de vuelta a páginas normales en silencio, así que un servidor afectado no informa de nada: ni error, ni aviso, solo peores números que la semana pasada. Pon huge_pages=on a propósito, y dimensiona el pool de huge pages antes de hacerlo, porque on significa que PostgreSQL se niega a arrancar si las páginas no están. Ese es el compromiso correcto —fallar a gritos en lugar de ir despacio en silencio—, pero no es un ajuste que se toque al final de una ventana de mantenimiento larga.[pghugepages][pgkernel][systemdexec]
Ejecutar la actualización
Aquí no hay nada ingenioso. Todo el valor está en el orden, y en no saltarse el paso cero.[upgradedoc]
# Nothing below is clever. The value is entirely in the order and in refusing
# to skip step 0.
# --- 0. A rollback you have actually tested ---
# Snapshot the VM, or take a filesystem-level backup you have restored from at
# least once. `do-release-upgrade` has no undo, and neither does apt history.
# If you cannot roll back, you are not upgrading, you are gambling.
# --- 1. Land on a fully patched 24.04 first ---
sudo apt update && sudo apt full-upgrade
sudo apt --purge autoremove
sudo reboot # boot the newest 24.04 kernel BEFORE upgrading
uname -r
# --- 2. Survive a dropped connection ---
# The upgrade takes 20-60 minutes and will kill your shell if the link drops
# mid-transaction. do-release-upgrade opens a standby sshd on 1022 by itself;
# run it inside tmux or screen anyway.
sudo apt install tmux
tmux new -s upgrade
# detach with Ctrl-b d, reattach after a disconnect with: tmux attach -t upgrade
# --- 3. Run it ---
sudo do-release-upgrade
# Answer the config-file prompts from the list you produced in the pre-flight.
# Default is "keep your currently-installed version" (N). For sshd_config and
# anything security-relevant, take the maintainer's version and re-apply your
# changes as a drop-in afterwards - your 2019 hardening file is not better
# than the 2026 defaults.
# --- 4. Reboot and verify, in this order ---
sudo reboot
lsb_release -ds # Ubuntu 26.04.1 LTS
uname -r # 7.x
systemctl --failed # must be empty
journalctl -p err -b --no-pager | head -50
ss -tlnp # every listener you expect, and nothing new
# --- 5. Clean up what the upgrade left behind ---
sudo apt --purge autoremove # read the list before confirming
ls /etc/apt/sources.list.d/ # re-enable third-party repos, resolute suites
dpkg -l | grep '^rc' | wc -l # removed-but-not-purged leftoversHay una decisión que conviene decir en voz alta, porque la respuesta por defecto no siempre es la correcta. Cuando la actualización te pregunte por un fichero de configuración modificado, conservar tu versión es la opción segura para configuración de aplicación y normalmente la equivocada para cualquier cosa relevante para la seguridad: tu endurecimiento de sshd_config de 2019 no es mejor que los valores por defecto de 2026. Pero cógete ese consejo con la salvedad evidente pegada. Aceptar el sshd_config del mantenedor descarta también un Port, un AllowUsers, un PermitRootLogin o un bloque Match propios que vivan en ese fichero, y sshd se reinicia antes de que hayas vuelto a aplicarlos, por encima de la misma conexión desde la que estás actualizando. Deja abierta la sesión de reserva en el puerto 1022, vuelve a aplicar tus cambios locales de verdad como un fichero suelto en sshd_config.d/, donde la siguiente actualización los dejará en paz, y solo entonces cierra la primera shell.
Verificar después, en serio
«Ha arrancado» no es una verificación. Esto es la contraparte del script previo y, para ser precisos sobre cómo usarlos, los dos scripts imprimen a propósito secciones distintas, así que no compares uno con otro en bloque. Los bloques que sí merece la pena comparar directamente son la lista de servicios habilitados y ss -tlnp: las mismas unidades habilitadas, los mismos puertos escuchando. Si un servicio estaba habilitado antes y ahora no lo está, aquí es donde te enteras, y no cuando alguien abra un ticket el lunes.
#!/usr/bin/env bash
# noble-postflight.sh - the counterpart to the pre-flight script. The two print
# DIFFERENT sections on purpose, so do not diff them against each other
# wholesale. The blocks that are directly comparable are the enabled-services
# list and `ss -tlnp`: same units enabled, same ports listening.
# "It booted" is not a verification; "the same 41 services are enabled and
# listening on the same ports" is.
set -uo pipefail
echo "=== the defaults that changed under you ==="
sudo --version | head -1 # sudo-rs, unless you reverted
update-alternatives --display sudo | head -2
ls --version | head -1 # uutils, unless you reverted
systemctl is-active chrony systemd-timesyncd 2>/dev/null # exactly one active
stat -fc %T /sys/fs/cgroup/ # cgroup2fs
echo "=== which initramfs generator is this host ACTUALLY using? ==="
# Both are supported in 26.04 and either can be in place after an upgrade, so
# do not assume - ask. (lsinitrd has no --version; dracut does.)
dpkg -l dracut initramfs-tools 2>/dev/null | grep '^ii' || true
command -v dracut >/dev/null && dracut --version
echo "=== crypto, which moved a long way in two years ==="
ssh -V # OpenSSH 10.2p1 in 26.04, from 9.6p1
ssh -Q kex | grep -c mlkem # post-quantum key agreement offered
# OpenSSL spells these with hyphens - ML-KEM-768, not mlkem - so grep for both
# or you will "prove" that a correctly configured box has no PQ support.
openssl list -kem-algorithms | grep -ciE 'ml-?kem'
echo "=== DSA host keys are gone; make sure nothing still expects one ==="
ls /etc/ssh/ssh_host_*_key 2>/dev/null
sudo sshd -t && echo "sshd config: valid"
echo "=== services ==="
systemctl --failed --no-pager
systemctl list-unit-files --state=enabled --type=service --no-pager --no-legend | awk '{print $1}'
ss -tlnp
echo "=== rebuild every virtualenv that pointed at python3.12 ==="
find / -xdev -name pyvenv.cfg 2>/dev/null
echo "=== the two server known-issues from the release notes ==="
# 1. apache2 now sets MemoryDenyWriteExecute=yes, which breaks the PHP JIT
# under libapache2-mod-php. php-fpm is unaffected and is the recommendation.
dpkg -l libapache2-mod-php\* 2>/dev/null | grep -q '^ii' && \
echo "mod-php present -> move to php-fpm, or: systemctl edit apache2 (MemoryDenyWriteExecute=no)"
# 2. A Linux 7.0 change can cost PostgreSQL significant throughput and latency.
# Systems using huge pages are not affected.
command -v psql >/dev/null && sudo -u postgres psql -tAc 'show huge_pages'
# Anything other than `on` here is worth fixing before you call this done.
echo "=== boot integrity: inspect, do not regenerate ==="
# READ ONLY on purpose. Regenerating the initramfs immediately after a release
# upgrade is the riskiest thing you could do on this page; look first.
# /boot/initrd.img-* is mode 0600 root:root, hence the sudo on both branches.
if command -v lsinitrd >/dev/null; then
sudo lsinitrd | grep -E 'nvme|virtio|megaraid|mpt3sas' | head
elif command -v lsinitramfs >/dev/null; then
sudo lsinitramfs /boot/initrd.img-"$(uname -r)" | grep -E 'nvme|virtio|megaraid|mpt3sas' | head
else
echo "neither lsinitrd nor lsinitramfs present - install the tool matching your generator"
fiDos cosas que hay que revisar y que el script no puede revisar por ti. Primero, tu configuración de netplan: 26.04 trae Netplan 1.2, incluido un systemd-networkd-wait-online propio que espera a una interfaz enrutable, así que un host con una NIC que tarda en levantar puede arrancar de forma distinta a como lo hacía. Segundo, todos los repositorios de terceros de la lista previa: reapúntalos a la suite resolute con una clave Signed-By y confirma que apt update sale limpio. Un parque que dejó de recibir actualizaciones de seguridad de proveedor sin decir nada es la forma más silenciosa posible de que esta actualización haya salido mal.[netplan]
Entonces: ¿ahora, en noviembre o en 2027?
Mi consejo honesto, después de haber hecho esto tanto en parques cuidadosos como en parques descuidados:
- No actualices el 27 de agosto. La point release existe para absorber regresiones, pero las que no atrapa salen a la superficie en la quincena siguiente, encontradas por gente con más apetito de riesgo del que debería tener un entorno de producción.
- Actualiza un servidor no crítico a principios de septiembre. Algo suficientemente real como para ser interesante —un agente de build, una herramienta interna— pero por el que nadie te llame de madrugada. Ejecuta los scripts previo y posterior y guarda el diff. Ese diff es tu documento de migración para todo lo demás.
- Despeja primero, en todas partes, los dos bloqueos de actualización. Un host arrancado todavía con cgroup v1, y cualquier cosa que corra sobre IBM Z z14 o anterior, recibirán un rechazo del actualizador: encuéntralos antes de planificar trabajo a su alrededor. Mete en la misma barrida las familias de instancias sin AMD64v3: esas no están bloqueadas, pero ejecutar una combinación no soportada es una decisión, y debería ser deliberada. Las tres cosas se comprueban hoy en 24.04, con independencia de cualquier decisión sobre actualizar.
- Y después agrupa el resto en octubre y noviembre. Para entonces los repositorios de terceros de los que dependes tendrán suites
resolute, lo que elimina casi toda la fricción restante.
Y lee la página de problemas conocidos, no solo el resumen. Se actualiza después de la publicación, que es exactamente la propiedad que quieres de ella: el resumen te cuenta lo que se pretendía, la lista de problemas conocidos te cuenta lo que pasó de verdad.[since2510]
Si vas a tocar init y planificación de tareas de todas formas, temporizadores de systemd frente a cron cubre la migración que esta versión vuelve inaplazable. La parte de SSH y TLS de la actualización es el tema de SSH y TLS post-cuánticos, que entra en qué verificar sobre las conexiones y no sobre los paquetes. Y si lo que este artículo te ha dejado sobre todo es ganas de tener menos piezas móviles que actualizar, ese es el argumento de arquitecturas cloud aburridas.
Preguntas frecuentes
¿Puedo actualizar de Ubuntu 24.04 a 26.04 antes del 27 de agosto de 2026?
Técnicamente sí, con do-release-upgrade -d, que apunta a la ruta de actualización en desarrollo. No deberías hacerlo en un servidor de producción. La point release existe precisamente para absorber cuatro meses de regresiones posteriores al lanzamiento, y forzar la actualización antes de tiempo significa que tú eres quien encuentra los fallos del actualizador. En un portátil que puedes restaurar en una hora, es razonable; en un servidor con tráfico real, no lo es.
¿Tengo que actualizar? ¿Hasta cuándo está soportada la 24.04?
Ubuntu 24.04 LTS tiene mantenimiento de seguridad estándar hasta abril de 2029, y Ubuntu Pro lo amplía con ESM hasta abril de 2034. En agosto de 2026 no hay ninguna urgencia. La razón para actualizar es que tu propia cadena de herramientas avanza —Python más nuevo, PostgreSQL más nuevo, runtimes más nuevos— y quedarte quieto acaba significando que retroportas todo tú. Congelar es una opción legítima para un appliance o un parque que vas a retirar, y mala para una plataforma sobre la que sigues construyendo.
¿Cuál es el cambio con más probabilidad de costarme una ventana de mantenimiento?
Un parámetro de kernel systemd.unified_cgroup_hierarchy=0 olvidado. systemd 259 no tiene cgroup v1 en absoluto, y Canonical lo ha convertido en una puerta cerrada: a un host arrancado todavía con cgroup v1 no se le permite actualizar. No te quedas con una máquina rota: te quedas con un rechazo, justo en el momento en que habías presupuestado una hora de parada. El segundo puesto es para la regresión de PostgreSQL con el kernel Linux 7.0, porque a diferencia de la primera no produce ningún error, solo peores números. Ambas se comprueban en menos de un minuto en 24.04, hoy, antes de comprometerte con ninguna fecha.
¿Es seguro usar sudo-rs en producción?
Sí para la configuración de sudoers que tiene realmente la inmensa mayoría de sistemas: especificaciones de usuario y grupo, de host, NOPASSWD, alias de comandos e includedir. El cuidado hay que ponerlo en los bordes. sudo-rs no implementa todo el abanico de entradas Defaults; los límites de recursos y la umask pasan a PAM, y la integración con sendmail ha desaparecido. Su comportamiento documentado ante una directiva no soportada es fallar en cerrado con un error claro, no ignorarla: es la dirección segura, pero significa que una directiva que no revisaste puede dejar sudo sin funcionar en una máquina donde sudo es precisamente cómo arreglas las cosas. Sí hay un conjunto corto y enumerado que se acepta y se ignora, y ninguno de esos relaja el acceso. Audita el fichero antes de actualizar. Y si necesitas volver atrás, las dos implementaciones conviven: instala sudo.ws y selecciónalo con update-alternatives --config sudo; instalar el paquete por sí solo no cambia el proveedor.
¿Seguirán funcionando mis contenedores Docker después de actualizar?
En casi todos los casos sí, porque Ubuntu 24.04 ya usa cgroup v2 por defecto y Docker moderno lleva años soportando v2. La excepción es un host donde alguien puso en su día systemd.unified_cgroup_hierarchy=0 en la línea de comandos del kernel para tener contento a un Docker o a un nodo de Kubernetes antiguos: a ese host se le rechaza la actualización directamente. Comprueba stat -fc %T /sys/fs/cgroup/, que debe imprimir cgroup2fs. Hay dos límites relacionados fáciles de pasar por alto. Un contenedor 26.04 no funcionará sobre un host arrancado todavía con cgroup v1, y un host 26.04 no ejecutará contenedores que exijan v1: imágenes basadas en un Ubuntu anterior a 18.04, por ejemplo. Así que revisa tus imágenes base además de tus hosts.
¿Por qué ha dejado de funcionar mi script de Python tras la actualización?
Lo más probable es un ImportError en un módulo eliminado en Python 3.13. Ubuntu 24.04 traía Python 3.12 y 26.04 trae 3.14, así que esta actualización cruza la versión que borró diecinueve módulos de la biblioteca estándar bajo la PEP 594. Los tres que más aparecen en servidores son cgi, crypt y telnetlib. Las eliminaciones de Python puro se republicaron en PyPI con nombres prefijados con standard- como parche temporal. Aparte, cualquier virtualenv creado contra el binario 3.12 hay que rehacerlo, porque el intérprete al que apunta ya no existe.
¿Tengo que migrar de systemd-timesyncd a chrony?
Estrictamente no: timesyncd sigue funcionando y un servidor actualizado lo conserva. Pero chrony es el valor por defecto en instalaciones nuevas de 26.04, así que si no haces nada tus hosts actualizados y tus hosts recién construidos divergen, y cualquier runbook o guía de endurecimiento escrita contra 26.04 deja de coincidir. Canonical documenta la migración como apt-mark auto systemd-timesyncd seguido de apt install chrony. Si migras, comprueba que los servidores que sigan listados en chrony.conf no estén duplicados por el fichero de /etc/chrony/sources.d/ubuntu-ntp-pools.sources.
¿Puedo volver atrás si la actualización sale mal?
Con herramientas de Ubuntu, no. do-release-upgrade no tiene deshacer, y el nuevo apt history-undo reproduce operaciones de paquetes en lugar de restaurar un sistema: no sabe nada de tus datos y no puede revertir una actualización de versión. Tu vuelta atrás es un snapshot de la máquina virtual o una copia de seguridad a nivel de sistema de ficheros desde la que hayas restaurado de verdad al menos una vez. Si no la tienes, no estás actualizando: estás apostando con buen valor esperado y una pérdida sin techo.
El runtime de contenedores que hay debajo también se ha movido: qué se rompe al pasar a Docker Engine 29 repasa el mínimo de API, el almacén de imágenes y el límite de descriptores de fichero que cambió sin dar ningún error.
Fuentes
Cada afirmación de arriba se remonta a una de estas fuentes. Las notas de publicación y el calendario de Canonical son la autoridad para todo lo específico de Ubuntu; la documentación del proyecto upstream para el resto. Donde las notas oficiales no dan una versión, este artículo describe la capacidad en lugar de adivinar un número.
- Canonical — Ubuntu 26.04 LTS (Resolute Raccoon) release notes; released 23 April 2026, supported until April 2031
- Canonical — Ubuntu 26.04 LTS summary for LTS users: the authoritative list of changes since 24.04, and the source for every default swap described here
- Canonical — Ubuntu 26.04 LTS changes since 25.10, including the known-issues list and the cgroup v1 removal detail
- Canonical — Resolute Raccoon release schedule; the 26.04.1 point release is listed for Thursday 27 August 2026
- Ubuntu Server documentation — How to upgrade your release (do-release-upgrade, the -d flag, and the LTS-to-LTS point release rule)
- Canonical — Ubuntu 24.04 LTS (Noble Numbat) release notes, the baseline this article upgrades from
- Canonical — Ubuntu release cycle: LTS cadence, five years of standard support, ESM through Ubuntu Pro
- Canonical — Ubuntu Pro documentation (ESM, Livepatch, and the ten-year maintenance window on 24.04)
- Trifecta Tech Foundation — sudo-rs, the memory-safe sudo and su implementation that is now Ubuntu's default sudo provider
- uutils/coreutils — the Rust reimplementation of the GNU core utilities shipped as rust-coreutils
- systemd v258 release notes — removal of cgroup v1 (legacy and hybrid hierarchies) and the raised kernel baseline
- systemd NEWS — the upstream changelog covering v256 through v259, including the System V compatibility deprecation
- Linux kernel documentation — Control Group v2, the only hierarchy systemd still mounts
- moby/moby #51111 — Docker's cgroup v1 deprecation discussion and support timeline
- apt-secure(8) — repository signing after the removal of apt-key, and the Signed-By mechanism that replaces it
- sources.list(5) — the deb822 .sources format and the Signed-By field
- dracut(8) — the initramfs infrastructure that replaces initramfs-tools as Ubuntu's default
- dracut.conf(5) — configuration in /etc/dracut.conf.d/, including hostonly and the drivers to force-include
- chrony.conf(5) — the configuration file, source directories and NTS options for Ubuntu's new default time daemon
- What's New In Python 3.13 — the release that removed the nineteen PEP 594 'dead battery' standard-library modules
- PEP 594 — Removing dead batteries from the standard library; the full list of removed modules and their replacements
- What's New In Python 3.14 — the interpreter Ubuntu 26.04 ships as the system Python
- OpenSSL 3.5 series release notes — ML-KEM, ML-DSA and SLH-DSA support and the default hybrid TLS groups
- OpenSSH release notes index — covers the 9.6 to 10.2 range that this upgrade crosses, including DSA removal
- NIST FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM), the algorithm behind the new OpenSSL and OpenSSH defaults
- AWS — previous generation EC2 instances; the families that lose Ubuntu support because of the AMD64v3 cloud image baseline
- x86-64 microarchitecture levels — what x86-64-v3 requires (AVX2, BMI1/2, FMA, MOVBE)
- RabbitMQ — upgrade documentation and feature flags, the reason RabbitMQ is not directly upgradable across this release
- Dovecot — upgrading from 2.3 to 2.4, the release that rewrote the configuration format (26.04 ships 2.4.2)
- HAProxy 3.2 configuration manual — the breaking changes since the 2.x series shipped in 24.04
- PostgreSQL 18 release notes — the major version 26.04 ships, requiring pg_upgrade from 16
- MySQL 8.4 LTS release notes — the series replacing 8.0, including removed deprecated options
- Netplan 1.2 documentation — the series shipped in Ubuntu 26.04
- SSSD 2.10 release notes — the change that makes the daemon run as the unprivileged sssd user rather than root
- systemd v260 release notes — System V service script support already dropped upstream, which is why 26.10 is the release that loses it
- PostgreSQL documentation — the huge_pages configuration parameter, the documented mitigation for the Linux 7.0 regression
- PostgreSQL documentation — configuring Linux huge pages for the server
- LP #2144455 — apache2's MemoryDenyWriteExecute hardening breaking the PHP JIT under libapache2-mod-php
- systemd.exec(5) — MemoryDenyWriteExecute=, the hardening directive apache2 now sets by default
¿Te ha resultado útil?