12

I would like to start a service using a systemd unit file. This service requires a password to start. I don't want to store the password in plaintext in the systemd unit file, because it is world-readable. I also don't want to provide this password interactively.

If I were writing a normal script for this, I would store the credentials in a file owned by root with restricted permissions (400 or 600), and then read the file as part of the script. Is there any particular systemd-style way to do this, or should I just follow the same process as I would in a regular shell script?

13

There are two possible approaches here, depending on your requirements. If you do not want to be prompted for the password when the service is activated, use the EnvironmentFile directive. From man systemd.exec:

Similar to Environment= but reads the environment variables from a text file. The text file should contain new-line-separated variable assignments.

If you do want to be prompted, you would use one of the systemd-ask-password directives. From man systemd-ask-password:

systemd-ask-password may be used to query a system password or passphrase from the user, using a question message specified on the command line. When run from a TTY it will query a password on the TTY and print it to standard output. When run with no TTY or with --no-tty it will use the system-wide query mechanism, which allows active users to respond via several agents

| improve this answer | |
  • 2
    Note that there are shortcomings to passing passwords in environment variables (even if the file where the variables are set is protected), since it's usually possible to snoop into environment variables of processes belonging to other users (e.g. using ps ajxewww) so someone might be able to pick it up from there. – filbranden Aug 2 '18 at 15:09
  • Thanks! EnvironmentFile entry with an absolute path to a file with 400 permissions works well. – levibostian Dec 9 '19 at 19:06
  • 1
    @filbranden You cannot read environment variables of processes belonging to other users. – woky Feb 13 at 12:22
3

There's a third alternative to this as well as the 2 suggestion by @jasonwryan.

excerpt from Michael Hampton's answer at ServerFault - How to set environment variable in systemd service?

The current best way to do this is to run systemctl edit myservice, which will create an override file for you or let you edit an existing one.

In normal installations this will create a directory /etc/systemd/system/myservice.service.d, and inside that directory create a file whose name ends in .conf (typically, override.conf), and in this file you can add to or override any part of the unit shipped by the distribution.

For instance, in a file /etc/systemd/system/myservice.service.d/myenv.conf:

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

Also note that if the directory exists and is empty, your service will be disabled! If you don't intend to put something in the directory, ensure that it does not exist.

| improve this answer | |
1

I can offer an additional alternative that may suit your needs but it requires several preconditions to be met:

The next steps are as follow:

Use secret-tool from libsecret to store your password. For example:

$ secret-tool store --label=myProgram myService password
Password: <type it here>

If your executable supports reading the password from an environmental variable, it's better:

[Service]
ExecStart=/usr/bin/sh -c 'env SECRET=$(secret-tool lookup myService password) /usr/bin/script'

If your executable accepts the password as an argument, you can still use secret-tool like so:

[Service]
ExecStart=/usr/bin/sh -c '/usr/bin/script --secret=$(secret-tool lookup myService password)'

Caution: the password will be plain visible when you will run systemctl --user status myUnit.service since it shows the argument as being run on the command line. This means this will also be visible for users running top or ps -aux.

| improve this answer | |

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.