[systemd-devel] How to factory reset?

Tobias Hunger tobias.hunger at gmail.com
Mon Mar 9 04:02:57 PDT 2015

Hi everybody,

I am running a kiosk-like box here and have a read-only copy of /etc
hidden away in /usr/ somewhere. /etc is a symlink to that directory
and that works fine.

Recently I thought I'd experiment with factory reset. My idea was to
use a tmpfs mounted on /etc instead of that symlink and populate that
from the directory in /usr on boots. That way I can still experiment
with changes to the configuration, but on all reboots I get the
trusted state back.

So how is factory reset supposed to work is systemd?

My first attempt was to add a etc.mount unit to mount a tmpfs over
/etc, modeled after the tmp.mount unit shipped with systemd and then
use a tmpfiles.d snippet to copy the actual configuration. This seems
pretty close to the ideas floating around in some blog posts on the
topic of factory reset.

Unfortunately this does not work: By the time /etc gets mounted
something already puts files into the empty /etc. The culprit seems to
be ldconfig.service. There are some more files that are in /etc
(localtime, machine-id and systemd directory), but I could not find
who creates those I think systemd-nspawn might be the one to blame for

There are some more services that get started and fail because their
configuration is not there yet. The systemd-firstboot.service also
kicks in (a really nice feature by the way!), but that of course
needed to be axed for my setup.

The next step was add a service that extracts a tarball with my
configuration, modeled on systemd-firstboot.service and depending on
etc.mount. That did not improve the situation by much: The files were
still created and quite a few processes still did try to start before
/etc with their configuration was set up.

Then I started adding After= and Before= statements to the offending
services (systemd-remount-fs.service, journald.service and a few
others that I can't remember right now). With this I get
ldconfig.service and journald up and running.

Unfortunately the dbus.service will not come up, claiming that there
is no /etc/dbus-1/system.conf. This file is in the tarball, and the
output during boot-up suggests that dbus.service is started only after
the /etc-tarball is extracted, so that file should be there. There
seems to be a dbus.socket involved in the start of dbus.service and
that is started before the tarball is extracted.

At this point I am stuck. Do I need to have dbus.socket wait for my
etc-extract.service? Or why would dbus not see the configuration file?

Am I on the right track with adding Before= and After= statements to
various services? Is there some convenient target that I should use
instead? Something that needs to be reached before systemd starts to
bring up services?

Should I take a different approach entirely and e.g. populate /etc in
the initrd? I'd like to keep the initrd generic if I can, so I am not
happy with that idea.

I am using systemd-nspawn for my experiments. This seems to add some
files to /etc, which is not ideal, but does not seem to hurt too much
either. Is there a better way to test setups like the one I intend to

Does systemd-nspawn indeed add/change files in /etc of the directory
it is running from?

Best Regards,

More information about the systemd-devel mailing list