A file transfer audit log: knowing what went to production
A file transfer audit log answers the question that comes up after every surprising change in production: what was uploaded, to which server, and when. You can record that on the server, in the client you transfer with, or both. Server-side logs are the authoritative record of what the server saw; a client-side log records what you did, across every server, in one place. This post covers what an audit trail should capture, how to switch on logging for SFTP, FTP and S3, and how to keep a useful record on your own Mac.
What a file transfer audit trail should answer
Most questions about a change come down to a few facts:
- What: the exact path of each file uploaded, downloaded or deleted.
- When: a timestamp precise enough to line up with error logs, ideally in UTC.
- Where: which server or bucket, since the same path often exists on staging and production.
- How much: the size transferred, which shows a truncated or empty upload at a glance.
- What failed: a failed transfer can leave a server in a half-changed state, so failures belong in the log too.
- Who: the account that did it.
Deletions deserve particular care. An upload can usually be undone by uploading the previous version. A deletion on a server with no backups can't, so a log that records transfers but not deletions misses the events that matter most.
Server-side logging
The server's own logs are the record to trust in a dispute, because they don't depend on any one person's laptop.
OpenSSH SFTP
By default, OpenSSH logs logins but not individual file operations. The SFTP server can log every open, close, rename and remove if you raise its log level. In /etc/ssh/sshd_config:
Subsystem sftp internal-sftp -l INFO
Restart sshd after testing the file with sudo sshd -t. Entries go to the system log (on most Linux systems, the auth log or the journal), with the user and the paths involved. If you run chrooted SFTP users with a Match block, add -l INFO to its ForceCommand internal-sftp line too, and note that a chrooted process needs a log socket inside the chroot for messages to reach the system log. The sftp-server manual page lists the log levels.
FTP servers
Most FTP servers write a transfer log in the traditional xferlog format, with one line per file. In vsftpd, it's controlled by xferlog_enable=YES. Check your server's documentation for where it writes and how it rotates.
Amazon S3
S3 offers two mechanisms. Server access logging writes a record of each request to another bucket. CloudTrail data events record object-level API calls such as PutObject and DeleteObject, with the identity that made them. Both are described in the S3 documentation, starting from the server access logging guide. Neither is on by default, and both cost something to store, so decide which buckets need them.
Why a client-side log still helps
Server logs answer "what happened on this server". They're less good at "what did I do this afternoon", because that might span three servers and a bucket, each with a different log format, and some of which you can't read. A client-side log is a single, readable timeline of your own actions, which is often what a change review, a client or an incident write-up actually needs.
The trade-off is that it lives on your machine. It records what that copy of the app did, not what other people or scripts did, and anyone with access to your user account could alter it. Treat it as a strong working record that complements server logs, not a replacement for them.
Wharf's activity log
Wharf keeps an activity log of what it does on your servers. Open it with View › Activity Log… (⌘⇧L). Each entry has a time, an action, the site, the path or a summary, and the size where it applies. The actions it records are:
- Connected, with the user, host and port.
- Uploaded and Downloaded, with the path and bytes moved. This includes transfers you start, transfers that a sync queues, every save uploaded while editing a file in place, and uploads and downloads made by Wharf's Shortcuts actions.
- Deleted on server and Deleted locally, for deletions carried out by sync when you've opted in to them.
- Sync finished, with counts of files up, down, deleted and in conflict.
- Continuous sync on and Continuous sync off. The "on" entry names the folder pair and notes when deletions are set to propagate.
- Conflict skipped, when continuous sync left a file alone because neither copy was clearly newer.
- Failed, with the error message.
Renames, permission changes and files you delete by hand from the remote pane aren't entries, so server-side logging is still the place to catch those.
Finding what you need
The window has three filters. A site picker narrows the list to one server. The Changes only toggle hides connections and sync bookkeeping, leaving just uploads, downloads and deletions, which is usually the view an auditor wants. A search field matches paths, site names and actions. Deletions are tinted so they stand out in a long list, and failures show in red.
Exporting to CSV
Export CSV… writes the log to a file you choose, named with the date by default. The columns are:
Date,Action,Site,Detail,Bytes,Error
Dates are ISO 8601 in UTC, so they sort correctly and line up with server logs. An illustrative row looks like this:
2026-10-21T14:03:12Z,Uploaded,Production web,/var/www/example.com/index.html,18342,
From there, ordinary tools answer most questions. For example, everything changed on production on one day:
grep '^2026-10-21' wharf-activity-2026-11-04.csv | grep ',Production web,'
Or open the file in a spreadsheet and filter by the Action column.
How it's stored
The log is kept on your Mac, appended one entry per line so a crash mid-write loses at most the last entry rather than the whole file. It holds the most recent 20,000 events, which covers a long stretch of normal use, but a heavy sync schedule can turn that over faster. If you need a longer record, export to CSV on a regular schedule and keep the files somewhere backed up. Like the rest of Wharf, the log never leaves your Mac unless you export it; see the privacy section.
Putting it together
- Turn on server-side logging where you can:
internal-sftp -l INFO, your FTP server's transfer log, S3 access logs or CloudTrail data events for important buckets. - Use a client that records what you do across servers, and export that record before it matters.
- Make destructive operations deliberate. A sync that never deletes by default keeps the most damaging entries out of the log in the first place.
- When something changes unexpectedly, start from the timestamp in the error logs and work backwards through both records.
More on Wharf's sync and logging is on the sync section of the homepage, and the support page covers the separate server log for diagnosing FTP problems.