diff --git a/nspawn-container/examples/multicast-relay/README.md b/nspawn-container/examples/multicast-relay/README.md new file mode 100644 index 0000000..73016b8 --- /dev/null +++ b/nspawn-container/examples/multicast-relay/README.md @@ -0,0 +1,149 @@ +## Create the filesystem overlay + +If you're going to create several nspawn containers, you can save some disk +space by using overlayfs to use a common base. Follow the instructions in the +unifi-utilities [documentation](https://github.com/unifi-utilities/unifios-utilities/blob/main/nspawn-container/README.md) +for UnifiOS 3.0+ containers. I called my container `debian-base`. + +Next, we need an `upperdir` where the file changes are saved and a `workdir` +where temporary file changes are saved. I'm going to create a container for +multicast-relay, replacing the [podman container](https://github.com/scyto/multicast-relay) +that I used prior to 3.x. An important note is that upperdir and workdir +must not be on the overlayfs that UnifiOS uses. I opted to store this data +on the hard drive that I use for video storage at `/volume1`. + +So, we have the following directories, which you need to create: + +- `/var/lib/machines/multicast-relay`: This will be the root directory of + our new container. +- `/volume1/machines/multicast-relay/upper`: This stores the differences from + the base container. +- `/volume1/machines/multicast-relay/work`: This is a temporary directory for + changes before they're saved to `upper`. This could possibly be on a `tmpfs` + mount, but I didn't want to mess with available memory. +- `/data/custom/machines/debian-base`: This is the base container directory + created by following the README linked above. + +Do it: +```shell +mkdir -p /var/lib/machines/multicast-relay /volume1/machines/multicast-relay/{upper,work} +``` + +Now add the matching entry to your fstab. I'm not 100% sure how permanent this is, +but I'll find out when I either reboot or do a firmware upgrade. + +Append this to `/etc/fstab` +``` +overlay /var/lib/machines/multicast-relay overlay noauto,x-systemd.automount,lowerdir=/data/custom/machines/debian-base,upperdir=/volume1/machines/multicast-relay/upper,workdir=/volume1/machines/multicast-relay/work 0 0 +``` + +If everything is good, you can `mount /var/lib/machines/multicast-relay`. If +there's any error from that, you have some homework to do. This _should_ automount +on reboot, but I haven't tested by rebooting my UDM Pro yet. We'll see 🤞. + +## Configure the container + +With your overlay in place, you can start the container and install your stuff. +``` +systemd-nspawn -M multicast-relay -D /var/lib/machines/multicast-relay +``` + +You should now be at a root shell inside the container. I configured this all +manually, but you can use the [script](./configure-container.sh) I created during +my trial and error to save yourself some time. Minimal Debian doesn't have +`curl` or `wget`, so you can install one of those and download the script, +or copy-paste into `vi` or something. This is left as an exercise to the reader. + +To escape this container, you'll have to press the cheat code given at the start +of your session. (HINT: Press Ctrl + ] 3 times.) + +NOTE: I didn't set the root password, which you will see in many tutorials. It +isn't needed. The host can bypass any login prompt using `machinectl shell `. +You might want to set a root password and/or other user if you are using the +container as a lightweight VM. + +## Run the container + +If this is your first systemd-nspawn service, you'll need to create the config +directory. + +``` +mkdir -p /etc/systemd/nspawn +``` + +Now create the container launch configuration in the file indicated. `multicast-relay` +requires the ability to open raw sockets, so we grant that capability and strip the rest. Be sure you specify the interfaces you wish to use in the `Environment=` line. +Optionally, you can specify additional `multicast-relay` options in `OPTS` + +``` +# /etc/systemd/nspawn/multicast-relay.nspawn +[Exec] +Boot=on +Capability=CAP_NET_RAW +Environment=INTERFACES="br0 br50" +Environment=OPTS= + +[Network] +Private=off +VirtualEthernet=off +ResolvConf=off +``` + +Once that file is in place, you're ready to enable the container on boot and run it. + +``` +machinectl enable multicast-relay +machinectl start multicast-relay +``` + +## Troubleshooting + +You can view the stdout of the container in the host journal. + +``` +journalctl -xe +``` + +Output from multicast-relay itself won't be found here though. You _should_ be +able to view a containers journal from the host, but I got an error when I tried +suggesting the Debian container has a newer journal format than the UnifiOS host. + +No matter, you can just enter the container and get a root shell (no login required). + +``` +machinectl shell multicast-relay +``` + +Now, we're setting the interface and options via environment variables set on the +host. If you want to double check that's working correctly, check the environment +of systemd from within the container. + +``` +cat /proc/1/environ | tr '\0' '\n' +``` +output: +``` +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +container=systemd-nspawn +HOME=/root +USER=root +LOGNAME=root +container_uuid=c05b41ce-0995-412d-bd2d-338759b24e54 +NOTIFY_SOCKET=/run/host/notify +container_host_version_id=11 +container_host_id=debian +INTERFACES=br0 br50 +``` + +You could use the same command to view the environment of our service. In this case, +we can use the PID of `dash`, the shell script interpreter from `start.sh`. + +``` +root@DreamMachinePro:~# cat /proc/$(pidof dash)/environ | tr '\0' '\n' +LANG=C.UTF-8 +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +INVOCATION_ID=d1cfaf43a00b4e79bcddca6a1595837c +JOURNAL_STREAM=8:51317778 +SYSTEMD_EXEC_PID=47 +INTERFACES=br0 br50 +``` \ No newline at end of file diff --git a/nspawn-container/examples/multicast-relay/configure-container.sh b/nspawn-container/examples/multicast-relay/configure-container.sh new file mode 100644 index 0000000..041d01b --- /dev/null +++ b/nspawn-container/examples/multicast-relay/configure-container.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -eux -o pipefail + +# Install dependencies +apt install -y --no-install-recommends python3 python3-netifaces git ca-certificates + +# Checkout latest commit of default branch of multicast-relay +cd /opt +git clone --depth=1 https://github.com/alsmith/multicast-relay.git + +# Drop a startup script +cat <<'EOF' | tee /opt/multicast-relay/start.sh +#!/bin/dash +# This script adapted from scyto +# https://github.com/scyto/multicast-relay/blob/master/start.sh +SCRIPT_DIR=$(dirname $(readlink -f $0)) + +echo "starting multicast-relay" +echo "Using Interfaces: ${INTERFACES}" +echo "Using Options --foreground " $OPTS +python3 "${SCRIPT_DIR}/multicast-relay.py" --interfaces ${INTERFACES} --foreground $OPTS +EOF + +chmod +x /opt/multicast-relay/start.sh + +# Install and enable a systemd service +cat <<'EOF' | tee /etc/systemd/system/multicast-relay.service +[Unit] +Description=multicast relay service + +[Service] +PassEnvironment=INTERFACES OPTS +ExecStart=/opt/multicast-relay/start.sh + +[Install] +WantedBy=multi-user.target +EOF + +systemctl enable multicast-relay.service \ No newline at end of file