Setting up a system service to start on login for a user

I’m trying to get a service (syncthing) to start for a user on login.

Arch Wiki says

Similar to system units, user units are located in the following directories (ordered by ascending precedence):

/usr/lib/systemd/user/ where units provided by installed packages belong.
~/.local/share/systemd/user/ where units of packages that have been installed in the home directory belong.
/etc/systemd/user/ where system-wide user units are placed by the system administrator.
~/.config/systemd/user/ where the user puts their own units.

But then in the next section says…

All the user units will be placed in ~/.config/systemd/user/.

My unit is currently in /usr/lib/systemd/user/, and indeed when I invoke systemctl --user enable syncthing.service I get

Failed to enable unit: Unit file ~/.config/systemd/user/default.target.wants/syncthing.service does not exist.

Can anyone explain what the wiki means by “Similar to system units, user units are located in the following directories”, if, in fact, the only place user units can be is ~/.config/systemd/user/default.target.wants/?

The service file goes to ~/.config/systemd/user/syncthing.service. Then, do a systemctl --user reload, and the to start, systemctl --user enable --now syncthing

From what I can gather, if you want the syncthing.service to start whenever any user logs in, then you should place the service file in /etc/systemd/user/. You would then enable that service using systemctl enable syncthing.service. Whenever any user logs in, that service will start for them.

If you want the syncthing.service to start only when you log in, then you should place it in your home directory’s .config folder, as per @mithrial’s instructions above, and enable it with the --user flag. Enabling the service will then symlink it into the appropriate .wants subdirectory, and it will run only when you are logged in.

I have lots of systemd timer jobs that I run as a user - here’s the tree of my ~/.config/systemd/user directory:

Tree output
tree --filesfirst ~/.config/systemd/user                                  ✔ 
/home/scotty/.config/systemd/user
├── 000-Instructions.txt
├── bingdailywall.service
├── bingdailywall.timer
├── cleanthumbs.service
├── cleanthumbs.timer
├── geoipdl.service
├── geoipdl.timer
├── hourlytidy.service
├── hourlytidy.timer
├── payday.service
├── payday.timer
├── qbtouch.service
├── qbtouch.timer
├── setshutdowntime.service
├── setshutdowntime.timer
├── whavwall.service
├── whavwall.timer
├── whavwallxmas.service
├── whavwallxmas.timer
├── default.target.wants
│   └── appimagelauncherd.service -> /usr/lib/systemd/user/appimagelauncherd.service
└── timers.target.wants
    ├── bingdailywall.timer -> /home/scotty/.config/systemd/user/bingdailywall.timer
    ├── cleanthumbs.timer -> /home/scotty/.config/systemd/user/cleanthumbs.timer
    ├── geoipdl.timer -> /home/scotty/.config/systemd/user/geoipdl.timer
    ├── hourlytidy.timer -> /home/scotty/.config/systemd/user/hourlytidy.timer
    ├── payday.timer -> /home/scotty/.config/systemd/user/payday.timer
    ├── qbtouch.timer -> /home/scotty/.config/systemd/user/qbtouch.timer
    ├── setshutdowntime.timer -> /home/scotty/.config/systemd/user/setshutdowntime.timer
    ├── whavwall.timer -> /home/scotty/.config/systemd/user/whavwall.timer
    └── whavwallxmas.timer -> /home/scotty/.config/systemd/user/whavwallxmas.timer

3 directories, 29 files

Edit: I just had a look in Pamac at the syncthing package, and their site, and I think there might be a very simple solution to your problem which doesn’t require setting up systemd services. Just add it to autostart via System Settings => Autostart => Add Application (which is the method recommended at their site).

If you want to do it the (slightly) harder way using systemd, then the relevant systemd service files are already installed (I am assuming you installed syncthing from the Manjaro repositories). You just need to do the following, as per the instructions at Starting Syncthing Automatically — Syncthing documentation:

  • Enable and start the service. Replace “myuser” with the actual Syncthing user after the @:

systemctl enable syncthing@myuser.service
systemctl start syncthing@myuser.service

Make sure you include the @ symbol in the command. You could also do it as a single command:

systemctl enable --now syncthing@myuser.service

2 Likes

Thanks. Tried that.

I’m still getting

Failed to enable unit: Unit file ~/.config/systemd/user/default.target.wants/syncthing.service does not exist.

Permissions are all right. The syncthing.service unit is in ~/.config/systemd/user/.

Why is it even looking in ~/.config/systemd/user/default.target.wants/ when it should be expecting the unit in ~/.config/systemd/user/?

My unit, if it helps

[Unit]
Description=Syncthing - Open Source Continuous File Synchronization
Documentation=man:syncthing(1)
StartLimitIntervalSec=60
StartLimitBurst=4

[Service]
ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0
Restart=on-failure
RestartSec=1
SuccessExitStatus=3 4
RestartForceExitStatus=3 4

# Hardening
SystemCallArchitectures=native
MemoryDenyWriteExecute=true
NoNewPrivileges=true

# Elevated permissions to sync ownership (disabled by default),
# see https://docs.syncthing.net/advanced/folder-sync-ownership
#AmbientCapabilities=CAP_CHOWN CAP_FOWNER

[Install]
WantedBy=default.target

For reasons I am at a loss to explain, doing that (using /bin/syncthing) places a syncthing-gtk (which I don’t even have anymore) in the autostart. I think the .desktop for syncthing has gotten messed up somewhere in my long history of using it.

Did you run systemctl --user daemon-reload?

What happens if you run systemctl --user status syncthing?

Yes.

I get.

Warning: The unit file, source configuration file or drop-ins of syncthing.service changed on disk. Run 'systemctl --user daemon-reload' to reload units.
○ syncthing.service - Syncthing - Open Source Continuous File Synchronization
     Loaded: loaded (~/.config/systemd/user/syncthing.service; disabled; preset: enabled)
     Active: inactive (dead)
       Docs: man:syncthing(1)

Ran a second systemctl --user daemon-reload and got…

○ syncthing.service - Syncthing - Open Source Continuous File Synchronization
     Loaded: loaded (~/.config/systemd/user/syncthing.service; disabled; preset: enabled)
     Active: inactive (dead)
       Docs: man:syncthing(1)

… same but without the warning

Ran another systemctl --user enable --now syncthing just in case the first reload didn’t take, but the second did. Same error.

According to the systemd wiki, a “disabled; preset:enabled” means that the system was loaded and cancelled by something.

However journalctl -b -u syncthing.service shows nothing at all has happened with syncthing -- No entries --.

It is unclear to me why it doesn’t create this directory. You could help it and create it manually, right?

mkdir ~/.config/systemd/user/default.target.wants

I could, but I’d rather understand why it’s not working as expected first. Maybe I’ll turn to making the directory as a last resort. Might have to go back through the guidance with a fine toothcomb and see if I’ve missed something.

1 Like

Because, user services that are started are linked in default.target.wants. The enable command, basically only creates a link to a user service file in /usr/lib/systemd/user/ or ~/.config/systemd/user/ in this specific folder.

1 Like

If it’s useful knowledge… I autostart syncthingtray in System Settings, which in turn launches Syncthing shortly after login. Cheers.

1 Like

I use syncthing to move data to and from a firewalled production server and usually syncthing just works.

I have also gone to great length to keep the service private - as in using a private discovery service.

When a package installs a service - whether that is user or system it is (usually) placed /usr/lib/systemd.

When you enable a user service - it will be placed in folder in your ~/.config/systemd - a folder matching the target run level - in the case of syncthing the folder is default-target.wnats.

This is how it looks on my system

 $ tree ~/.config/systemd
/home/fh/.config/systemd
└── user
    ├── check-aur.service
    ├── check-aur.timer
    ├── default.target.wants
    │   ├── modprobed-db.service -> /usr/lib/systemd/user/modprobed-db.service
    │   └── syncthing.service -> /usr/lib/systemd/user/syncthing.service
    ├── protonvpn_reconnect.service
    └── timers.target.wants
        └── check-aur.timer -> /home/fh/.config/systemd/user/check-aur.timer

When you manually create a service you place it in ~/.config/systemd.

The check-aur.timer and check-aur.service is described in [root tip] [HowTo] Check if your AUR build scripts have been updated

When a user service is placed in /usr/lib/systemd/user it is a template service - you need to activate for your user - and should be needless to say never use sudo with user services - this is the only way the system will know which user you are enabling the service for - it is only a template.

systemctl enable --now syncthing@$USER.service

If you omit the @username you will get a service not found - because it does not exist

2 Likes

Only in my case, it doesn’t. It just responds that there is no such service in that folder.

This worked to a point (so thank you - I’ve learned something new at least), in that it seemed to create the symlink in the right place, but it created a symlink to the syncthing@ service. Syncthing documentation says…

Running Syncthing as a system service ensures that Syncthing is run at startup even if the Syncthing user has no active session. Since the system service keeps Syncthing running even without an active user session, it is intended to be used on a server.

… which is not my use case. I’m trying to run it as a user, for which I need to start syncthing.service, not syncthing@.service.

You are not correct - if you are intending to run as a user - you setup syncthing@username.service.

Syncthing can be setup in a wide array of use cases and the questions you ask and the answers given my not correctly reflect your usecase.

The most basic use case is to run syncthing as a user service on two or more systems thus syncing files between the two.

The backdraw to this is that both systems must be up and connected to eachother for a sync process to be executed.

If you want to create a common sync location where you will sync selected files - you will need a server system and setting that up is slightly different - depending on how public you want it to be.

Syncthing documentations says…

How to set up a user service

  1. Create the user who should run the service, or choose an existing one. Probably this will be your own user account.
  2. (Skip if your distribution package already installs these files, see above.) From git location copy the syncthing.service file into the load path of the user instance. To do this without root privileges you can just use this folder under your home directory: ~/.config/systemd/user/.
  3. Enable and start the service:
    systemctl --user enable syncthing.service systemctl --user start syncthing.service

… that’s what I’m trying to follow.

It appears you are using the official documentation on syncthing - am I correct?

From what I can understannd you are also ignoring the fact that the service must be started with a username.

Running Syncthing as a system service ensures that it is running at startup even if the user has no active session, it is intended to be used on a server. Enable and start the syncthing@myusername.service where myusername is the actual name of the Syncthing user.
Syncthing - ArchWiki

Bit of both (Syncthing docs and Arch-Syncthing), but from the Arch Wiki it would be…

User service: on login

Running Syncthing as a systemd user service ensures that Syncthing only starts after the user has logged into the system (e.g., via the graphical login screen, or ssh). This method is intended to be used on a (multiuser) computer. To run the user service, start/enable the user unit syncthing.service (i.e. with the --user flag).

… that I’m following.

Did you install syncthing using the package manager? or by some other means?

I have used syncthing for years and I know other members do as well - if you do it right - it just sync things - sligt joke intended :grin:

I would appear there is either inconsistency in the documentation you are using or you are overlooking something. Perhaps I didn’t understand well enough first time around …

For the system wide service @ character tells that it must be run with an argument - in this case a username - this will run as a system wide service and must be installed with sudo - and loose the --user argument.

Activated with a command like (to have it work with a user not logged in use the linger option as described in the wiki)

sudo systemctl enable --now syncthing@username.service
 $ cat /usr/lib/systemd/system/syncthing@.service
[...]
[Service]
User=%i
ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0
[...]

The user service in the user tree does not require the @ as the call - no sudo - but with the –user argument will place the activation link in your user’s home and only be activated when you login - activate like this

systemctl enable --now --user syncthing.service
 $ cat /usr/lib/systemd/user/syncthing.service
[...]
[Service]
ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0
[...]

Technically you can use either one or the other - the result is the same but with the first can use the linger option to activate with the user actually logging in - at least - that is how I understand it.

Yes, all normal there. The only oddity I can think of that might explain things is that I also used to have Syncthing-GTK installed as a helper, but that stopped working last update so I uninstalled it. I do still have the normal synthing package though, and when I run it from the command line (just syncthing) it runs flawlessly with all my original syncs set up.

The problem just seems to be that enabling the service via systemctl enable --now --user syncthing.service doesn’t seem to behave as expected.

My (uneducated) guess is that there must be something wrong with the syncthing.service unit file (posted above) on my installation that’s causing it to misbehave when run.

Also (unrelated, but annoying, given the alternative) I don’t have the syncthing-start.desktop file as the Synthing docs suggest I should have, but I’ve downloaded that file directly from syncthing’s git and put it in autostart. That also works, so I have a temporary fix, but I don’t like not knowing what’s wrong…

I don’t use any desktop apps - simply launching a web brower at the address will open a configuration page

http://localhost:8384/

There is nothing wrong with it - it is exactly the one I use - and it works as expected. I am running my own discovery server and sync service as I want to keep it private to the company I work for.