Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Audit: reading the trail

The audit trail says who did what, on which file, and whether it worked; refusals and errors included. The vocabulary of the lines (actions, fields, reason) is in the reference.

{"timestamp":"2026-10-07T14:41:25.402Z","level":"INFO","target":"audit","fields":{"message":"audit: operation succeeded","source":"sftp","action":"upload","session_id":"550e8400-e29b-41d4-a716-446655440000","remote_addr":"192.168.1.42","username":"alice","path":"/in/rapport.csv","backend":"disque","new_path":"","count":524288,"replaced":"no","removed":"","result":"success"}}

Where it goes

SettingWhere the trail goes
defaultstdout, mixed with the application log, one JSON line per event, target = audit
[log] dirin addition, craft-file-gate-audit.log (the trail alone) next to craft-file-gate.log
[log] stdout = falsethe files only
[telemetry]each operation line is also an event of the operation’s span

Rotation, retention and level: Logs.

What it keeps

log.audit (all, changes, failures) only removes successes; repeated anonymous refusals are summarized as connection_rejected_summary. See The volume of the trail and Repeated refusals.

Severity

LevelLines
WARNwhat only a credential holder produces: a denied, error or unknown operation; a refusal after an accepted credential; a refused admin action; ip_banned
INFOwhat any peer produces: the other connection_rejected; connection_accepted, session_end, the summaries, the successes

An alert on the trail’s WARN lines therefore does not fire for an anonymous scanner.

Filtering

In the console, Logs tab, source audit (permission audit): filters by level, period, text and field:value; each read writes an audit_read line. See Admin API and console.

# the admin console API
curl -H "Authorization: Bearer $TOKEN" \
  'http://serveur:8081/admin/logs/audit?field=username:alice&level=WARN&since=2026-10-07T00:00:00Z'

# the files; without [log] dir: docker logs ... | jq -c 'select(.target == "audit")'
jq -c 'select(.fields.username == "alice")' /var/log/craft-file-gate/craft-file-gate-audit.log
QuestionFilter
everything an SFTP session did.fields.session_id == "<id>"
overwritten files.fields.action == "upload" and .fields.replaced == "yes"
ACL refusals.fields.reason == "acl"
storage failures.fields.result == "error" and .fields.backend == "<name>"
refusals and errors.fields.result != "success"

The text of a storage error is not in the trail: look for it in the application log, at the same time, with the same path.

An incomplete trail

A line the server cannot write (closed pipe, full disk) is lost: craftfilegate_log_write_errors_total counts it, stderr says so at most once per minute, and the server keeps serving. Alert on increase(craftfilegate_log_write_errors_total[5m]) > 0.