Skip to content

permission and ordering concerns regarding the current preservation implementation #24

Description

@rebmit

I have some concerns regarding the current preservation implementation, particularly commit 97104c0.

Permission setup and bind-mount timing

Currently, the approach appears to bind-mount directories first and then use systemd-tmpfiles-setup.service to set their permissions.

This creates a window where services using RequiresMountsFor= with DefaultDependencies=no can observe these directories before their intended permissions are in place.

Preserved directories are expected to have correct permissions as soon as they appear; applying them afterward introduces a race during early boot.

A real example is systemd-journal-flush.service, which uses RequiresMountsFor= and is ordered before systemd-tmpfiles-setup.service. While this specific case does not lead to observable failures, the ordering itself still appears conceptually unsound.

Conflicting tmpfiles rules

There could be multiple tmpfiles rules for the same directory.

For example, if a user wants to preserve the /var/tmp directory, tmpfiles.d/preservation.conf may define it, while systemd's default tmp.conf also defines /var/tmp as:

q /var/tmp 1777 root root 30d

to periodically clean temporary files.

In such cases, one of the rules will be ignored. This causes systemd's default tmpfiles-based cleanup of /var/tmp to be bypassed.

systemd-tmpfiles[482]: /etc/tmpfiles.d/tmp.conf:12: Duplicate line for path "/var/tmp", ignoring.

I believe that other tmpfiles configurations should be respected, and preservation should not unintentionally override them.

Personal suggestion

One possible approach to avoid both ordering and permission issues would be to introduce a dedicated systemd-tmpfiles-setup-preservation.service that runs earlier in the boot process. Its responsibilities would be:

  1. Create and apply permissions for preserved paths before they are bind-mounted
  2. Leave the regular systemd-tmpfiles-setup.service to run afterwards as usual, so that default tmpfiles definitions are still respected

It could look conceptually similar to something like the following:

systemd.services.systemd-tmpfiles-setup-preservation = {
  wantedBy = [ "preservation.target" ];
  after = [
    "systemd-sysusers.service"
    "systemd-journald.service"
  ];
  before = [
    "shutdown.target"
    "sysinit.target"
    "initrd-switch-root.target"
    "systemd-tmpfiles-setup.service"
    "preservation.target"
  ];
  conflicts = [
    "shutdown.target"
    "initrd-switch-root.target"
  ];
  unitConfig = {
    DefaultDependencies = false;
    RefuseManualStop = true;
    RequiresMountsFor = "/persist";
  };
  serviceConfig = {
    Type = "oneshot";
    RemainAfterExit = true;
    ExecStart = "systemd-tmpfiles --create --remove --boot /etc/preservation.conf";
    ...
  };
};

I have experimented with this idea for a while in my personal repo. I'd be interested in hearing thoughts from maintainers, users, and other contributors on whether this approach makes sense, and I'd be happy to help explore or iterate on it if it seems useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions