61

With init scripts (or with openrc) I alway could run services from a different installation root.
but when I run chroot /somepath/to_root /usr/bin/systemctl start someservice I got:

Running in chroot, ignoring request.

Is there a way to force systemd run the service?

Update:
I forgot to say my host system run init scripts or openrc, but never systemd, and that I use chroot to troubleshot Unix systems which can't even launch a minimal shell.

user2284570
  • 2,020

9 Answers9

45

A well-known problem in systemd distros (Arch Linux, OpenSUSE, Fedora).

Systemd replaces sysvinit, and provides one great advantage over this. In sysvinit, when you ask a service to start, it inherits the execution context of the person invoking the script, which includes environment variables, ulimits, and so on. Systemd improves on this at the contrary by notifying a daemon, which will start the service in a well-defined, healthy, constant environment, where of course the performances of the services are much easier to predict, since the environment is always the same.

This implies that, when I call systemctl from within the chroot, it is irrelevant that I am inside chroot, the environment that will be inherited is still that of PID 1, not my current one. But it gets worse than this: since communication sockets are placed inside /run/systemd, a process in a chroot will not even be able to talk to the init system!

So how do you go about chroot'ing in systemd distros?

  1. If all you want to do is have a Linux container, this Arch Wiki page will tell you how to set up a Linux container in less than 30 seconds, thanks to systemd-nspawn.

  2. If instead you really want a chroot environment, this beautiful and crystal clear Web page will provide you with two working solutions (the second one is a modified version of the one offered at point #1).

Evan Carroll
  • 9,518
MariusMatutiae
  • 48,517
  • 12
  • 86
  • 136
16

Several years later I must admit there is only one solution to most Systemd practical problems. Because the error is Systemd itself

I am really fed up with Systemd as I had problems that I never faced with things like Upstart or Openrc :

  • The enforcing of a kernel requiring cgroups support (instead of being made optional but enabled by default inside a config file) even for embedded systems with only 24Mb of ram and no writable storage.
    While proponents argue that not being able to use it in such case is the wanted behavior since it wasn’t designed for such case, the reality is the other init systems also don’t care while in systemd such feature isn’t a separate project which highlights once again the consequences of not following kiss.
  • Despite the claim of being modular, at runtime the dependency hell makes it a strong god object : want to boot over a single reiser4 rootfs ? It’s not possible because many programs requires systemd-udevd which requires systemd-init which requires the systemd-boot package which can’t be installed at the same time than grub2 nor can read kernel images from a reiser4 partition.
  • Want to connect to the internet through Bluetooth dialup ? If it doesn’t work with your Samsung java me phone, then you aren’t able to run the scripts and command line software that previously worked manually because of networkd.
  • Though I recognize the biggest problem is if you are building and maintaining your own Linux distribution : the systemd init module itself has so many dependencies that you can’t propose to choose another init system through different install packages.
  • The default use of Google dns for systemd if no resolver is defined in terms of privacy and censorship through the example to prevent Tornado Cash domains to resolve.
  • The inability to launch a background non service process and log out as there are no simple ways to do it in a new systemd scope.
  • Good luck for viewing logs if you can’t chroot in your system or if you upgraded from libdb4.8 (whereas at least, in worst case Microsoft has it’s log files in xml format).

The only solution :

Systemd is unnecessary complex for solving problems : like alsa instead of ossv4. So if you have something that uses systemd just wipe all the data :

dd if=/dev/urandom of=/dev/dm−0 bs=1M count=1

and install something that doesn’t use it at all while solving problems of SysV Init like Gentoo with Openrc.
Concerning my question systemd makes things like the Windows® registry : if a part of it gets screwed up, then it’s over.

user2284570
  • 2,020
11

systemd only ignores "services", so I just run the daemon commands manually.

So instead of

service sshd start

I use

/usr/sbin/sshd -D &
DavidPostill
  • 162,382
johnP
  • 171
3

No. Services are executed by systemd (pid 1), not by systemctl directly (which only sends a start request), and since systemd runs outside the chroot, so will the service.

Although technically it could be possible to implement this (by making systemctl somehow pass its root to systemd), it is somewhat unlikely to happen since there already is a tool for creating full containers (systemd-nspawn /somepath/to_root). You could always contact the mailing list though.

grawity
  • 501,077
2

Faced this problem once tried to bring up network in rescue mode using network configuration from chroot. Finally this works for me:

service --skip-redirect <service> restart

or:

SYSTEMCTL_SKIP_REDIRECT=_ /etc/init.d/<service> restart
reddot
  • 398
2

Define a service file outside chroot that execute the service inside the chroot with the options RootDirectory=/path/to/chroot in conjunction with MountAPIVFS=on, the link above contains the magic.

Run systemd script in chroot from outside the chroot

0

Systemd will simply not run unless it has access to cgroups, udev and a bunch of others. It will not run in a chroot or in a docker container (unless the container is give unlimited privileges).

It will run in podman, which is not a surprise seeing as the same company stands behind that and systemd. The fact systemd tries to do everything is also concerning to linux altogether. It is an init system, but wait, it also uses journald and is now a logging system. And that listens on /dev/log, so you cannot use rsyslog with local sockets. Oh, and now it's a timesyncd daemon as well, and so forth.

So anyways, I am also fed up with docker saying "that is not the docker way, one container, one service, one entrypoint". But hold on, with chroot environments, and then with LXC containers, we were able to run an init system and use containers like mini-servers if we wished so, since forever. Systemd simply doesn't let you, unless you give it a lot of permissions on docker or use podman. And docker is adamant you should not be running a multi-service init system inside containers, even though they are full linux containers.

So, anyways, this is not just a rant. I have a solution - I did a thing!

https://github.com/rglonek/docker-systemd/blob/main/QUICKSTART.md

It's a golang-written application, which allows you to put in a single binary in your docker container and run it. It loads itself and acts as systemd/journald and provides systemctl/journalctl commands. Essentially I have rewritten the important parts of systemd/journald in go :D Yes, this is a beta, yes the code is a proof-of-concept. And yes, I've been using it since I built it and it works, at least for me, without issues.

It supports most standard systemctl commands (start/stop/restart/status/etc) though output looks more basic, most standard journalctl parameters and handles the loading of services at system startup (looks up the multi-user.target). It understands and speaks systemd system files, so you can install say apache2, and do systemctl start apache2; journalctl -u apache2 -f and systemctl enable apache2 to make it start at system boot.

I needed it cause some stuff I am installing is badly packaged and tries to run systemctl commands on install (and fails) in docker. And I like running say a process and it's little other process-helper thing in the same container. It's linux, I should be allowed to if I choose so.

-2

If you are launching an inetd-style service with socket activation, consider launching stunnel instead with a configuration file that specifies both a chroot and your binary as an inetd-style launch target.

Note that you may have SELINUX issues. On an Oracle Linux 7.1 system, I had to "chcon -v --type=stunnel_etc_t" on all files that stunnel needed to read.

You will need to use TLS encryption on the client side of the socket (i.e., another stunnel with "client=yes" in the config). Let me know if you want more details on this.

chas
  • 1
-3

You can use nohup command to start services in chroot. To start httpdservice for example, I do it like this.

nohup httpd /dev/null &

to stop it pkill httpd