Nixpkgs: syncthing for multiple users

Created on 19 Nov 2017  路  15Comments  路  Source: NixOS/nixpkgs

config.services.syncthing allows configuring only one syncthing service. However, multiple users should be configured as separate processes according to syncthing documentation: https://docs.syncthing.net/users/faq.html#how-do-i-configure-multiple-users-on-a-single-machine

It would be nice if config.services.syncthing would be converted to a list of syncthing definitions, or whatever is the best way to support multiple syncthing instances.

All 15 comments

I can try to contribute the required changes, but I'd like to hear opinions on what to actually do.

cc @peterhoeg @rnhmjoj

services.syncthing configures a system-wide service, with a dedicated user and all the related options iff config.services.systemService is true. You can still run any number of syncthing services on any users by setting services.syncthing = true and then running systemctl --user start synthing.

@rnhmjoj Oh, wow! :+1: That seems to work, although based on the nix file I don't understand how. So, I guess this can be closed.

although based on the nix file I don't understand how

You are correct, the syncthing module doesn't create the user service anymore. Thanks to @peterhoeg NixOS is directly using the unit file provided upstream as other distros do.

@jluttine, you can do this to activate the user service for all users:

systemd.user.services.syncthing.wantedBy = [ "default.target" ];

Shouldn't this follow the emacs per-user service example in the manual?

In other words:

{ 
  services.syncthing.enable = false; # Do not start the service system-wide...
  services.syncthing.install = true; # ...but never-the-less, make it available to individual users
}

The way services are handled (at least so far) is very much up to the individual maintainers which is far from ideal and we absolutely should standardize both the names for the various options as well as how we handle them. This is something I have wanted to do for a long time but never got around to. I really don't know if the emacs way is the best way forward or something else entirely but it would be worth at least starting the conversation. That should however, belong in a separate issue.

If there isn't one, an RFC certainly seems to be warranted.

(Though, given that there's not much difference technically, IMO the least surprising behavior for new services would be to follow whats in the manual as a de facto standard in the mean time. If nothing else it makes it easier to refactor everything uniformly to follow a new standard.)

If there isn't one, an RFC certainly seems to be warranted.

Absolutely.

IMO the least surprising behavior for new services would be to follow whats in the manual as a de facto standard in the mean time

Fully agree. Ping me in a PR? ;-)

I looked into this, but after some quick hacking I was surprised to notice that the emacs doesn't actually do exactly what I was expecting:

  config = mkIf (cfg.enable || cfg.install) {. 
    systemd.user.services.emacs = {
      ....
    } // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };

Specifically it uses systemd.user.services for both scenarios. This doesn't sound right for syncthing: I want to be able to deploy it to the cloud for "non-interactive" use. I may need to retract my initial reaction.

We have a few different scenarios here:

  1. Run as a system-wide "single user" through a systemd system unit. This should only be the case when specifically enabled (the cfg.enable case). Should default to false.
  2. Run for all interactive users by default through a systemd user unit. One example for this is dbus that we want to have available for everybody but probably not the case for emacs/syncthing. This would be a "system vs user run mode" that defaults to "system".
  3. Available to run for interactive users through a systemd user unit. This would be the cfg.install option.

Some thought really needs to go into the best way of structuring this.

services.syncthing configures a system-wide service, with a dedicated user and all the related options iff config.services.systemService is true. You can still run any number of syncthing services on any users by setting services.syncthing = true and then running systemctl --user start synthing.

How can I accomplish that declaratively via configuration.nix?

I want to run a syncthing service for a handful of particular users, but not for all of them. Furthermore, I'd like those services to start at boot-time, i.e. not just when the users log in.

Is that possible with the current code?

There is no option to control user services declaratively afaik. You can enable a service for a certain user by symlinking the syncthing unit file like this:

ln -s /run/current-system/etc/systemd/user/syncthing.service $XDG_CONFIG_HOME/systemd/user/default.target.wants

this should make the default.target depend on syncthing so it will be started on login. I'm not sure about starting at boot, maybe with loginctl enable-linger.

I ended up duplicating the code from the main syncthing module in a function

~
mkJob = user: {
"syncthing-${user}" = {
description = "Syncthing service for user ${user}";
after = [ "network.target" ];
environment = { STNOUPGRADE = "yes"; };
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "on-failure";
SuccessExitStatus = "2 3 4";
RestartForceExitStatus="3 4";
User = user;
Group = "users";
PermissionsStartOnly = true;
ExecStart = "${config.services.syncthing.package}/bin/syncthing -no-restart -no-browser -home=/var/lib/syncthing/${user}";
};
};
};
~

than can define services per user, like so:

systemd.services = mkJob "foo" // mkJob "bar";

It's not pretty, but it works fine. Now, what's missing is a way to configure the listen addresses for the actual sync service declaratively. I ended up editing lots of config.xml files ...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

copumpkin picture copumpkin  路  3Comments

edolstra picture edolstra  路  3Comments

spacekitteh picture spacekitteh  路  3Comments

matthiasbeyer picture matthiasbeyer  路  3Comments

grahamc picture grahamc  路  3Comments