The timezone decides which local time appears in logs, cron schedules and application timestamps, and the locale decides the language, character encoding and date and number formats that programs use. A wrong timezone makes logs from different servers hard to correlate, and a missing locale produces setlocale warnings and broken non-ASCII characters. In this tutorial you will check and set the timezone, confirm NTP time synchronization, and generate and apply locales on Ubuntu 24.04, with the equivalent commands for Rocky Linux 9.

Prerequisites

To follow this tutorial, you will need:

  • A server running Ubuntu 24.04 LTS, for example a CubePath VPS. Rocky Linux 9 differences are covered in their own sections.
  • A non-root user with sudo privileges.

Step 1 - Checking the current time settings

timedatectl shows the time, the timezone and the synchronization status in one place:

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

The important lines are:

  • Time zone: most cloud images default to Etc/UTC.
  • System clock synchronized: yes means the clock is being disciplined by an NTP server.
  • NTP service: active means a time sync daemon is running.
  • RTC in local TZ: should be no on Linux servers. The hardware clock should stay in UTC.

Step 2 - Choosing UTC or a local timezone

For servers, UTC is usually the better choice. It has no daylight saving time changes, so there are no repeated or missing hours in logs, and logs from servers in different regions line up without conversion. Applications can still display local time to users.

Use a local timezone when something on the server must follow local wall-clock time and cannot be configured separately, such as cron jobs that must run at 09:00 local time all year round.

Step 3 - Setting the timezone

Timezones are named Region/City. List them and filter by a city or region:

timedatectl list-timezones | grep -i madrid
Europe/Madrid

Set the timezone:

sudo timedatectl set-timezone Europe/Madrid

To go back to UTC, use sudo timedatectl set-timezone Etc/UTC.

timedatectl points the /etc/localtime symlink at the new zone file. Verify the change:

timedatectl | grep 'Time zone'
ls -l /etc/localtime
                Time zone: Europe/Madrid (CEST, +0200)
lrwxrwxrwx 1 root root 33 Sep 24 12:16 /etc/localtime -> /usr/share/zoneinfo/Europe/Madrid

Running processes may keep using the timezone they read at start. Restart the services whose timestamps matter, in particular cron, which schedules jobs in the timezone it saw at startup:

sudo systemctl restart cron rsyslog

A reboot achieves the same for every service.

Setting a timezone for one user

If the system should stay in UTC but you want local time in your own shell, set the TZ variable in your profile instead of changing the system timezone:

echo 'export TZ=Europe/Madrid' >> ~/.profile

It applies from the next login. Only your sessions and programs you start are affected.

Step 4 - Verifying time synchronization

Accurate time matters more than the timezone: TLS certificate checks, TOTP two-factor codes, Kerberos and distributed databases all fail when the clock drifts. Ubuntu 24.04 synchronizes the clock with systemd-timesyncd, which is enabled by default. Check it:

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

An offset of a few milliseconds or less is normal. If NTP service showed inactive in Step 1, enable synchronization:

sudo timedatectl set-ntp true

Using different NTP servers

By default timesyncd uses ntp.ubuntu.com. To use other servers, for example the public NTP Pool, create a drop-in file rather than editing the main configuration:

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

Restart the service and confirm which server it uses:

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

Time synchronization on Rocky Linux 9

Rocky Linux uses chrony, enabled by default. Check its status with:

chronyc tracking
chronyc sources -v

Servers are set with server or pool lines in /etc/chrony.conf. Restart with sudo systemctl restart chronyd after editing. The timedatectl commands from Step 3 work unchanged on Rocky Linux.

Step 5 - Checking the current locale

The locale is a set of environment variables. LANG is the default for everything, and the LC_* variables override individual categories such as LC_TIME (date format) or LC_NUMERIC (decimal separator). LC_ALL overrides all of them and should not be set permanently.

Show the current values:

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

Ubuntu cloud images often use C.UTF-8, which supports UTF-8 characters but has no language-specific formatting. List the locales that are already generated:

locale -a
C
C.utf8
POSIX

Step 6 - Generating and setting locales

On Ubuntu, a locale must be generated before it can be used. Make sure the locales package is installed, then generate the locales you need. This example generates US English and Spanish:

sudo apt install locales
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.

Set the system default. update-locale writes the values to /etc/default/locale:

sudo update-locale LANG=en_US.UTF-8

A common server setup is English messages with local date formats. You can set individual categories in the same way:

sudo update-locale LANG=en_US.UTF-8 LC_TIME=es_ES.UTF-8

Check the file:

cat /etc/default/locale
LANG=en_US.UTF-8
LC_TIME=es_ES.UTF-8

The new locale applies to new login sessions and to services started after the change. Log out and back in, then run locale again to confirm. Reboot if services need to pick it up.

Locales on Rocky Linux 9

Rocky Linux ships locales as language packs instead of generating them. Install the pack for the language, then set the locale with localectl:

sudo dnf install glibc-langpack-es
sudo localectl set-locale LANG=en_US.UTF-8
localectl status

localectl writes to /etc/locale.conf. English (glibc-langpack-en) is installed by default.

Troubleshooting

  • setlocale: LC_ALL: cannot change locale (es_ES.UTF-8) or perl: warning: Setting locale failed after SSH login: your SSH client forwards its LANG and LC_* variables, and Ubuntu's SSH server accepts them (AcceptEnv LANG LC_* in /etc/ssh/sshd_config), but that locale is not generated on the server. Generate it with sudo locale-gen es_ES.UTF-8, or stop forwarding it by removing SendEnv LANG LC_* from your client's ~/.ssh/config or /etc/ssh/ssh_config.
  • Cron jobs run at the wrong hour after changing the timezone: cron was not restarted. Run sudo systemctl restart cron.
  • System clock synchronized: no for a long time: outbound UDP port 123 may be blocked by a firewall. Check with journalctl -u systemd-timesyncd for timeout messages and allow outgoing NTP traffic.
  • A container shows UTC while the host shows local time: containers have their own /etc/localtime. Set TZ in the container environment or mount the host's /etc/localtime read-only.

Conclusion

Your server now has the timezone you chose, a clock synchronized over NTP, and the locales it needs generated and applied. As next steps, review the schedules in /etc/crontab and your systemd timers against the new timezone, configure the same timezone on the rest of your servers so logs line up, and set the timezone in your databases and application runtimes where they keep their own setting.