From 74508faf27e7d7e6138ee95981c22e18657d2229 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Sun, 14 Jan 2024 19:12:53 -0600 Subject: [PATCH] nut: Apply udev rules on the host NUT needs some udev rules in order to set the proper permissions on USB etc. devices so it can run as an otherwise unprivileged user. Since udev rules can only be processed on the host, these rules need to be copied out of the container and evaluated before the NUT server starts. To enable this, the *nut-server* container image copies the rules it contains to `/etc/udev/rules.d` if that directory is a mount point. By bind mounting a directory on the host at that path, we can get a copy of the rules files outside the container. Then, using a systemd path unit, we can tell the udev daemon to reload and reevaluate its rules. SELinux prevents processes in containers from writing to `/etc/udev/rules.d` directly, so we have to use an intermediate location and then copy the rules files to their final destination. --- host/nut0.pyrocufflink.blue.k | 3 ++- pkg/common/templates.k | 21 +++++++++++++++++++++ pkg/nut/templates.k | 2 +- templates/common/reload-udev-rules.path | 3 +++ templates/common/reload-udev-rules.service | 8 ++++++++ templates/nut/nut-server.container | 3 +++ 6 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 pkg/common/templates.k create mode 100644 templates/common/reload-udev-rules.path create mode 100644 templates/common/reload-udev-rules.service diff --git a/host/nut0.pyrocufflink.blue.k b/host/nut0.pyrocufflink.blue.k index 6ca473c..d7a1e74 100644 --- a/host/nut0.pyrocufflink.blue.k +++ b/host/nut0.pyrocufflink.blue.k @@ -1,4 +1,5 @@ import pkg import pkg.nut +import pkg.common -render: [pkg.RenderInstruction] = nut.templates +render: [pkg.RenderInstruction] = common.templates + nut.templates diff --git a/pkg/common/templates.k b/pkg/common/templates.k new file mode 100644 index 0000000..7f29f3d --- /dev/null +++ b/pkg/common/templates.k @@ -0,0 +1,21 @@ +templates = [ + { + template = "common/reload-udev-rules.path" + dest = "/etc/systemd/system/reload-udev-rules.path" + hooks = { + changed = [ + {run = "systemctl daemon-reload"} + {run = "systemctl try-restart reload-udev-rules.path"} + ] + } + } + { + template = "common/reload-udev-rules.service" + dest = "/etc/systemd/system/reload-udev-rules.service" + hooks = { + changed = [ + {run = "systemctl daemon-reload"} + ] + } + } +] diff --git a/pkg/nut/templates.k b/pkg/nut/templates.k index bef7a25..0c894f9 100644 --- a/pkg/nut/templates.k +++ b/pkg/nut/templates.k @@ -41,7 +41,7 @@ templates = [ dest = "/etc/containers/systemd/nut-server.container" hooks = { changed = [ - {run = "systemctl daemon-reload", immediate = True} + {run = "systemctl daemon-reload"} {run = "systemctl restart nut-server"} ] } diff --git a/templates/common/reload-udev-rules.path b/templates/common/reload-udev-rules.path new file mode 100644 index 0000000..1245417 --- /dev/null +++ b/templates/common/reload-udev-rules.path @@ -0,0 +1,3 @@ +[Path] +PathChanged=/run/containers/udev-rules +MakeDirectory=yes diff --git a/templates/common/reload-udev-rules.service b/templates/common/reload-udev-rules.service new file mode 100644 index 0000000..32f28b3 --- /dev/null +++ b/templates/common/reload-udev-rules.service @@ -0,0 +1,8 @@ +[Unit] +ConditionDirectoryNotEmpty=/run/containers/udev-rules + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'cp /run/containers/udev-rules/*.rules /run/udev/rules.d/' +ExecStart=/usr/bin/udevadm control --reload +ExecStart=/usr/bin/udevadm trigger diff --git a/templates/nut/nut-server.container b/templates/nut/nut-server.container index 949a81f..c872552 100644 --- a/templates/nut/nut-server.container +++ b/templates/nut/nut-server.container @@ -4,11 +4,14 @@ Description=Network UPS Tools - power devices information server Wants=network-online.target After=network-online.target Before=nut-monitor.service +Wants=reload-udev-rules.path +After=reload-udev-rules.path [Container] Image=git.pyrocufflink.net/containerimages/nut:latest Pull=newer RunInit=true +Volume=%t/containers/udev-rules:/etc/udev/rules.d:rw,z Volume=/etc/ups:/etc/ups:ro Volume=/dev:/dev:rw ReadOnly=true