A pluggable SFTP server with support for multiple storage backends.
Sftpd wraps Erlang's :ssh_sftpd module and provides a clean API for
starting SFTP servers with configurable authentication and storage backends.
OTP 29 no longer enables the SFTP subsystem implicitly when starting an SSH
daemon. Sftpd.start_server/1 passes an explicit
:ssh_sftpd.subsystem_spec/1 to :ssh.daemon/2, so callers do not need to
configure the OTP daemon subsystem list themselves.
OTP 29 also disables shell and exec services by default. Sftpd is an
SFTP-only wrapper and does not enable remote shell or exec channels.
Quick Start
# Start an SFTP server with the in-memory backend
{:ok, ref} = Sftpd.start_server(
port: 2222,
backend: Sftpd.Backends.Memory,
backend_opts: [],
auth: {:passwords, [{"dev", "dev"}]},
system_dir: "ssh_keys"
)Backends
Sftpd supports pluggable backends. Built-in backends:
Sftpd.Backends.Memory- in-memory storage for development and testsSftpd.Backends.S3- optional Amazon S3 or S3-compatible storage
To create a custom backend, implement the Sftpd.Backend behaviour.
See the HexDocs extras Backends and
Custom Backends for package-level guidance and
examples. If you need persistent object storage, see the S3 backend docs for
the optional dependency set required by that backend.
Guides
Package-level HexDocs extras:
Options
:port- Port to listen on (default: 22):backend- Backend module,{:genserver, pid_or_name}, or{:genserver, pid_or_name, session: true}(required):backend_opts- Options passed tobackend.init/1for module backends (default: []) The built-in S3 backend accepts:bucket,:prefix, and:aws_client.:auth- Authentication config, either{:passwords, list}or{Module, opts}(required):system_dir- Directory containing SSH host keys (required):max_sessions- Maximum concurrent sessions (default: 10):open_timeout- Timeout in milliseconds for opening files (default: 30000):close_timeout- Timeout in milliseconds for finalizing file closes (default: 30000)
Process-Based Backends
Instead of a module, you can use a running GenServer:
{:ok, backend_pid} = MyBackendServer.start_link()
Sftpd.start_server(backend: {:genserver, backend_pid}, ...)See Sftpd.Backend for the messages your GenServer must handle.
Telemetry
See Sftpd.Telemetry and the Telemetry extra in HexDocs for the event
reference emitted by the server and file-handler layers.
SSH Host Keys
You need SSH host keys for the server. Generate them with:
ssh-keygen -t rsa -f ssh_host_rsa_key -N ""
ssh-keygen -t ecdsa -f ssh_host_ecdsa_key -N ""Then set :system_dir to the directory containing these keys.
Summary
Functions
Return a child spec for supervising an SFTP server.
Start an SFTP server.
Stop an SFTP server.
Types
@type server_ref() :: :ssh.daemon_ref()
Functions
@spec child_spec(keyword()) :: Supervisor.child_spec()
Return a child spec for supervising an SFTP server.
This lets applications start the server directly from a supervision tree:
children = [
{Sftpd,
port: 2222,
backend: Sftpd.Backends.Memory,
backend_opts: [],
auth: {:passwords, [{"dev", "dev"}]},
system_dir: "ssh_keys"}
]
@spec start_server(keyword()) :: {:ok, server_ref()} | {:error, term()}
Start an SFTP server.
Examples
# Start with the in-memory backend
{:ok, ref} = Sftpd.start_server(
port: 2222,
backend: Sftpd.Backends.Memory,
backend_opts: [],
auth: {:passwords, [{"admin", "secret"}]},
system_dir: "ssh_keys"
)Options
See module documentation for full list of options.
@spec stop_server(server_ref()) :: :ok | {:error, term()}
Stop an SFTP server.
Examples
{:ok, ref} = Sftpd.start_server(opts)
:ok = Sftpd.stop_server(ref)