21

For instance, I have a service named mysshd.service under /usr/lib/systemd/system/ directory. Can I create a symbolic link such as:

ln -s /usr/lib/systemd/system/mysshd.service /usr/lib/systemd/system/fool.service

so that whatever operation I do with fool.service will be reflected to mysshd.service (systemctl enable/disable start/stop fool.servce) ?

My purpose is that overwrite the native sshd service by a symbolic link of my own sshd service.

4
  • 2
    Why not add and enable your service and disable the native sshd service?
    – Lambert
    Apr 3, 2015 at 9:21
  • I want my software is compatible with previous version which used a symbolic link /etc/init.d/ssh -> /etc/init.d/myssh.
    – nick
    Apr 3, 2015 at 9:26
  • I still do not exactly understand what you mean but according to your line <quote>so that whatever operation I do with fool.service will be reflect to mysshd.service (systemctl enable/disable start/stop fool.servce) ?</quote> you might have a look at systemd dependencies (see wiki.archlinux.org/index.php/systemd#Handling_dependencies) for starting/enabling your service after sshd.
    – Lambert
    Apr 3, 2015 at 9:31
  • @nick welcome to Stack Exchange! on Stack Exchange it's customary to show kudos for answers by upvoting. you can do this by clicking the up arrow at the left of the answer. if my answer solved your problem, you might also consider clicking the checkbox, to mark it as accepted. thanks!
    – strugee
    Apr 19, 2015 at 4:34

4 Answers 4

15

Use link with the full path:

systemctl link /home/nick/myservice.service

Note that you can't link to a file that is in itself already a link.

1
  • 1
    add --user, if applicable
    – evandrix
    Mar 29, 2020 at 15:38
11

As far as I know, systemd won't deal with this particularly well. As I understand it, you want to override the behavior of sshd.service, right?

Luckily for you, systemd is designed for this kind of thing. Simply put your service definition in /etc/systemd/system/ssh.service, execute systemctl daemon-reload to reload unit files, and systemd will automatically use that configuration instead of the system ssh.service.

Want to have systemctl enable mysshd.service work, too? No problem. In the [Install] section of your unit file, add a line that says Alias=mysshd.service. Then execute systemctl reenable ssh.service to have systemd fix the unit symlinks, and you're golden.

Now, you haven't given details on what mysshd.service is supposed to do. If it's completely different from the normal ssh.service, great! Use the method above. However, if you just want to change one small thing, then you're using the wrong approach. systemd allows you to create "snippets" of unit files that will be applied on top of the normal unit files. This lets you add or override individual directives while allowing the rest of the unit file to receive updates from the package manager. To do this, simply create /etc/systemd/system/ssh.d/my-custom-config.conf (you can change my-custom-config.conf to be whatever you want, and you can also have multiple override files). In that file, place whatever directives you want to change or add to the usual ssh.service. You can even add Alias= directives, so that systemctl start mysshd.service works! Just remember to execute systemctl daemon-reload after you're done (and, if you used Alias=, systemctl reenable ssh.service).

As an aside, never, ever change systemd unit files in /usr/lib/systemd. Ever! The Filesystem Hierarchy Standard requires that /usr is treated as read-only. In practice, this means that the package manager handles /usr (except for /usr/local), and you don't touch what the package manager handles - especially because whatever you change will probably eventually be overwritten. Instead, put your stuff in somewhere like /etc.

3
  • 1
    To clarify it a bit: if you want to override foo.service, run sudo systemctl edit foo.service, and it will save whatever you typed in /etc/systemd/system/foo.service.d/override.conf.
    – Rockallite
    Mar 16, 2017 at 3:47
  • Also, Alias= directive does NOT work in override files. See github.com/systemd/systemd/issues/1090
    – Rockallite
    Mar 16, 2017 at 3:54
  • @Rockallite didn't know about systemctl edit at the time I wrote this answer. feel free to edit my answer to reflect the Alias= bug (put "OK with answerer" or something in the edit message). good catch.
    – strugee
    Mar 16, 2017 at 4:19
2

Symlinks didn't used to be possible. But they are as of today.

0

Others have answered this question, however no one pointed out that you cannot create symbolic links to units that live in a user's home directory. They must live outside of it. Even if its owned by root, configured for 644 permissions, it will not work. Must be outside of /home.

@evandrix pointed out that you can use the --user flag. The process is more complicated than that. "--user" can only be applied to systemd units that are enabled in the user's directory. This allows users to control their own services outside of the --system domain. Be aware only specific version of systemd (I forget which ones but 2.37 and above are working for me) employee the --user domain. I recommend reading this post:

https://nts.strzibny.name/systemd-user-services/

Also this arch page gives good info too:

https://wiki.archlinux.org/title/systemd/User

Quick breakdown of how to do it:

  1. User account must have a password. This will not work if the account does not have a password
  2. perform a ps -aux | grep systemd You should see a "/usr/lib/systemd/systemd --user" for the specific user. This service is started when the user logs in for the firs time by pam.d
  3. Does /home/YourUserName/.config/systemd/user/ directory exist? If it does, put your unit files in there. If it does not create it, and put your units in there.
  4. Log out and log back in after moving your units to the above directory.
  5. Perform these commands
$ systemctl --user enable myuser.service
$ systemctl --user daemon-reload

Now you can run all systemctl commands as the user, but you need to include the --user flag.

$ systemctl --user status myuser.service
$ systemctl --user start myuser.service
$ systemctl --user restart myuser.service
$ systemctl --user stop myuser.service

Be aware your "User" and "Group" settings in your unit's [Service] section need to set appropriately. Also when using --user, do not use systemctl link myuser.service this will not work as it only works in the system domain. The symbolic links for users are built when running systemctl --user enable myuser.service and links to /home/YourUserName/.config/systemd/user/multi-user.target.wants/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.