← All posts

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:

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:

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

  1. 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.
  2. Use a client that records what you do across servers, and export that record before it matters.
  3. Make destructive operations deliberate. A sync that never deletes by default keeps the most damaging entries out of the log in the first place.
  4. 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.