1

Using Debian 9 stable, I want to start a custom shell script before starting NGINX processes and shorewall firewall:

  • Do some init work
  • Mount a directory (overlayfs) to overlay /etc with NGINX configuration, shorewall configuration and /etc/hosts
  • The script also ends with sync, not sure if it's a good idea

systemctl list-dependencies
default.target
● ├─display-manager.service
● ├─systemd-update-utmp-runlevel.service
● └─multi-user.target
● ├─console-setup.service
● ├─cron.service
● ├─dbus.service
● ├─dropbear.service
● ├─myservice.service   <-- My service (link created with systemctl enable)
● ├─networking.service
● ├─nginx.service       <-- To be executed after myservice
[...]
● ├─basic.target
● │ ├─-.mount
● │ ├─myservice.service <-- My service (link created with systemctl enable)
● │ ├─shorewall.service  <-- To be executed after myservice

myservice.service ATTEMPT 1

[Unit]
Description=My startup service
Requires=shorewall.service nginx.service
Before=shorewall.service nginx.service

[Service]
RemainAfterExit=yes
ExecStart=/usr/local/bin/myservice start
ExecStop=/usr/local/bin/myservice stop

[Install]
WantedBy=multi-user.target
WantedBy=basic.target

The logs:

journalctl [...]
Oct 12 11:31:43 server-dev nginx[448]: nginx: [emerg] host not found in upstream "server-dev.com" in /etc/nginx/sites-enabled/default:33
Oct 12 11:31:43 server-dev nginx[448]: nginx: configuration file /etc/nginx/nginx.conf test failed <== NGINX: BAD
Oct 12 11:31:43 server-dev systemd[1]: nginx.service: Control process exited, code=exited status=1
Oct 12 11:31:43 server-dev systemd[1]: Failed to start A high performance web server and a reverse proxy server.
Oct 12 11:31:43 server-dev systemd[1]: nginx.service: Unit entered failed state.
Oct 12 11:31:43 server-dev systemd[1]: nginx.service: Failed with result 'exit-code'.
Oct 12 11:31:43 server-dev systemd[1]: Reached target Multi-User System.
Oct 12 11:31:43 server-dev systemd[1]: Reached target Graphical Interface.
Oct 12 11:31:43 server-dev systemd[1]: Starting Update UTMP about System Runlevel Changes...
Oct 12 11:31:43 server-dev systemd[1]: Started Update UTMP about System Runlevel Changes.
Oct 12 11:31:43 server-dev server[423]: DO: server start DONE <== END OF SCRIPT myservice
Oct 12 11:31:43 server-dev shorewall[449]: Compiling using Shorewall 5.0.15.6... <== SHOREWALL: GOOD
Oct 12 11:31:44 server-dev shorewall[449]: Processing /etc/shorewall/shorewall.conf...
Oct 12 11:31:44 server-dev shorewall[449]: Loading Modules...

Shorewall is systematically started correctly, after the execution of myservice. Nginx is most of the time started during the execution of myservice, before /etc is correctly overlayed (overlaid?), and therefore it fails to initialize properly.

myservice.service ATTEMPT 2

I also tried to change the

[Install]
WantedBy=default.target

And change

[Unit]
Before=multi-user.target

It also does not work.

How can I ensure that nginx and shorewall start after the execution of myservice?

2 Answers 2

6

If you don't specify the type of your systemd service, it defaults to Type=simple. This means the service is considered started at the moment its main service process has been forked off (at which point it isn't even executing the ExecStart command yet). You probably want to use Type=oneshot instead, which waits for the ExecStart command to exit before considering the service started. See man systemd.service for further details.

1

You could use the ExecStartPre= option in a drop-in snippet configuration to add the option to Nginx service unit instead of using separate ones (or add Requires=shorewall.service to the nginx service unit, though I advise against that).

Use the command sudo systemctl edit nginx.service (it creates directory in /etc/systemd/system/nginx.service.d with a drop-in snippet config).

Type:

[Unit]
Requires=shorewall.service
After=shorewall.service

Or:

[Service]
ExecStartPre=/usr/bin/your_script

This will always execute your script prior to starting nginx service unit. You should add (since it's a shell script and redirections are not supported by default) IgnoreSIGPIPE=no to the service section or Systemd will ignore redirections, pipes and signals otherwise.

For: Mount a directory (overlayfs) to overlay /etc with NGINX configuration, shorewall configuration and /etc/hosts.

Add to the service section:

TemporaryFileSystem=/etc:ro,nodev,noexec,nosuid

This mounts a blank tmpfs mount point on top of the /etc directory. You will need to bind mount (using BindReadOnlyPaths=, BindPaths=) all required files in /etc (2 dirs and 5 files).

To bind mount the hosts file:

BindReadOnlyPaths=/etc/hosts

(add openssl, ca-certificates and nameservices to ;))

No need for any scripts to set up the environment, containerization, namespaces, sandboxing, MAC/IPS is possible using systemd.exec.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .