Three issues caught once `bw test ovh.left4me` ran with the bundle
actually attached (vs. the earlier `bw test` with no node opting in,
which only checks parsing):
1. systemd_services + nftables_output reactors didn't read any metadata.
bw rejects this with "did not request any metadata, you might want
to use defaults instead". Both contributions are static, so they
belong in `defaults` — moved.
2. git_deploy:/opt/left4me/src triggered action:left4me_create_venv,
but create_venv lacked `triggered: True`. bw enforces that any
action in a triggers list must be `triggered: True`. Removed
create_venv from the trigger list — it's gated by `unless` for
idempotency and doesn't need to refire on git updates anyway
(the venv persists). pip_install stays in triggers so editable
installs pick up new code.
Replaces the per-app inet left4me_mark table from
deploy/files/usr/local/lib/left4me/nft/left4me-mark.nft with two rules
in the central bundles/nftables/ inet filter table's output chain.
Same selectors (skuid left4me + l4proto udp), same actions (DSCP EF +
priority 6) for both v4 and v6.
The server@ template intentionally has no svc_systemd entry — instances
are started on-demand by the web app through the left4me-systemctl
helper. Slices are activated implicitly when units use Slice=.
Sets in libs/systemd.py:18 are sorted alphabetically. The current
output is correct by accident — host.env < web.env, host.env < /var.
Adding a third path later would silently reorder. Tuples preserve
insertion order; generate_unitfile() iterates them the same way.
Environment (HOME=, PATH=) stays a set: each line is an independent
KEY=VALUE assignment, order is irrelevant.
Translates the remaining three unit files from left4me/deploy/files/.
Server template carries the full hardening + cgroup/IO/Mem keys
verbatim. Slices need the bundles/systemd .slice support added in
prior commit.
Translates left4me/deploy/files/usr/local/lib/systemd/system/left4me-web.service
into a Python dict consumed by bundles/systemd/. Two changes vs. the
shell-deploy unit:
- --bind 0.0.0.0:8000 -> 127.0.0.1:8000 (nginx terminates TLS in front)
- workers/threads are templated from left4me/gunicorn_{workers,threads}
(defaults: 1 worker + 32 threads — same as the static unit)
Mirrors deploy-test-server.sh:233-242 + :329-333. Single pip command
installs both editable packages (l4d2host + l4d2web) from the same
checkout. Alembic and seed-overlays run as the left4me user with
JOB_WORKER_ENABLED=false sourced from web.env.