Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tarsnap-service: add persistent option for systemd timer #8823

Closed
wants to merge 1 commit into from

Conversation

doshitan
Copy link
Contributor

This is very useful for things like daily backups on a laptop (or any
not constantly running system) since one generally want them to happen
every day the system is awake regardless of if the machine was awake at
the exact trigger time
. In order for this to work reliably, we wait
until we are sure we can connect to the server before backing up.


path = [ pkgs.tarsnap pkgs.coreutils ];
path = [ pkgs.tarsnap pkgs.coreutils pkgs.iputils ];
preStart = "/run/current-system/sw/bin/sh -c 'while ! ping -q -c 1 betatest-server.tarsnap.com &> /dev/null; do true; done'";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this hack?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this, running the service when offline or when the tarsnap server is otherwise unavailable might count as having performed a backup (just guessing here).

I dislike this. I prefer using after/requires network-online.target and leave it at that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To add to this: for persistent timers, it seems systemd only keeps track of whether the service was triggered, not whether it completed successfully. For backups, I suppose the latter is what we actually want ... I'm not quite sure if this hack even accomplishes this, though (i.e, whether systemd waits until the main process starts before counting the service as "triggered").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I wish the network-online.target stuff was enough but it doesn't seem to be and I'm not exactly sure why. The docs seem to suggest that network-online.target should simply work as is or you can use something like NetworkManager-wait-online.service/system-networkd-wait-online.service to force the network.target to wait until the network is online (like network-online.target is suppose to do) which is overkill/overreaching to enable. Now systemd.networkd-wait-online.service had a change about a year ago which removed the before requirement on network.target, so that would seem to suggest that enabling that service might actually make network-online.target work correctly now without requiring everything with dependencies on network.target to wait as well (didn't actually test this). The NetworkManager service still has a before requirement on network.target. We have our own thing for NetworkManager which triggers network-online.target when an interface comes up (which I don't know what exactly NetworkManager's definition of "up" is). Ultimately, if we have to enable a special service to get network-online.target to work for each possible network management system we support, some of them don't provide a built in facility for this waiting stuff (NetworkManager and systemd-networkd ship units to do this but seem to differ in their actual effect on the boot process as mentioned above) and they differ in their definition of what "online" means, then the persistent option is only going to work if users are using some limited set of network management systems and be broken (in the sense that tarsnap will bail out every time) otherwise.

The PreStart hack ensures that the tarsnap only starts when we can actually reach out to the tarsnap server -- regardless of what is managing the network configuration -- since otherwise there's no point in performing a backup. Note, there is a timeout for starting a service (90s by default) so it is not going to sit there forever pinging away. The unit will just fail if we can't connect to the server after 90s, so if the system is extremely slow booting/waking up or the system is extremely slow getting a network connection, then the unit will fail even though it might have worked in a few minutes. We can of course tweak this with TimeoutStartSec in the service file and we could expose this to be configurable by the user if we think it needs to be. Definitely another downside to the PreStart thing, but it hasn't hit me in the year I've been doing it.

I'm happy to explore other options, I'm not very fond of the PreStart thing either, but it's the easiest way I know how to ensure that it works for nearly all cases. If we could get all our network stuff to agree on what network-online.target means, whether that is "I have an IP" or "I can connect to some arbitrary location" or something else, then we might have a clearer way forward, but I suspect they will probably not all mean "I can connect to the internet" since that is a fairly broad definition of "online". Thus, we are probably still going to need something which delays execution until we know that yes, the network is up/"online" and we've at least tried to connect to the outside world before failing.

And yes, persistent timers just track the last time the service was triggered (i.e., the whole service was asked to start, so regardless of it starts successfully or not) not the last time it completed successfully, which is fine for my uses.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unaffected by the backup-will-eventually-succeed-but-not-right-now problem and failed to consider it, but I can see how preStart might be warranted, esp. for people who backup rarely and so could end up not backing up for a long time if the service is triggered at bootup. It is unfortunate that network-online.target is underspecified on NixOS, but that seems to be a more general problem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that doing sh -c ... in preStart is unnecessary.

@joachifm
Copy link
Contributor

cc @thoughtpolice

@@ -258,12 +272,13 @@ in
serviceConfig = {
IOSchedulingClass = "idle";
NoNewPrivileges = "true";
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH";
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_RAW";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can do away with this if you set PermissionsStartOnly = true; then, restrictions only apply to the process launched by ExecStart.

This is very useful for things like daily backups on a laptop (or any
not constantly running system) since one generally want them to happen
every day the system is awake regardless of if the machine was awake *at
the exact trigger time*. In order for this to work reliably, we wait
until we are sure we can connect to the server before backing up.
@doshitan
Copy link
Contributor Author

doshitan commented Aug 6, 2015

Made the couple of changes suggested by @joachifm.


path = [ pkgs.tarsnap pkgs.coreutils ];
path = [ pkgs.tarsnap pkgs.coreutils pkgs.iputils ];
preStart = "while ! ping -q -c 1 betatest-server.tarsnap.com &> /dev/null; do true; done";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

betatest-server? What's that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot check right now, but I believe tarsnap itself uses betatest-server.tarsnap.com to test network connectivity. I think the proposed patch basically replicates what tarsnap does on network resolution failure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

betatest-server.tarsnap.com is the address the tarsnap client connects to, i.e, it's where the tarsnap server code is running. Why it still carries the name betatest after all these years is unknown to me (^_^).

The goal here is to wait until we can connect to the server so that tarsnap doesn't run and just die because it couldn't connect to the server when it could have connected successfully a few seconds later (after the network has finished setting up).

@edolstra
Copy link
Member

Is there actually a reason to make this an option? Maybe just set timerConfig.Persistent = true unconditionally?

@thoughtpolice
Copy link
Member

Sorry for taking so long with this, it looks good to me, and I'll need it for my current laptop. :) I'm cleaning this up and pushing a modified version shortly - thank you for this!

@doshitan
Copy link
Contributor Author

doshitan commented Jan 7, 2016

cool, thank you @thoughtpolice

@doshitan doshitan deleted the tarsnap-persistent-timer branch January 7, 2016 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants