Linux – Is it possible to override a systemd unit file to create a template unit file

linuxsystemd

I know that systemd provides an excellent mechanism to override a package-provided unit file to influence the service configuration/behavior. This is typically done by using the below command

sudo systemctl edit <unitfile>

to create an override conf file at

/etc/systemd/system/<unitfile.d>/

Systemd also provides a separate mechanism to define a template unit file, and have it instantiated to create instance-specific units at runtime. This requires naming the template file as

<servicename>@.service

and then instantiating it as

systemctl start <servicename>@<instancename>

Now, I have a situation where I would like to run a package-provided service as multiple unit instances. I want to avoid creating my own template unit file, so I am trying to see if the package-provided unit file can be overriden to create the template unit file.

Since, per my understanding, the template unit file has a naming convention that is different from the regular unit file, I think I cannot override the package-provided unit file with a template file by placing it in /etc/systemd/system.

Is there any defined way to achieve what I am trying to do?

Specific scenario:
The grafana package installs a grafana-server.service unit file. I want to run two instances of grafana on my machine – one each for DEV and STG. I have been able to do this:

  • modify the grafana-server.service file (using %I to set folder locations & file paths)
  • rename the modified grafana-server.service to grafana-server@.service
  • start instances of grafana by using:

    sudo systemctl start grafana-server@dev
    

    and

    sudo systemctl start grafana-server@stg
    

However, this breaks the link from the grafana provided service unit file, and if they enhance the service file when I upgrade, I will need to redo this activity again. My objective is to avoid this direct dependency, and instead convert it to an override dependency.

Any thoughts?

Best Answer

For both options below, first override the grafana-server.service (without the @) on /etc/systemd/system and suppress ExecStart (supposing it uses that) to make it starts nothing. On /etc/systemd/system/grafana-server.service.d/10-disable-execstart.conf:

[Service]
ExecStart=
WorkingDirectory=/path/to/your/confdir

Option 1 - Overriding with generic instances

Create a grafana-server@.service that corresponds to your settings with the following configuration to [Unit] and [Service]:

[Unit]
PartOf=grafana-server.service
ReloadPropagatedFrom=grafana-server.service

These should bind grafana-server start/stop/restart to all your instances together. The magic is not very well documented, but if you put <instance_name>.conf files on your /path/to/your/confdir, all those instances will be bound automagically!

Option 2 - Overriding specific instances to keep package config

If you want to keep all update goodness from package service file, but accept mainaining custom instances options, create a symbolic link for each instance name from generic

/lib/systemd/system/grafana-server.service

to

/etc/systemd/system/grafana-service@<instance>.service

and then override only the specific options of that instance using

/etc/systemd/system/grafana-server@<instance>.service.d/99-my-options.conf

Make sure to add the following configuration to [Unit] and [Service] to 99-my-options.conf:

[Unit]
PartOf=grafana-server.service
ReloadPropagatedFrom=grafana-server.service

This will assume for each instance all grafana-server.service options and will override them with all options on 99-my-options.conf file and also bind start/stop/restart actions to grafana-server.service.

On both options, if you run

systemctl start grafana-server.service

all your instances which have a /path/to/confdir/<instance>.conf file will be started. The same apply to stop and restart AND you can always manage them individually by using their grafana-server@<instance> service name.