Integrating timedatectl//systemd-timesyncd with readonly root file system

Hello,

One of the requirements in my project is to change timezone of the system. I am using timedatectl to achieve this.

My file system being read only I am unable to change the timezone on the device.

-rw-r--r-- 1 root root    10 Jul 17 21:48 timezone
lrwxrwxrwx 1 root root    29 Jul 17 21:48 localtime -> /usr/share/zoneinfo/Universal
-rw-r--r-- 1 root root    15 Aug 14 22:08 timestamp

Should I just create a symlink for timezone and timestamp ?

Edit1: I am currently looking at https://bugs.launchpad.net/ubuntu/+source/ubuntu-system-settings/+bug/1227520

I think they are facing somewhat similar situation. But they are suggesting to create a symlink of /etc/localtime as well. Which I don’t understand?

That is how I would start but it’s always a bit of trial and error to figure out everything that needs to be moved.

I haven’t tried this myself so I don’t have a definite answer though. Please let us know what you find.

Drew

meaning just create a symlink of timezone and timestamp?

I was able to create a symlink for localtime and timezone by editing the tzdata recipe file. But I am still unable to change the timezone.

Any suggestions?

@drewmoseley how do people change timezone on a read-only file system?

I don’t know. I can’t say I’ve ever tried that.
Drew

So I think. I know what the issue might be. The file timedated.c actually looks for \etc\localtime it read and writes using that file specifically. So I think irrespective of what symlink I create I will not be able to change the timezone unless I change that link in the c file. But I have some trouble understanding the c file

static int context_read_data(Context *c) {
        _cleanup_free_ char *t = NULL;
        int r;

        assert(c);

        r = get_timezone(&t);
        if (r == -EINVAL)
                log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.");
        else if (r < 0)
                log_warning_errno(r, "Failed to get target of /etc/localtime: %m");

        free_and_replace(c->zone, t);

        c->local_rtc = clock_is_localtime(NULL) > 0;

        return 0;
}   

Where is the function get_timezone() defined?

I assume that is a standard system function provided by the C library or some such.
One possibility may be to use a bind mount of /etc/localtime into the /data partition. I have not tried it myself but that may work:

# mount -t bind /data/localtime /etc/localtime

And then /data/localtime is the symlink to the file in /usr/share/zoneinfo.

Drew

See this link for a discussion in the Yocto community about this.

I recently saw this link. But your method sounds less painful

So based on that link. I did create a volatile bind.
VOLATILE_BINDS ?= "\ /data/system/localtime /etc/localtime \ n\ "
I do see
/data/system/localtime -> /usr/share/zoneinfo/Universal But I am still unable to use timedatectl set-timezone "America/New_York"

Still the same error:
Failed to set timezone: failed to set timezone: Read only file system

So I am able to change the timezone. But my date command is still in UTC?

root@raspberrypi-cm3:~# timedatectl
               Local time: Fri 2020-08-21 17:55:02 EDT
           Universal time: Fri 2020-08-21 21:55:02 UTC
                 RTC time: Fri 2020-08-21 21:55:03
                Time zone: America/New_York (EDT, -0400)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
root@raspberrypi-cm3:~# date
Fri Aug 21 21:55:16 UTC 2020
root@raspberrypi-cm3:~#

Any help or pointers why this could be happening?

That’s just how the date command works. It does respect the TZ environment variable:

$ TZ=America/New_York date
Sat Aug 22 17:07:31 EDT 2020
$ TZ=America/Los_Angeles date
Sat Aug 22 14:07:44 PDT 2020

More details: https://unix.stackexchange.com/questions/48101/how-can-i-have-date-output-the-time-from-a-different-timezone

But that was not how my system was behaving before the read-only rootfs.
Below is an example of the system. That does not have a read-only rootfs

root@raspberrypi-cm3:~# date
Mon Aug 24 08:23:46 CDT 2020
root@raspberrypi-cm3:~# timedatectl
               Local time: Mon 2020-08-24 08:23:52 CDT
           Universal time: Mon 2020-08-24 13:23:52 UTC
                 RTC time: Mon 2020-08-24 13:23:53
                Time zone: America/Chicago (CDT, -0500)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
root@raspberrypi-cm3:~#

The problem with exporting TZ is I can execute it from a script. As it does not make a global change

FYI I am using this link as template

I got it working thanks a lot for all the help :slight_smile:

1 Like

@thesillywhat could you please share a solution for your problem? I’m facing the same issue now and do not want to reinvent the wheel… Thanks!

Look at the link in my comment above. I have currently marked that particular link as a solution.
Also please let me know if you have found a better way

@thesillywhat I am too facing similar issue with readonly root file system, I had follwed the link this link which you mentioned but still when changing timezone using timedatectl it showing Read-Only filesystem. Can you support me to resolve this issue.

The systemd version i was using is
root@Docsis-Gateway:~# systemctl --version
systemd 244 (244)
+PAM -AUDIT -SELINUX +IMA -APPARMOR -SMACK +SYSVINIT +UTMP -LIBCRYPTSETUP -GCRYPT -GNUTLS -ACL +XZ -LZ4 -SECCOMP +BLKID -ELFUTILS +KMOD -IDN2 -IDN -PCRE2 default-hierarchy=hybrid

@vssaran the link to the systemd PR is not really applicable, it was never merged. The technique that I’ve successfully used in the past is to softlink the required directories in /etc to a writeable, persistent place as mentioned in Integrating timedatectl//systemd-timesyncd with readonly root file system - #8 by drewmoseley

@TheYoctoJester Thanks for the idea. It worked using mount-copybind.

1 Like