Skip to content
An Elixir SFTP Client that wraps Erlang's ssh and ssh_sftp.
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib Fix docs for upload_file operation May 19, 2019
.gitignore Init project May 6, 2019
LICENSE Upgrade Delx May 19, 2019
mix.exs Upgrade Delx May 19, 2019
mix.lock Upgrade Delx May 19, 2019

SFTP Client

Build Status

An Elixir SFTP Client that wraps Erlang's ssh and ssh_sftp.


  • Erlang 20 or greater
  • Elixir 1.8 or greater


If available in Hex, the package can be installed by adding sftp_client to your list of dependencies in mix.exs:

def deps do
    {:sftp_client, "~> 1.3.1"}


There are bang (!) counterparts for almost all available functions.

Connect & Disconnect

To open a new connection to an SFTP server:

{:ok, conn} = SFTPClient.connect(host: "")

Refer to the docs for SFTPClient.Operations.Connect.connect/1 to find out all available options.

It is strongly recommended to close a connection after your operations have completed:


For short-lived connections you can also use a function as second argument. After the function body has run or raises, the connection is automatically closed.

SFTPClient.connect([host: ""], fn conn ->
  # Do something with conn


You can download a file from the server you can use the following function.

SFTPClient.download_file(conn, "my/remote/dir/file.jpg", "my/dir/local-file.jpg")
# => {:ok, "my/dir/local-file.jpg"}

When the third argument is an existing directory on your file system, the file is downloaded to a file with the same name as the one on the server.

SFTPClient.download_file(conn, "my/remote/dir/image.png", "my/local/dir")
# => {:ok, "my/local/dir/image.png"}

It is also possible to use Streams to download data into a file or memory.

source_stream = SFTPClient.stream_file!(conn, "my/remote/file.jpg")
target_stream =!("my/local/file.jpg")

|> Stream.into(target_stream)


To upload are file from the file system you can use the following function.

SFTPClient.upload_file(conn, "my/local/dir/file.jpg", "my/remote/dir/file.jpg")
# => {:ok, "my/remote/dir/file.jpg"}

You can also use Streams to upload data.

source_stream =!("my/local/file.jpg")
target_stream = SFTPClient.stream_file!(conn, "my/remote/file.jpg")

|> Stream.into(target_stream)

List Directory

SFTPClient.list_dir(conn, "my/dir")
# => {:ok, ["my/dir/file_1.jpg", "my/dir/file_2.jpg", ...]}

Create Directory

SFTPClient.make_dir(conn, "my/new/dir")

Note that this operation fails unless the parent directory exists.


To delete a file:

SFTPClient.delete_file(conn, "my/remote/file.jpg")

To delete a directory:

SFTPClient.delete(conn, "my/remote/dir")

Note that a directory cannot be deleted as long as it still contains files.


To delete a file or directory:

SFTPClient.rename(conn, "my/remote/file.jpg", "my/remote/new-file.jpg")

File Info

You can retrieve meta data about a file from the server such as file size, modification time, file permissions, owner and so on.

SFTPClient.file_info(conn, "my/remote/file.jpg")
# => {:ok, %File.Stat{...}}

Refer to the File.Stat docs for a list of available file information.

Symbolic Links

There are also a couple of functions that handle symlinks.

It is possible to get the target of a symlink.

SFTPClient.read_link(conn, "my/remote/link.jpg")
# => {:ok, "my/remote/file.jpg"}

You can retrieve meta data about symlinks, similar to file_info/2.

SFTPClient.link_info(conn, "my/remote/link.jpg")
# => {:ok, %File.Stat{...}}

And you are able to create symlinks.

SFTPClient.make_link(conn, "my/remote/link.jpg", "my/remote/file.jpg")


Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at

Missing Features

  • Support for ed25519 and ed448 keys
  • Remote TAR creation and extraction
  • :ssh_sftp.write_file_info/3
You can’t perform that action at this time.