Nowadays, creating a raw chroot is far from simple. Last time I tried, I had to handle the special mount points like /proc and /sys. I can't remember the details, but I believe there were other problems.
In my experience, systemd-nspawn provides a nice alternative. It's mainly a chroot that abstracts the low-level details, and it fixes some security concerns (with cgroups, etc) and adds some nice features: e.g. networking, or `systemctl status` from the host that will display the sub-tree for the processes of the sub-host.
Last time I tried to recover an ubuntu system by booting from a live sub, mounting the drive and chrooting into the target device i was surprised to find out that systemd refuses to work if it detects being run in a chroot.
If you're talking about what happens when you mount the root filesystem, chroot into it, and run systemctl then you're essentially asking to break out of the chroot and communicate to the service manager outside the chroot which almost always doesn't make sense.
The only time this is reasonable is when a container needs to manage services on the host a la what Portainer does for Docker.
You have a lot of options for accomplishing what you want.
* To run a service with a given root filesystem add RootFilesystem=/path to your unit file.
* Run a service from an image of a root filesystem use systemd portable services.
* To run your service using the init system in your root filesystem (could be systemd but doesn't have to be) use systemd-nspawn --boot.
Right, but what you're describing as running a pre-systemd "service" is really just "run a shell script that sources some environment files and then double forks".
Running a systemd service means talking to the /org/freedesktop/systemd1 object on the system bus typically listening on /run/dbus/system_bus_socket and asking it to start your service. This is all that systemctl really does.
mkdir ./rootfs
curl -O https://cloud-images.ubuntu.com/minimal/releases/bionic/release/ubuntu-18.04-minimal-cloudimg-amd64-root.tar.xz | tar -xJPC ./rootfs
mount -o bind /proc ./rootfs/proc
mount -o bind /sys ./rootfs/sys
mkdir ./rootfs/run/dbus
mkdir ./rootfs/run/systemd
mount -o bind /run/dbus ./rootfs/dbus
mount -o bind /run/systemd ./rootfs/systemd
chroot ./rootfs bash
# See that it works just by sending dbus messages.
dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager.ListUnits
# Now do the same with systemctl.
export SYSTEMD_IGNORE_CHROOT=true
systemctl list-units
THIS IS ALMOST CERTAINLY NOT WHAT YOU WANT. You're just talking to the host systemd. You won't see any of the services in your chroot since how could systemd know about them? Your chrooted root is also now just root on the host. Just use systemd-nspawn.
# undo all the bind mount junk.
chroot ./rootfs bash
useradd ubuntu -G sudo
passwd ubuntu
exit
cd ./rootfs
systemd-nspawn -x --private-network --boot
# login
sudo systemctl list-units
In my experience, systemd-nspawn provides a nice alternative. It's mainly a chroot that abstracts the low-level details, and it fixes some security concerns (with cgroups, etc) and adds some nice features: e.g. networking, or `systemctl status` from the host that will display the sub-tree for the processes of the sub-host.