Self-hosted server logging
The self-hosted server writes all logs to standard output - there are no
log files. In development that output is human-readable text; with
PRODUCTION=1 it switches to JSON, one object per line, ready for
CloudWatch, Azure Monitor, Elasticsearch or any log shipper that reads a
container's stdout.
Transaction entries
Logins and file operations are logged as transaction entries, marked
"transaction": true - that flag is how you separate user activity from
server operational logs in your pipeline.
A login followed by a download looks like:
{"transaction":true,"operation":"login","protocol":"sftp","session_id":"501bbb4c6a046417628b","source_ip":"203.0.113.7","bytes":0,"user.username":"root","user.uuid":"ixxvwd0z","user.home":"/","level":"info","time":"..."}
{"transaction":true,"operation":"get","protocol":"sftp","session_id":"501bbb4c6a046417628b","source_ip":"203.0.113.7","bytes":22,"src_path":"/testfile1","user.username":"root","user.uuid":"ixxvwd0z","user.home":"/","level":"info","time":"..."}
Fields worth building queries on:
| Field | Meaning |
|---|---|
operation | login, get, put, delete, ... |
protocol | sftp, ftp, ... |
session_id | groups all operations of one connection |
bytes | bytes transferred for the operation |
src_path | the file path operated on |
source_ip | the client's address |
user.username / user.uuid | who did it |
Startup logs
At startup the server logs its configuration (ports, TLS files, public IP),
its SSH host-key fingerprints, and - once the cloud link is up -
SFS configuration loaded successfully, which is the line that means the
server is ready to authenticate users.
Shipping the logs
- Docker: any log driver that captures stdout works
(
awslogs,fluentd,json-file+ an agent...) - systemd: journald captures stdout; forward from there
- The one rule: transfer history lives only in these logs - DocEvent's cloud has no copy - so ship them somewhere durable if you need an audit trail.