packaging/systemd: ship daedalus-v4l2.service + modules-load drop-in

Canonical location for the systemd unit + module-autoload conf,
referenced by both arch/daedalus-v4l2 and debian/daedalus-v4l2
in marfrit-packages.  Was a real gap in the original packaging:
postinst installed the daemon binary but nothing started it, so
the libva path got REQ_DECODE messages with nobody listening on
/dev/daedalus-v4l2 and timed out.

packaging/systemd/daedalus-v4l2.service:
  - Type=simple, ExecStart=/usr/bin/daedalus_v4l2_daemon daemon
  - After=systemd-modules-load.service + ConditionPathExists=
    /dev/daedalus-v4l2 (so it only starts when the kernel module
    is loaded; doesn't false-fire on non-daedalus hosts that
    happen to have the package installed)
  - Restart=on-failure, RestartSec=2
  - MemoryHigh=128M / MemoryMax=256M (Phase 8.9 stress run
    showed RSS settling around 25 MiB; leaves headroom)
  - Hardening: NoNewPrivileges, ProtectSystem=strict, ProtectHome,
    PrivateTmp, ProtectKernel*, SystemCallFilter=@system-service.
    PrivateDevices=false because we DO need /dev/daedalus-v4l2

packaging/systemd/daedalus-v4l2.modules-load:
  - Drops to /etc/modules-load.d/daedalus-v4l2.conf so the kernel
    module loads before the .service unit fires.

Both files are picked up by the package recipes (next bump in
marfrit-packages) — neither lives in /usr/lib/systemd/system or
/etc/modules-load.d until the .deb / .pkg installs them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 10:26:58 +02:00
parent f0cd29a340
commit 481279c9bf
2 changed files with 72 additions and 0 deletions
@@ -0,0 +1,6 @@
# /etc/modules-load.d/daedalus-v4l2.conf
#
# Load the daedalus_v4l2 kernel module at boot so /dev/daedalus-v4l2
# + /dev/videoNN (V4L2 m2m decoder) + /dev/mediaNN (request API)
# come up before the daedalus-v4l2.service unit fires.
daedalus_v4l2
+66
View File
@@ -0,0 +1,66 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# daedalus-v4l2 userspace decoder daemon.
#
# Pairs with the daedalus_v4l2 kernel module (DKMS-built into
# /lib/modules/.../updates/dkms/daedalus_v4l2.ko). When the
# module loads it creates /dev/daedalus-v4l2 (chardev bridge).
# This unit starts the userspace daemon that holds the chardev
# open and answers REQ_DECODE requests with FFmpeg-software
# decode + dmabuf-back.
#
# Without the daemon running, libva / V4L2 clients can S_FMT /
# REQBUFS / QBUF against /dev/videoNN but the decode never
# returns (device_run sends REQ_DECODE into the chardev and
# nothing answers). Always-on is the right disposition.
[Unit]
Description=daedalus-v4l2 userspace decoder daemon
Documentation=https://git.reauktion.de/reauktion/daedalus-v4l2
# Wait until /dev/daedalus-v4l2 actually exists. systemd
# auto-derives the device unit name from the path. The kernel
# module is loaded via /etc/modules-load.d/daedalus-v4l2.conf
# (see daedalus-v4l2.modules-load) earlier in the boot sequence.
After=systemd-modules-load.service
Wants=systemd-modules-load.service
ConditionPathExists=/dev/daedalus-v4l2
[Service]
Type=simple
ExecStart=/usr/bin/daedalus_v4l2_daemon daemon
# Daemon needs read+write on the chardev (created mode 0660 by
# the kernel module, owner root:video). Run as root for simplicity;
# can be relaxed to a daedalus system user with `video` supplementary
# group when we add the user.
User=root
# Recover from crashes. RestartSec=2 picks a small but non-zero
# backoff so a tight crash-loop doesn't burn CPU.
Restart=on-failure
RestartSec=2
# Resource hygiene. Daemon's RSS settles around 25 MiB (per
# Phase 8.9 stress test); the cap is well above that to leave
# headroom for FFmpeg internal state on large frames.
MemoryHigh=128M
MemoryMax=256M
# Hardening — keep what the daemon doesn't need locked down.
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=false # we need /dev/daedalus-v4l2
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
RestrictRealtime=true
LockPersonality=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target