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

User= and Group= environment variable substitution #5501

Closed
1 of 2 tasks
9fcc opened this issue Mar 1, 2017 · 7 comments
Closed
1 of 2 tasks

User= and Group= environment variable substitution #5501

9fcc opened this issue Mar 1, 2017 · 7 comments
Labels
pid1 RFE 🎁 Request for Enhancement, i.e. a feature request

Comments

@9fcc
Copy link

9fcc commented Mar 1, 2017

Submission type

  • Bug report
  • Request for enhancement (RFE)

NOTE: Do not submit anything other than bug reports or RFEs via the issue tracker!

systemd version the issue has been seen with

215

NOTE: Do not submit bug reports about anything but the two most recently released systemd versions upstream!

Used distribution

Debian Jessie

In case of bug report: Expected behaviour you didn't see

Feature request

User= and Group= directives doesn't allow environment variables (from EnvironmentFile=), but many system services are running under users specified in configuration files.

I want to put user and group name into configuration file and run my services under specified user and group. Moreover one of the services is running under root but then it executes another process under the same specified user. So I need 3 service files running under the same user and 1 configuration file. I could turn them into 1, but I want to restart them independently. So if someday I'll change user name than I'll have to rename it in 4 files.

I've tried to use workaround with su:

Type=notify
EnvironmentFile=/etc/default/my-config
ExecStart=/bin/su -m -s /bin/sh -c /usr/bin/my-service - $MY_USER

But in this case user process can't send notify with systemd-notify --ready. So I had to put username hardcoded.

Can you add variable substitution to User= and Group= directives?

@gdamjan
Copy link
Contributor

gdamjan commented Mar 1, 2017

your usage scenario is not clear, but you can do a template service file and
User=%i like user@.service does

@poettering
Copy link
Member

We explicitly only track issues with the two most recently released upstream versions here. That's 231 and 232 currently, and certainly not 215. This is explicitly clarified when posting an issue.

environment variable expansion is only available on ExecXYZ= since the environment block is only assembled at the time we fork something off, from various sources, such as EnvironmentFile=, Environment=, PassEnvironment=, the env block PID 1 manages itself, as well as env vars PID1 sets for each service individually. Since a numbre of these are highly dependent on runtime parameters, but User=/Group= need to be processed at config load time we can't add env var resolution to them. sorry...

As @gdamjan suggested, consider using instances and the %i specifier if you are looking for a way to write a single unit file that can be instantiated for different parameters easily.

Closing. Sorry!

@poettering poettering added pid1 RFE 🎁 Request for Enhancement, i.e. a feature request labels Mar 1, 2017
@9fcc
Copy link
Author

9fcc commented Mar 2, 2017

and certainly not 215.

@poettering I can't use new versions at the moment, but I'd want to see this feature in next versions. Sorry but I've just pointed which version doesn't have the feature. It's a feature request, so I think version number is useless. May template description be fixed to consider this? As you said this feature is not implemented in any version due to assembling while forking.

As @gdamjan suggested, consider using instances and the %i specifier if you are looking for a way to write a single unit file that can be instantiated for different parameters easily.

I have an embedded device and only one user for GUI interface. The user permissions are restricted and I don't want him to see daemon files in .config directory. I've cleaned up almost all from home directory and made root partition read-only and invisible for the user, while home directory is rw mounted and can be used by him to store files.

So storing systemd config files (and %i) in the home directory is unacceptable for me. I want to hide them.

but User=/Group= need to be processed at config load time we can't add env var resolution to them.

Can then a new parameter be added? Something like ConfigFile= to point configuration file instead of environment.

What I'd like to see is:

Type=notify
EnvironmentFile=/etc/default/my-config
ExecStart=/usr/bin/my-service
User=$MY_USER
Group=$MY_GROUP

or

Type=notify
ExecStart=/usr/bin/my-service
ConfigFile=/etc/default/my-config
User=$MY_USER
Group=$MY_GROUP

And EnvironmentFile= is the first thing I tried until I've figured out from documentation that only few parameters accept variables. It would be great if more parameters would accept them.

So can this request be open again?

@gdamjan
Copy link
Contributor

gdamjan commented Mar 2, 2017

@9fcc we better continue on the IRC channel. you seem misguided about some details in systemd

@ebikt
Copy link

ebikt commented May 23, 2018

Any progress on this? We would like also to use this feature: Specifying some parameteres in template and other indirectly via some configuration/environmet files, where the indirect parameters include: User, SyslogIdentifier, SyslogFacility, StandardOutput, StandardError, ...

@filbranden
Copy link
Member

Do drop-in units do what you need here?

For foo.service, you could create an /etc/systemd/system/foo.service.d/override.conf and add the User and Group setting there:

# /etc/systemd/system/foo.service.d/override.conf
[Service]
User=myuser
Group=mygroup

You can use any file name with the .conf extension in that directory. You can also use systemctl edit foo.service to create that file and open it in an editor (see systemctl man page for more details on that.)

I really don't see environment variables being used in more options really... But I think drop-in files might be close to what you're looking for?

@ebikt
Copy link

ebikt commented May 28, 2018

The idea was to provide single config file which will be parsed by systemd as well as sys-v init initscript on older distributions. But we abandoed the idea anyway, because we need to use also systemd-notify. The program itself is not compiled with systemd notify support, so we run monitor-wrapper which forks, parents does exec(server) and child does systemd-notify when it observes parent is ready. This setup does not work with non-root 'User' setting. (I don't know why, and after other "surprises" from systemd I lost interest in getting know how this should be done correctly.)

carlosalvesuy added a commit to Perceptyx/minio-formula that referenced this issue Apr 18, 2019
Add pillar.example, it should contain the bare minimum config options
needed to make minio works.
Add files/minio.etc.default.jinja, it should reflect the config
options present in the pillar.example file.
Update files/minio.service.jinja, little *WARNING* here;

The **EnvironmentFile** parameter is used to read the environment
variables from the `/etc/default/minio` file, those are used later
for variable expansion in **ExecStart** but they cannot be used
for the **User** and **Group** parameters. In fact environment variable
expansion is only available on *ExecXYZ=* as can be seen here:
systemd/systemd#5501 (comment)
Seems that it will stay that way. That's the reason for having a
template for the minio service file, as User, Group, LimitNOFILE can't
be configured by environment variable expansion.
ubitux added a commit to ubitux/rest-server that referenced this issue Aug 27, 2021
I tried several approaches to this. First, I thought I could away by
adding something like EnvironmentFile=/etc/conf.d/rust-server to the
proposed .service file so that users could copy the service without
editing it and instead patch a config file. Unfortunately, it does not
seem possible to customize User, Group and ReadWritePaths through
environment overrides¹.

Similarly, the ExecStart directive is problematic because we can't
customize the program argument, for example if we want to do
ExecStart=$RUST_SERVER_PREFIX/bin/rest-server in case the user install
it in another location such as /usr instead of /usr/local.

Then I tried overriding settings with systemctl edit, but without the
--full argument the ExecStart can not be customized, because it adds a
2nd directive instead of adding one. That's why the --full switch is
present in the example.

Finally, during my tests, I was trying --path /tmp/restic-backups, which
failed due to the namespacing security. For that reason I added a
warning.

[1]: systemd/systemd#5501
ubitux added a commit to ubitux/rest-server that referenced this issue Aug 27, 2021
I tried several approaches to this. First, I thought I could away by
adding something like EnvironmentFile=/etc/conf.d/rust-server to the
proposed .service file so that users could copy the service without
editing it and instead patch a config file. Unfortunately, it does not
seem possible to customize User, Group and ReadWritePaths through
environment overrides¹.

Similarly, the ExecStart directive is problematic because we can't
customize the program argument, for example if we want to do
ExecStart=$RUST_SERVER_PREFIX/bin/rest-server in case the user installs
it in another location such as /usr instead of /usr/local.

Then I tried overriding settings with systemctl edit, but without the
--full argument the ExecStart can not be customized, because it adds a
2nd directive instead of replacing it. That's why the --full switch is
present in the example.

Finally, during my tests, I was trying --path /tmp/restic-backups, which
failed due to the namespacing security. For that reason I added a
warning.

[1]: systemd/systemd#5501
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pid1 RFE 🎁 Request for Enhancement, i.e. a feature request
Development

No branches or pull requests

5 participants