Update flatpaks using timers

I've recently replaced all possible apps I had from snaps to Flatpaks.

One of the key feature from flatpak that I like to have and is not present in snaps is being able to install packages as a regular user (rather than requirering a superuser access). On the other hand snap packages are able to update themselves without any interaction, a feature that flatpak lacks by default.

I lied. I still use snaps for Microk8s, LXD and Notable. While Notable has some viable alternatives regarding its installation process, I'm still stuck with snaps for the 2 others. Maybe viable ports will be done soon ? :)

To fix this issue, I'm leveraging Systemd, service unit files, timers, and the ability of systemd to configure such items without admin rights.

Unit files

Both a service unit and a timer unit are needed (they're specific type of systemd's unit file).

At core, a service unit triggers a command which last until the service or the system is stopped. A service can be extensivly configured with environment variables, complex dependencies, pre and post execution commands, etc. In our case, we're just looking to execute a simple task.

The timer will “wrap” the service unit with a configuration tailored to control the regularity of the service execution. A timer unit always relate to a service unit by sharing its name (They'll just have different extensions).

Service unit

The service unit file is created through systemctl (no need to know where the file is, we can let systemd manage that):

systemctl --user edit --force --full flatpak-update.service
# --force will create a new unit if it doesn't already exists
# --full will edit a file in place instead of creating an override
Description=Update flatpak apps

ExecStart=flatpak update --noninteractive --assumeyes


The most important instruction is ExecStart which contains the update command. We're also enforcing a dependency to network availability.

Timer unit

If you start the newly created service as is (systemctl --user start flatpak-update.service) it'll update your packages but won't be scheduled. To trigger that unit on a regular basis, you need a timer:

systemctl --user edit --force --full flatpak-update.timer
Description=Update flatpack packages every hours



The most important instruction (and a bit cryptic one) is OnUnitActiveSec which says “Once you ran a unit for the first time, trigger that unit again at the given interval, starting at first launch", which in our case is 1h. In other words, once a system boots, it'll wait 15 minutes, trigger the service unit, and do so each hours with that “first trigger time” as a reference point.


All components are ready, we just need to start the timer and set it as enabled:

systemctl --user start flatpak-update.timer # Start the timer
systemctl --user enable flatpak-update.timer # Start the timer again when the system (re)starts

You should be able to check the status of your timer(s) now:

systemctl --user list-timers # See your timers and their related timing infos
systemctl --user list-timers --all # --all: Shows non-started timers

More infos

If you're curious about the location of the files your created, the info is available with the status action :

systemctl --user status flatpak-update
     Loaded: loaded (<your_home>/.config/systemd/user/flatpak-update.service; ...

This will also report the status of the last run of your service.

Also notice: using --user means a different instance for systemd than the global one. Each users will have its own repport regarding health. A healthy system won't mean a user (through systemd point of view) will have the same healthy report. Check both:

systemctl is-system-running
systemctl --user is-system-running

For more infos, you can check the following links:

Julien Pericat
Linux Sysadmin, SysOps & DevOps friendly

Happily automating and putting things in containers.