La hora y el idioma del sistema parecen detalles menores hasta que fallan: tareas cron que se ejecutan una hora antes, logs imposibles de correlacionar entre servidores, certificados TLS rechazados por un reloj desfasado o scripts que rompen con caracteres acentuados. En este tutorial configurarás en Ubuntu 24.04 la zona horaria, la sincronización de hora por NTP y el locale (idioma y formatos regionales) del sistema, y comprobarás que cada ajuste persiste.

Al final se indican los cambios para Rocky Linux 9 y AlmaLinux 9.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Salida al puerto 123/UDP hacia Internet para NTP (abierta por defecto en la mayoría de configuraciones).

Paso 1: Revisar la configuración actual

timedatectl muestra en una sola salida la hora local, la zona horaria y el estado de sincronización:

timedatectl
               Local time: Thu 2026-09-25 10:15:42 UTC
           Universal time: Thu 2026-09-25 10:15:42 UTC
                 RTC time: Thu 2026-09-25 10:15:42
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Las líneas que importan son:

  • Time zone: la zona horaria del sistema. Las imágenes de servidor suelen venir en UTC.
  • System clock synchronized: yes indica que el reloj está sincronizado con un servidor NTP.
  • NTP service: active indica que el servicio de sincronización está en marcha.
  • RTC in local TZ: debe ser no, es decir, el reloj de hardware guarda la hora en UTC.

Consulta también el locale actual:

locale
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
...
LC_ALL=

Paso 2: Elegir la zona horaria

Antes de cambiar nada, decide qué zona necesitas:

  • UTC es la opción recomendada para servidores: no tiene cambios de horario de verano, y los logs de varios servidores se comparan directamente. Las aplicaciones convierten a la hora local del usuario al mostrarla.
  • Una zona local (por ejemplo Europe/Madrid) tiene sentido si las personas que leen los logs o programan tareas cron piensan en hora local y el servidor solo sirve a esa región.

Lista las zonas disponibles y filtra por región:

timedatectl list-timezones | grep Europe
Europe/Amsterdam
Europe/Andorra
...
Europe/Madrid
...

Usa siempre nombres del tipo Región/Ciudad. Evita abreviaturas como CET o EST, que no reflejan correctamente los cambios de horario de verano.

Paso 3: Cambiar la zona horaria

Aplica la zona elegida. Este ejemplo usa Europe/Madrid; sustitúyela por tu zona horaria o por Etc/UTC:

sudo timedatectl set-timezone Europe/Madrid

El comando actualiza el enlace simbólico /etc/localtime y el archivo /etc/timezone. Verifica el cambio:

timedatectl | grep "Time zone"
date
                Time zone: Europe/Madrid (CEST, +0200)
Thu Sep 25 12:17:03 CEST 2026

Los procesos que ya estaban en marcha conservan la zona con la que arrancaron. Reinicia al menos cron y el registro del sistema para que las tareas programadas y los logs usen la nueva zona:

sudo systemctl restart cron rsyslog

Si ejecutas aplicaciones de larga duración (PHP-FPM, bases de datos, servicios Java o Node.js), reinícialas también, o reinicia el servidor cuando puedas.

Para comprobar una hora en otra zona sin cambiar la del sistema, define TZ solo para ese comando:

TZ=America/New_York date
Thu Sep 25 06:17:10 EDT 2026

Paso 4: Sincronizar la hora con NTP

Ubuntu 24.04 usa systemd-timesyncd para mantener el reloj sincronizado. Si en el paso 1 NTP service aparecía como inactive, actívalo:

sudo timedatectl set-ntp true

Consulta con qué servidor se sincroniza y el desfase medido:

timedatectl timesync-status
       Server: 185.125.190.58 (ntp.ubuntu.com)
Poll interval: 34min 8s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C0248F8A
    Precision: 1us (-25)
Root distance: 19.305ms (max: 5s)
       Offset: -312us
        Delay: 37.921ms
       Jitter: 1.204ms
 Packet count: 12
    Frequency: +4.113ppm

Un Offset de unos pocos milisegundos o menos indica que el reloj está bien sincronizado.

Usar otros servidores NTP

Por defecto se usa ntp.ubuntu.com. Para usar los servidores del NTP Pool Project o los de tu organización, crea un archivo de configuración adicional:

sudo mkdir -p /etc/systemd/timesyncd.conf.d
sudo nano /etc/systemd/timesyncd.conf.d/ntp.conf
[Time]
NTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org
FallbackNTP=ntp.ubuntu.com

Reinicia el servicio y comprueba el servidor en uso:

sudo systemctl restart systemd-timesyncd
timedatectl timesync-status | grep Server
       Server: 162.159.200.123 (0.pool.ntp.org)

Paso 5: Generar y establecer el locale

El locale define el idioma de los mensajes, la codificación de caracteres y el formato de fechas, números y moneda. En un servidor lo más habitual es dejar los mensajes en inglés (más fáciles de buscar cuando algo falla) con codificación UTF-8.

Lista los locales generados en el sistema:

locale -a
C
C.utf8
POSIX

Genera los locales que necesites. Este ejemplo genera inglés de Estados Unidos y español de España:

sudo locale-gen en_US.UTF-8 es_ES.UTF-8
Generating locales (this might take a while)...
  en_US.UTF-8... done
  es_ES.UTF-8... done
Generation complete.

Establece el locale por defecto del sistema:

sudo localectl set-locale LANG=en_US.UTF-8

El ajuste se guarda en /etc/default/locale y se aplica en los nuevos inicios de sesión. Cierra la sesión SSH, vuelve a entrar y comprueba:

locale | head -3
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"

Combinar idioma y formatos regionales

Las variables LC_* permiten separar el idioma de los formatos. Por ejemplo, mensajes en inglés pero fechas, números y papel en formato español:

sudo localectl set-locale LANG=en_US.UTF-8 LC_TIME=es_ES.UTF-8 LC_NUMERIC=es_ES.UTF-8 LC_PAPER=es_ES.UTF-8
VariableQué controla
LANGValor por defecto para todas las categorías
LC_TIMEFormato de fecha y hora
LC_NUMERICSeparador decimal y de miles
LC_MONETARYFormato de moneda
LC_COLLATEOrden alfabético (afecta a sort y ls)
LC_MESSAGESIdioma de los mensajes de los programas
LC_ALLAnula todas las anteriores. No lo fijes a nivel de sistema

Tras volver a iniciar sesión, comprueba el formato de fecha:

date +%c
jue 25 sep 2026 12:30:11 CEST

Locale por usuario

Un usuario puede usar otro locale sin cambiar el del sistema añadiendo la variable a su ~/.bashrc:

echo 'export LANG=es_ES.UTF-8' >> ~/.bashrc

El locale debe estar generado (paso anterior); si no, el sistema mostrará avisos y usará C.

Paso 6: Comprobar el resultado

Reinicia el servidor para confirmar que la configuración persiste:

sudo reboot

Tras reconectar, revisa los tres ajustes:

timedatectl
locale | head -1
               Local time: Thu 2026-09-25 12:35:20 CEST
           Universal time: Thu 2026-09-25 10:35:20 UTC
                 RTC time: Thu 2026-09-25 10:35:20
                Time zone: Europe/Madrid (CEST, +0200)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
LANG=en_US.UTF-8

Diferencias en Rocky Linux 9 y AlmaLinux 9

  • timedatectl set-timezone y timedatectl list-timezones funcionan igual.

  • La sincronización la hace chronyd. Comprueba su estado y fuentes con:

    chronyc tracking
    chronyc sources
    

    Los servidores se definen con líneas server o pool en /etc/chrony.conf, seguidas de sudo systemctl restart chronyd.

  • Los locales se instalan como paquetes en lugar de generarse con locale-gen:

    sudo dnf install glibc-langpack-es
    
  • localectl set-locale guarda el ajuste en /etc/locale.conf.

Solución de problemas

System clock synchronized: no durante mucho tiempo. Comprueba que el servicio está activo con systemctl status systemd-timesyncd y revisa sus mensajes con journalctl -u systemd-timesyncd. Si ves tiempos de espera agotados, algún cortafuegos está bloqueando la salida al puerto 123/UDP.

Aviso setlocale: LC_ALL: cannot change locale o perl: warning: Setting locale failed al conectar por SSH. El cliente SSH envía sus variables LANG y LC_* y el servidor no tiene ese locale generado. Genera el locale que indica el aviso con sudo locale-gen o deja de enviarlo desde tu equipo comentando SendEnv LANG LC_* en /etc/ssh/ssh_config.

Una tarea cron se ejecuta a una hora distinta de la esperada. cron usa la zona horaria con la que arrancó. Reinícialo con sudo systemctl restart cron tras cambiar la zona.

Una aplicación muestra otra hora distinta a la del sistema. Muchas aplicaciones tienen su propia zona horaria: date.timezone en php.ini, default-time-zone en MySQL o la variable TZ en contenedores Docker. Revisa su configuración además de la del sistema.

Conclusión

Tu servidor tiene ahora una zona horaria explícita, un reloj sincronizado por NTP y un locale UTF-8 generado y persistente. Con estos ajustes, los logs, las tareas programadas y el tratamiento de texto se comportan de forma predecible.

Como siguientes pasos, puedes configurar el hostname y el FQDN del servidor, programar tareas con cron sabiendo en qué zona se ejecutan o centralizar los logs de varios servidores, que ahora comparten una referencia horaria común.