Updated: 12 October 2026 · Applies to: OpenSSH 10.2p1 with rsyslog 8.2512 on Ubuntu 26.04 (tested), OpenSSH 9.9p1 with rsyslog 8.2510 on AlmaLinux 10.2 (configuration tested); the same steps apply to Rocky Linux and RHEL 9 and 10, Ubuntu 24.04 and Debian 13

There is no separate SFTP log file by default. SFTP logins are logged together with SSH logins: in /var/log/auth.log on Ubuntu, in /var/log/secure on AlmaLinux, Rocky Linux and RHEL, and in the systemd journal everywhere (journalctl -u ssh, or -u sshd on the RHEL family). The files that users upload, download, rename or delete are not logged at all until you add -l INFO to the SFTP subsystem. The steps below turn that on and write the transfers to their own file, /var/log/sftp.log.

Where SFTP logins are logged by default

  • Ubuntu: /var/log/auth.log. rsyslog is part of a normal install (the ubuntu-minimal package recommends it on 24.04 and 26.04).
  • Debian 12 and 13: according to Debian's release notes, rsyslog is no longer installed by default, so there is no auth.log. Use sudo journalctl -u ssh.
  • AlmaLinux, Rocky Linux, RHEL: /var/log/secure. sshd logs with SyslogFacility AUTHPRIV (set in /etc/ssh/sshd_config.d/50-redhat.conf), and rsyslog writes authpriv.* to that file. Or use sudo journalctl -u sshd.

This is what one SFTP session looked like in auth.log on our Ubuntu 26.04 test server (timestamps removed, key fingerprint shortened):

sshd-session[1111]: Accepted publickey for alice from 127.0.0.1 port 51784 ssh2: ED25519 SHA256:9jAH...
sshd-session[1111]: pam_unix(sshd:session): session opened for user alice(uid=1001) by root(uid=0)
sshd-session[1123]: Received disconnect from 127.0.0.1 port 51784:11: disconnected by user
sshd-session[1123]: Disconnected from user alice 127.0.0.1 port 51784
sshd-session[1111]: pam_unix(sshd:session): session closed for user alice

Nothing shows that this was SFTP rather than a shell, and no file names appear. Since OpenSSH 9.8 the login lines come from sshd-session, so search with grep sshd, which matches both names. With LogLevel VERBOSE in the sshd configuration you also get a line that names the subsystem: Starting session: subsystem 'sftp' for alice from 127.0.0.1 port 51788 id 0.

1. Log every SFTP file operation

  1. Create /etc/ssh/sshd_config.d/10-sftp-logging.conf with the line for your system:
    # AlmaLinux, Rocky Linux, RHEL
    Subsystem sftp /usr/libexec/openssh/sftp-server -l INFO -f LOCAL3
    
    # Ubuntu, Debian
    Subsystem sftp /usr/lib/openssh/sftp-server -l INFO -f LOCAL3
    -l INFO logs each operation (the default level is ERROR, which logs no transfers). -f LOCAL3 uses the syslog facility local3, so the lines can go to their own file. Without -f the facility is AUTH: the lines end up in auth.log on Ubuntu, and in /var/log/messages on AlmaLinux and Rocky Linux, because rsyslog there writes only authpriv to /var/log/secure.
  2. Check and apply it. sshd uses the first Subsystem line it reads, and the Include of sshd_config.d comes before the default line, so you do not need to edit /etc/ssh/sshd_config:
    sudo sshd -t
    sudo sshd -T | grep subsystem
    sudo systemctl restart ssh      # Ubuntu, Debian
    sudo systemctl restart sshd     # AlmaLinux, Rocky Linux, RHEL
    sshd -t prints nothing when the file is fine, and sshd -T should show your line: subsystem sftp /usr/lib/openssh/sftp-server -l INFO -f LOCAL3.
  3. Write local3 to its own file. Create /etc/rsyslog.d/10-sftp.conf:
    local3.*    /var/log/sftp.log
    & stop
    & stop keeps these lines out of syslog and messages. Check and restart rsyslog:
    sudo rsyslogd -N1
    sudo systemctl restart rsyslog
  4. Upload a test file and watch the log: sudo tail -f /var/log/sftp.log.

On Debian without rsyslog, skip step 3 and read the same lines from the journal: sudo journalctl -t sftp-server (or install rsyslog with sudo apt install rsyslog).

2. Read the SFTP log

One session on our test server: upload, download, rename, new folder, delete (timestamps removed):

sftp-server[1186]: session opened for local user alice from [127.0.0.1]
sftp-server[1186]: sent status No such file
sftp-server[1186]: open "/home/alice/report.txt" flags WRITE,CREATE,TRUNCATE mode 0644
sftp-server[1186]: close "/home/alice/report.txt" bytes read 0 written 6
sftp-server[1186]: open "/home/alice/report.txt" flags READ mode 0666
sftp-server[1186]: close "/home/alice/report.txt" bytes read 6 written 0
sftp-server[1186]: posix-rename old "/home/alice/report.txt" new "/home/alice/report-old.txt"
sftp-server[1186]: mkdir name "/home/alice/backups" mode 0777
sftp-server[1186]: remove name "/home/alice/report-old.txt"
sftp-server[1186]: rmdir name "/home/alice/backups"
sftp-server[1186]: session closed for local user alice from [127.0.0.1]
  • Upload: open with WRITE flags, then close with the bytes written.
  • Download: open with READ, then close with the bytes read.
  • sent status No such file before an upload is the client checking whether the file already exists, not an error.
  • To see who it was, match the process number with the login lines in auth.log or secure.

-l VERBOSE adds every stat, lstat and realpath request, which makes the file much longer without telling you more about transfers. INFO is enough for an audit trail.

3. Chrooted SFTP users (internal-sftp)

Users locked into a folder with ChrootDirectory and ForceCommand internal-sftp (see how to create an SFTP-only chroot user) do not use the Subsystem line. They need two changes:

  1. Add the options to their ForceCommand, for example in the Match Group sftponly block:
    ForceCommand internal-sftp -l INFO -f LOCAL3
  2. Give syslog a socket inside the chroot. In our test, step 1 alone logged nothing, because the chrooted process cannot reach /dev/log; the sftp-server manual says the same. With rsyslog, create /etc/rsyslog.d/09-sftp-chroot.conf with one line per chroot folder:
    input(type="imuxsock" Socket="/srv/sftp/bob/dev/log" CreatePath="on")
    Do not add a module(load="imuxsock") line: the main configuration already loads it, and rsyslogd -N1 reports "module 'imuxsock' already in this config". Run sudo rsyslogd -N1, restart rsyslog, then sshd.

The lines then appear as internal-sftp, with paths seen from inside the chroot:

internal-sftp[1403]: session opened for local user bob from [127.0.0.1]
internal-sftp[1403]: open "/upload/report.txt" flags WRITE,CREATE,TRUNCATE mode 0644
internal-sftp[1403]: close "/upload/report.txt" bytes read 0 written 6

4. Rotate the SFTP log

Create /etc/logrotate.d/sftp so the file does not grow forever, and test it with sudo logrotate -d /etc/logrotate.d/sftp:

/var/log/sftp.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
    postrotate
        systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}

Client side: debug an SFTP connection

To see what your own sftp client does, add -v: sftp -v alice@203.0.113.10 prints debug lines such as debug1: Sending subsystem: sftp and, at the end, the bytes transferred. For sftp commands and keys, see how to use SFTP to transfer files securely; for other log files on a server, see common log file locations and the journalctl cheat sheet.

Official documentation: sftp-server manual, sshd_config manual and rsyslog imuxsock module.

Ucartz services for this topic

Was this answer helpful? 0 Users Found This Useful (0 Votes)