RPi4 - best practices for custom application init (systemd)

# Overview

I am fairly new to Mender and went through the tutorial for RPi4 here over the past couple days, using the provided RPi Mender image:

My install is working and seems capable of updating the rootFS . I also installed the mender-demo-artifact.

I’m now trying to understand the “recommended” way to manage custom systemd services relative to the persistent data partition.

mender-demo-artifact installs its systemd .service in the rootFS. Unless I’m mistaken, this seems like a fresh rootFS update can accidentally disable the service… Care must be taken to ensure new rootFS images have the desired systemd script(s) for all enabled services.

This feels a little strange to me since I’m used to being able to update applications (including enabling them in systemd) without an entire rootFS update…but maybe this is just how it is done with Mender: adding a new systemd service? → new rootFS.

# Question

Does anyone have lighter-weight solutions for managing custom systemd services vs putting them in the rootFS? Like a nifty symlink or overlay strategy?

# What I Tried #1

I tried creating a symlink from /etc/systemd/system/my.service to a custom service file at /data/my.service. My idea was that an “empty” symlink could exist in the rootFS, with the target populated some later time by a small application package.

However it seems systemd loads services before /data is mounted…thus my custom service never runs automatically at startup. systemctl status my.service returns “Unit my.service could not be found.” Manually typing sudo systemctl daemon-reload and sudo systemctl start my.service works fine…but I would want a way to make that happen automatically for an unmonitored system and have yet to figure that out.

# What I Tried #2

I briefly enabled overlayfs via raspi-config, but am admittedly not too familiar with it. It gave a warning about “Couldn’t identify type of filesystem” so I am not really sure if it is compatible with the Mender RPi image. I also see unknown kernel command line parameter "overlayroot=tmpfs" in dmesg, which seems not good.

Hi @ttnick,

Interesting question. The only thing which immediately crosses my mind is having a kind of dispatcher service.

  1. keep the empty symlink(s)
  2. have a unit which is After=data.mount and which essentially does systemctl daemon-reload, start.

Slightly hacky for sure, but has an extremely small footprint and no impact on the larger image structure, such as an overlays would have.

Greetz,
Josef

Thanks Josef. Seems like I didn’t try hard enough with my symlink strategy (attempt #1)…

I was able to get that working today so appears a workable approach, although slightly hacky.

A reload service as follows:

[Unit]
Description=A reload service
After=data.mount

[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/bin/systemctl daemon-reload
ExecStartPost=/usr/bin/systemctl start my.service

[Install]
WantedBy=multi-user.target

And a symlink at /etc/systemd/system/my.service to a custom service at /data/my.service as follows:

[Unit]
Description=A custom service
StartLimitIntervalSec=0
After=data.mount

[Service]
Type=simple
Restart=always
RestartSec=5
User=developer
ExecStart=/usr/bin/echo hello

[Install]
WantedBy=multi-user.target

This way a smaller artifact is able to populate, remove, or update the file at /data/my.service to change behavior outside of a rootFS update…which was my goal.

Appreciate the feedback!

1 Like