Simple FTP Service

Cloud storage limitations over FTP and SFTP

What object storage backends can and cannot do through an FTP/SFTP interface - renames, symlinks, appends, and why some operations show up as two log entries.
Updated August 27, 2026

Your Simple FTP Service presents S3, Azure Storage or Google Cloud Storage as if it were a filesystem - but object storage is not a filesystem. A few FTP and SFTP operations behave differently as a result. They all come down to the same underlying fact, so they are collected here.

Renames (mv) are a copy plus a delete

FTP and SFTP both have a rename command, but none of the bucket backends have a rename API - an object's name is its identity. So when a user renames a file, the server performs a copy to the new name, then a delete of the old name on your backend.

You will see this in your service logs as two entries for one mv:

  • a COPY API call (executed first)
  • a DELETE API call (executed second, shown first in the log ordering so the old-name → new-name relationship reads naturally)

Two entries are deliberate: if the copy succeeds but the delete fails, the log shows exactly which half completed - which is also why a failed rename can leave both the old and new names present (never neither).

Note that a rename of a large file re-copies the whole object on the backend, so it is not instant the way a filesystem rename is.

Object stores have no native symlink concept, so creating symlinks over SFTP is not supported on S3, Azure or GCS backends.

APPE (append) cannot append

The FTP APPE command is accepted, but object storage cannot append to an existing object. APPE behaves like STOR: it uploads the file if nothing exists at that name, and will not overwrite or extend a file that already exists.

Empty directories

Directories are a naming convention in object storage, not a real object. A freshly created user whose home directory has never had a file uploaded may not "exist" yet from the backend's point of view - see 550 Not found when logging in.