You are not logged in.

#1 2020-09-29 16:33:17

kevdog
Member
Registered: 2013-01-26
Posts: 102

Creating systemd service file with multiple variables

I'm trying to pass multiple dynamic variables to a systemd service file.  I'm aware of the use of systemd templates  --ie service-file@.service

Typically with a one variable service file I would do the following

...
ExecStart="/root/.acme.sh"/acme.sh --cron --debug --home "/root/.acme.sh" --renew --dns dns_cf -d %i --log
...

%i in the example above represents one variable without any spaces

I'd like however to pass multiple variables within %i -- I'm not sure how to do this however I found this post as a reference but it doesn't seem to be working:
https://superuser.com/posts/1471682/revisions

Clearly doing something like this isn't working:

ExecStart="/usr/bin/docker-compose -f /etc/docker/compose/"arg1"/docker-compose.yml up -d --force-recreate" arg2

Offline

#2 2020-10-02 14:53:31

berbae
Member
From: France
Registered: 2007-02-12
Posts: 1,302

Re: Creating systemd service file with multiple variables

man systemd.exec

See the part:

ENVIRONMENT
       Environment=
...
       EnvironmentFile=
...

Offline

#3 2020-10-02 16:38:08

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,525
Website

Re: Creating systemd service file with multiple variables

The link you provide has nothing to do with passing arguments to systemd template service files, but simply passing multiple arguments to the command executed by the "Exec" line.

How would you even pass multiple arguments to a service file (without an environment file)?  Whatever is between the "@" and ".service" (or the "@" and the end of the token) is the argument: there's only one.

You could have whatever is called by the Exec line tokenize this input if you wanted.  What is your use case?  In your docker example, what might arg1 and arg2 be?  And why would you want them specified in the unit name?


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#4 2020-10-02 22:36:57

kevdog
Member
Registered: 2013-01-26
Posts: 102

Re: Creating systemd service file with multiple variables

@Inspector Parrot --

arg1 would represent a directory name, and arg2 would represent the specific container needing to be restarted in the docker stack.

Offline

#5 2020-10-02 22:51:03

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,525
Website

Re: Creating systemd service file with multiple variables

I didn't mean what would the represent, that's clear from the command. What would you actually need to put into their place, and how would it vary?  How many containers do you have?  How many directories might this need to run on?  And again, why would any of this be in a unit instance variable?  Note that I'm just asking because I'm curious what you are trying to do and how / why you thought a service template might be a way to acheive your goal - in underatanding this we might be able to propose suitable alternaitves - but regardless, this is not possible with a systemd template service.

Last edited by Trilby (2020-10-02 22:57:45)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#6 2020-10-03 15:24:44

kevdog
Member
Registered: 2013-01-26
Posts: 102

Re: Creating systemd service file with multiple variables

@Trilby

To give a better explanation of what I'm trying to do is to write a deploy-hook for acme.sh after Let's encrypt certs are renewed.  Since my certs in this case are mounted either using secrets or volumes into a docker container, what I want to do is restart the specific container to basically refresh the certificates used within the container after renewal.

I'm currently using docker-compose. 

For reference purposes I keep my docker-compose file in a directory structure like the following:
/etc/docker/compose/<docker-project-name> or <docker-network-name>/docker-compose.yml

The docker-compose.yml file may contain anywhere from 3-6 containers depending on the size of the project.  A very simple project for example would consist of the base-docker image with a mariadb container.  Sometimes I'll need openldap/phpldapadmin/portainer-agent/redis/watchtower depending on the scope of the project.

So the two variables I have in the case of renewing the certificates are -- directory location where docker-compose.yml is located (which represents arg1) and the specific container I need refreshed -- which is arg2.

Anyway I was hoping that systemd templates would be flexible enough to have the ability to parse arguments such as I originally posted, however I've since learned from you that systemd does not have this capability -- which seems to be a limitation IMO -- since why have the ability to create a template if only one variable can be included in the template -- just seems very rudimentary to me???  Yes I could use Environment Variable or Files however when using these methods, one of the variables would need to be "hard coded" into the file which limits some flexibility.

I suppose I could have the renewal hook actually just call a bash script with the variables and not involve systemd.  I'm wondering your opinion on the matter since I'm kind of new to the process. 

Thanks.

Offline

#7 2020-10-04 08:26:40

solskog
Member
Registered: 2020-09-05
Posts: 416

Re: Creating systemd service file with multiple variables

How about a simple wrapper script using bash parameter expansion? You are using one string with a delimiter to separate two arguments.

systemd[1]: wrapper@mylocation_myContainer.service
...
ExecStart=/usr/local/bin/wrapper.sh %i
...
$ cat /usr/local/bin/wrapper.sh
#!/bin/bash
/usr/bin/docker-compose -f /etc/docker/compose/"${1%%_*}"/docker-compose.yml up -d --force-recreate" "${1##*_}"

Last edited by solskog (2020-10-04 08:34:18)

Offline

#8 2020-10-04 12:19:35

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,525
Website

Re: Creating systemd service file with multiple variables

That is possible, but at that point, what's the point.  Apparently this is something that would be run manually every time it needs to run - so what is the systemd service doing in the first place other than making it clumsy?  Compare:

sudo systemd start wrapper@mylocation_myContainer.service
# vs
sudo wrapper mylocation myContainer

The service file is really just being used as a very clumsy alias to the script.  Note, too, that there is no delimiter that you could use in the instance variable that couldn't also exist in the location or container names.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#9 2020-10-05 03:56:08

solskog
Member
Registered: 2020-09-05
Posts: 416

Re: Creating systemd service file with multiple variables

Trilby wrote:

Apparently this is something that would be run manually every time it needs to run

I agree that OP wasn't stated which process automatically trigger acme.sh and docker-compose.

kevdog wrote:

what I want to do is restart the specific container to basically refresh the certificates used within the container after renewal.

Create each service for each specific container and renew the certification based on time unit.

1, Create a systemd.timer unit file
$ cat certrenew-container1.timer
[Timer]
# UTC time
OnCalendar=*-*-* 12:00:00
Persistent=true
[Install]
WantedBy=timers.target

2, Correspondent with a service file
$ cat certrenew-container1.service
[Unit]
Description=Certrenew Container1 Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/certrenew-container1.sh
...
3, Then use a conditional check inside certrenew-container1.sh 
to restart the specific container after successful certification renewal.

Last edited by solskog (2020-10-05 03:57:00)

Offline

#10 2020-10-05 14:22:51

kevdog
Member
Registered: 2013-01-26
Posts: 102

Re: Creating systemd service file with multiple variables

Hey @solskog and @Trilby -- thanks a lot for helping me with the issue.  I guess there are multiple ways to skin the cat.  You have given me a lot of ideas about how to implement what I want to do and some nice thoughts about bash scripting.  Thanks a lot.  I already have acme setup attempting to renew the certificates nightly and then it runs a hook instruction on successful renewal of the certificate.  I'll probably continue to use this method rather than reinvent the wheel.  I just throw together a hook script that will restart the specific container based on passed variables.  Thanks.

Offline

#11 2020-10-05 15:06:05

frostschutz
Member
Registered: 2013-11-15
Posts: 1,418

Re: Creating systemd service file with multiple variables

use @simple argument in the service name and hide the complexity elsewhere, seems to be the way to go

OpenVPN systemd service also needs multiple variables so it just uses openvpn-server@configuration.service, configuration being the base name of a config file which then includes all the variables and parameters involved...

for my personal use I just put a case statement in a shell script ...

Offline

#12 2020-10-06 02:30:25

fukawi2
Ex-Administratorino
From: .vic.au
Registered: 2007-09-28
Posts: 6,224
Website

Re: Creating systemd service file with multiple variables

Not exactly what you're asking for, but I'd do this with a .path unit that watches the certificate, which then starts a corresponding oneshot .service with multiple ExecStart lines

.path unit:

[Unit]
Description=Triggers restart of docker containers when Lets Encrypt certificate is updated

[Path]
PathChanged=/etc/letsencrypt/archive/foobar.example.com/

[Install]
WantedBy=multi-user.target
WantedBy=system-update.target

.service unit:

[Unit]
Description=Restart containers using foobar.example.com certificate

[Service]
Type=oneshot
ExecStart=docker restart foobar
ExecStart=docker restart barbaz
ExecStart=docker restart foobaz

Offline

#13 2020-10-09 02:22:15

kevdog
Member
Registered: 2013-01-26
Posts: 102

Re: Creating systemd service file with multiple variables

@fukawi2

Honestly I didn't even know about a path unit file.  Neat trick.

Offline

Board footer

Powered by FluxBB