journald vs JSONL file logging: choosing your audit sink
The audit log is only as good as the sink it lands in. You can emit the perfect event — timestamp, credential name, outcome, no token values — and still lose it to a file nobody rotates, a directory with world-readable permissions, or a journal that fills up silently. For agent credential events, the choice usually comes down to two sinks: a JSONL file on disk or the systemd journal. Both are legitimate; they are not interchangeable.
What a JSONL file gives you
A plain JSONL file is the lowest-friction audit sink that exists. Every line is one event, one JSON object. You can grep it, jq it, tail it, and feed it to a SIEM with a single file reader. It has no runtime dependencies, and it works identically on any distribution, container, or machine without systemd. Files also give you explicit control: set permissions to 0600, put it on a dedicated volume, and rotate it with logrotate. The one requirement is that the logger cooperate with rotation — reopening its file descriptor on SIGHUP — otherwise events vanish into the old inode mid-rotation.
What journald gives you
journald moves the plumbing into the system. The journal is structured from the start: fields are indexed, timestamps are precise, and access is governed by systemd’s own permission model rather than by whatever umask the shell happened to use. Rotation and size limits are configured once in journald.conf and enforced by the daemon — there is no cron job to forget. On a machine where systemd already manages services, the journal also gives you attribution: events from a service unit are tagged with the unit name, which helps when multiple agents run under the same user.
When the file wins
Choose a JSONL file when you need portability, simplicity, or direct tooling. If your audit pipeline is a script that tails files, if your agents run on macOS or in containers, or if you want the audit data physically separate from the system journal, a file is the honest choice. You trade system-managed rotation for a small amount of your own plumbing: a logrotate stanza and a reopen signal.
When journald wins
Choose journald when the machine already runs it and you want the journal’s guarantees without building your own. The journal is tamper-resistant against the unprivileged user writing to it, which matters when the thing being logged is credential access. If you need remote shipping, journald-upload handles forwarding; if you need querying, journalctl has field filtering built in. The cost is that you depend on systemd being present and healthy, and that the journal is a system-wide store — your events share retention settings with everything else unless you configure a separate namespace or size limit.
The one rule: pick one
Do not write the same events to both sinks. Two copies of the same log diverge — one gets rotated, the other does not; one is filtered, the other is not — and then you have two logs, neither of which is authoritative. Choose the sink that matches how you will actually read the events, and make every other consumer read from that sink.
trustless supports both sinks for its audit log: append-only JSONL at ~/.local/state/trustless/audit.jsonl with 0600 permissions and SIGHUP reopen for logrotate, or journald on systems that run it. Either way the events are the same — proxy.inject, proxy.deny, run.spawn, dlp.redact, oauth.refresh, oauth.fail, oauth.reauth_required — and token values never appear.
Which sink did you last configure on purpose — and when it rotates, will you notice if events stop appearing?