From a9ca90537b842b04e9651f2ecd1f0eae880eb2e4 Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sun, 10 May 2026 00:58:42 +0200 Subject: [PATCH] feat(deploy): left4me-cake.service oneshot wrapping apply-cake helper The CAKE egress shaper now has a systemd unit that wraps the left4me-apply-cake helper in apply and clear modes. The unit is a oneshot that starts after network-online and survives service restarts, allowing the shaper to persist across reboots and be managed by systemd. The environment file is marked non-fatal (EnvironmentFile=-) to handle missing or incomplete configurations gracefully. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../lib/systemd/system/left4me-cake.service | 14 +++++++++++++ deploy/tests/test_deploy_artifacts.py | 20 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 deploy/files/usr/local/lib/systemd/system/left4me-cake.service diff --git a/deploy/files/usr/local/lib/systemd/system/left4me-cake.service b/deploy/files/usr/local/lib/systemd/system/left4me-cake.service new file mode 100644 index 0000000..5dce525 --- /dev/null +++ b/deploy/files/usr/local/lib/systemd/system/left4me-cake.service @@ -0,0 +1,14 @@ +[Unit] +Description=left4me CAKE egress shaper +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes +EnvironmentFile=-/etc/left4me/cake.env +ExecStart=/usr/local/libexec/left4me/left4me-apply-cake apply +ExecStop=/usr/local/libexec/left4me/left4me-apply-cake clear + +[Install] +WantedBy=multi-user.target diff --git a/deploy/tests/test_deploy_artifacts.py b/deploy/tests/test_deploy_artifacts.py index a72e1dd..bdc1edb 100644 --- a/deploy/tests/test_deploy_artifacts.py +++ b/deploy/tests/test_deploy_artifacts.py @@ -15,6 +15,7 @@ SYSCTL_CONF = DEPLOY / "files/etc/sysctl.d/99-left4me.conf" GLOBAL_REFRESH_SERVICE = DEPLOY / "files/usr/local/lib/systemd/system/left4me-refresh-global-overlays.service" GLOBAL_REFRESH_TIMER = DEPLOY / "files/usr/local/lib/systemd/system/left4me-refresh-global-overlays.timer" NFT_MARK_UNIT = DEPLOY / "files/usr/local/lib/systemd/system/left4me-nft-mark.service" +CAKE_UNIT = DEPLOY / "files/usr/local/lib/systemd/system/left4me-cake.service" SANDBOX_UNIT_DIR = DEPLOY / "files/usr/local/lib/systemd/system" SYSTEMCTL_HELPER = DEPLOY / "files/usr/local/libexec/left4me/left4me-systemctl" JOURNALCTL_HELPER = DEPLOY / "files/usr/local/libexec/left4me/left4me-journalctl" @@ -803,3 +804,22 @@ def test_apply_cake_helper_supports_apply_and_clear_modes(): def test_apply_cake_helper_passes_shell_syntax_check(): subprocess.run(["sh", "-n", str(APPLY_CAKE_HELPER)], check=True) + + +def test_cake_unit_runs_helper_in_apply_and_clear_modes(): + assert CAKE_UNIT.is_file() + text = CAKE_UNIT.read_text() + + assert "After=network-online.target" in text + assert "Wants=network-online.target" in text + assert "Type=oneshot" in text + assert "RemainAfterExit=yes" in text + # `-` prefix: missing env file is non-fatal (deploy ships one, but be safe). + assert "EnvironmentFile=-/etc/left4me/cake.env" in text + assert ( + "ExecStart=/usr/local/libexec/left4me/left4me-apply-cake apply" in text + ) + assert ( + "ExecStop=/usr/local/libexec/left4me/left4me-apply-cake clear" in text + ) + assert "WantedBy=multi-user.target" in text