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

Add systemd user service #20871

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Trumeet
Copy link

@Trumeet Trumeet commented May 23, 2024

The [email protected] was introduced by
e00c96d. This system-level unit uses User= to change into a specific user, and qbittorrent will access cache and database files in that user's home.

This is a very bad design, because systemd offers a better solution called systemd-user. It makes units specific to the current user run completely under the user service manager, so there is no need to do User= in the system unit anymore.

The current approach breaks service dependencies because my home directory is dynamically mounted by systemd-homed upon logon, which is unavailable when [email protected] was started, rendering the service to dump its core. By moving the unit to systemd-user, systemd handles all dependencies perfectly since the user unit is only going to be started when the home directory is mounted.

This patch preserves compatibility with existing setups as it does not delete the previous [email protected].

The [email protected] was introduced by
e00c96d. This system-level unit uses
User= to change into a specific user, and qbittorrent will access cache
and database files in that user's home.

This is a very bad design, because systemd offers a better solution called
systemd-user. It makes units specific to the current user run completely under
the user service manager, so there is no need to do User= in the system unit
anymore.

The current approach breaks service dependencies because my home directory is
dynamically mounted by systemd-homed upon logon, which is unavailable when
[email protected] was started, rendering the service to dump its core.
By moving the unit to systemd-user, systemd handles all dependencies perfectly
since the user unit is only going to be started when the home directory is mounted.

This patch preserves compatibility with existing setups as it does not
delete the previous [email protected].

Signed-off-by: Yuuta Liang <[email protected]>
if (SYSTEMD_FOUND AND "${SYSTEMD_USER_SERVICES_INSTALL_DIR}" STREQUAL "")
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
--variable=systemduserunitdir systemd
OUTPUT_VARIABLE SYSTEMD_USER_SERVICES_INSTALL_DIR)
Copy link
Member

Choose a reason for hiding this comment

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

Missing SYSTEMD_USER_SERVICES_INSTALL_DIR at line 6.

@@ -21,6 +21,17 @@ elseif (NOT SYSTEMD_FOUND AND SYSTEMD_SERVICES_INSTALL_DIR)
defined, but we can't find systemd using pkg-config")
endif()

if (SYSTEMD_FOUND AND "${SYSTEMD_USER_SERVICES_INSTALL_DIR}" STREQUAL "")
Copy link
Member

@Chocobo1 Chocobo1 May 23, 2024

Choose a reason for hiding this comment

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

You should merge the new code to the if at line 13. For example:

if (SYSTEMD_FOUND)
    if ("${SYSTEMD_SERVICES_INSTALL_DIR}" STREQUAL "")
        # ...
    endif()
    if ("${SYSTEMD_USER_SERVICES_INSTALL_DIR}" STREQUAL "")
        # ....
    endif()
elseif (NOT SYSTEMD_FOUND)
    if (SYSTEMD_SERVICES_INSTALL_DIR)
        # ...
    endif()
    if (SYSTEMD_USER_SERVICES_INSTALL_DIR)
        # ...
    endif()
endif()

[Service]
Type=simple
PrivateTmp=false
ExecStart=/usr/bin/qbittorrent-nox
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ExecStart=/usr/bin/qbittorrent-nox
ExecStart=@EXPAND_BINDIR@/qbittorrent-nox

@Chocobo1
Copy link
Member

This is a very bad design, because systemd offers a better solution called systemd-user. It makes units specific to the current user run completely under the user service manager, so there is no need to do User= in the system unit anymore.

I'm not familiar with the features so bear with me with the beginner questions.
For our case here, can user-level unit fully replace system-level unit? For example, I have setup a dedicated user qbtUser just for qbt-nox and my own regular user is userA and the question is, how can I start qbt-nox running as qbtUser while logged in as userA?

@Chocobo1 Chocobo1 added the OS: Linux Issues specific to Linux distributions label May 24, 2024
@tessus
Copy link

tessus commented May 25, 2024

TBH this is a very bad idea.

You cannot switch to user systemd unitfiles on a headless server. Please note that the service will no start automatically UNLESS you login.

Edit: the qbittorrent user is a system user. You usually do not login with that user after everything is setup.

@HanabishiRecca
Copy link
Contributor

HanabishiRecca commented May 27, 2024

I use a custom user service on my server right now. One big advantage is that you can control (start/stop/enable/disable/etc) it and access its journal under that user without priviledge escalation.

how can I start qbt-nox running as qbtUser while logged in as userA?

With sudo/su, same as you do it with a system service, but specifying the respective user instead of root. E.g.

$ sudo -u qbtUser systemctl --user start qbittorrent-nox.service

You cannot switch to user systemd unitfiles on a headless server. Please note that the service will no start automatically UNLESS you login.

You totally can. Systemd has a linger function to start user services without requiring user to actually log in.
https://wiki.archlinux.org/title/Systemd/User#Automatic_start-up_of_systemd_user_instances

[Unit]
Description=qBittorrent-nox service
Documentation=man:qbittorrent-nox(1)
Wants=network-online.target
Copy link
Contributor

@HanabishiRecca HanabishiRecca May 27, 2024

Choose a reason for hiding this comment

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

network-online.target doesn't work for user services unfortunately. There are some workarounds though.

systemd/systemd#28762

@tessus
Copy link

tessus commented May 27, 2024

I use a custom user service on my server right now. One big advantage is that you can control (start/stop/enable/disable/etc) it and access its journal under that user without priviledge escalation.

I still do not understand why you would login to the server with a user in the first place.
So imagine you have 20 services running under 20 different users. So you rather log in to all these accounts to do problem determination and reading journals? Even if you used o11y tooling, you'd have to set that up for 20 users.
Also, most of the service users do not even have a home dir or a shell set.

You totally can. Systemd has a linger function to start user services without requiring user to actually log in.

Yep, unfortunately I had issues with that in the past. Maybe they fixed it since then.

However, I still believe that for a headless server a user service is the wrong approach. I agree with you when you talk about a workstation that you login to locally. I could even imagine using user services on a server that has proper users that work on that server.
But the qbittorrent user and account is not an account you log in to - at least I don't.

Please, whatever you do, do not replace the current service. Add the user service as a choice, but do not get rid of the current implementation.

@HanabishiRecca
Copy link
Contributor

HanabishiRecca commented May 27, 2024

I still do not understand why you would login to the server with a user in the first place.

The same reason you don't run the service with root priviledges.
https://en.wikipedia.org/wiki/Principle_of_least_privilege
https://unix.stackexchange.com/questions/82626/why-is-root-login-via-ssh-so-bad-that-everyone-advises-to-disable-it/82639#82639

Even if you don't care, it could be useful if:

  • You are not an admin and only have regular user access.
  • You are an admin, but want to give regular user access to someone else.

Yep, unfortunately I had issues with that in the past. Maybe they fixed it since then.

I didn't face any issues with it.

Please, whatever you do, do not replace the current service.

Of course not. Both system and user services are useful and have their advantages. This MR only adds a new service file, it does not remove the existing one. I don't see any reason not to ship both.

@tessus
Copy link

tessus commented May 27, 2024

The same reason you don't run the service with root priviledges.

That I understand. However, when administering a server manually, I hardly use a user and run all commands with sudo. Using sudo is indeed a good practice, but I usually have a tmux window with a root session and do my admin work there.

I didn't face any issues with it.

Nice. This is good news.

I don't see any reason not to ship both.

Perfect. Thanks.

@johnyb0y
Copy link

johnyb0y commented May 29, 2024

Some more thoughts regarding this:

  • I'd suspect that most people using systemd for controlling something like qBittorrent would want to run it automatically at startup without interaction. I'd say that this is the general intention of someone who uses a systemd service for qBittorrent. Maybe I'm wrong about that?
  • This PR currently only adds the service file which on its own would not accomplish this. @HanabishiRecca Your proposal to use systemd lingering is also what I'd call "advanced systemd". It is not enabled by default and the user needs to take additional steps. So we probably should mention it somewhere. Maybe in a comment inside the service file or something like that.
  • I'd suspect that only enabling lingering using loginctl would not be enough. You would need to daemon-reload and enable the service specifically with the --user flag:
    systemctl --user daemon-reload
    systemctl --user enable SERVICE

@HanabishiRecca
Copy link
Contributor

Maybe I'm wrong about that?

Well, you can use the service on desktop instead of a "dumb" autostart. But this scenario is probably uncommon.

So we probably should mention it somewhere.

It is not our job to explain how systemd works imo, it has its own documentation. Could be mentioned somewhere like the wiki page though.

You would need to daemon-reload and enable the service specifically

There is no difference between system and user services in this regard. Both need to be enabled after install, both need to be reloaded on update.

@johnyb0y
Copy link

I'd argue that there is a certain practice in providing a systemd service example with stuff like qBittorrent without a lot of additional documentation since these service files are nearly always system based service files. So you can somewhat expect a user to know about daemon-reloading, enabling a new service and be done with it. It's common practice.

In my view this changes when you introduce a user based service file. Not a lot of users will have heard about systemd lingering, how to enable it and the required --user flag for systemctl.

If we agree that most users will use systemd service files with qBittorrent to enable automatic startup at boot, introducing this new service example on its own without additional details would not help a lot.

One could argue, why then provide a service example for this in the first place? If we expect the user to learn about this by themselves, they might as well write the service file too :-)

@HanabishiRecca
Copy link
Contributor

In my view this changes when you introduce a user based service file. Not a lot of users will have heard about systemd lingering, how to enable it and the required --user flag for systemctl.

I guess it is more for users wanting a user service specifically for some reason. They probably know what they are doing at this point.

If we expect the user to learn about this by themselves, they might as well write the service file too :-)

That's also true. People who understand systemd services are also probably capable of writing their own. I would say this is a "why not" thing.

@Chocobo1 Chocobo1 changed the title Move systemd service to a user unit Add systemd user service Jun 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS: Linux Issues specific to Linux distributions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants