README
¶
portable-sftp
A single-binary SFTP server for ad-hoc file transfers on a trusted network.
Run it in a directory, connect with any SFTP client, stop it when you're done. No daemon, no system configuration, no root privileges, no config file.
$ portable-sftp
portable-sftp v1.0.0
serving /home/you/Pictures (read-write)
listening [::]:2222
user sftp
password cAds-L29c-W88E-KWce
(generated for this run; set -password or $SFTP_PASSWORD to choose your own)
host key SHA256:PAbgL0iubsiG2h4YN1Fp9REmEGy2ai4L6q91JOvKTa4
connect with:
sftp -P 2222 sftp@192.168.50.241
Ctrl-C to stop.
Why
Moving a few files between a laptop and a phone, or between two machines on the same network, is a solved problem with about six unsatisfying solutions. This is one binary you can drop anywhere and delete afterwards.
Install
Download a binary from Releases, or:
go install github.com/H7O/portable-sftp@latest
Build it yourself:
git clone https://github.com/H7O/portable-sftp
cd portable-sftp
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o portable-sftp .
CGO_ENABLED=0 produces a static binary that runs on any Linux of the same
architecture. Cross-compile with GOOS/GOARCH:
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o portable-sftp-arm64 .
Requires Go 1.25 or newer to build (it uses os.Root for path confinement).
Usage
portable-sftp [flags]
| Flag | Default | Meaning |
|---|---|---|
-root |
. |
Directory to serve |
-user |
sftp |
Username clients must log in as |
-password |
generated | Password to require |
-keyfile |
authorized_keys file to accept instead of a password |
|
-port |
2222 |
Port to listen on (0 picks a free one) |
-bind |
all | Address to bind; 127.0.0.1 for local only |
-read-only |
false |
Refuse writes, renames, and deletions |
-max-conns |
10 |
Maximum concurrent connections |
-hostkey |
~/.config/portable-sftp/host_key |
Host key path |
-stats-interval |
0 |
Log a summary at this interval |
-verbose |
false |
Log every request, including rejected ones |
-version |
Print the version and exit |
Examples
Share a folder read-only:
portable-sftp -root ~/Pictures -read-only
Use a password you choose, without putting it in your shell history or in ps:
SFTP_PASSWORD='the one you want' portable-sftp
Use key authentication:
portable-sftp -keyfile ~/.ssh/authorized_keys
Accept connections from this machine only:
portable-sftp -bind 127.0.0.1
Authentication
If you give neither -password nor -keyfile, a strong password is generated
and printed once at startup. There is no default password.
-password and -keyfile are mutually exclusive, and only the corresponding
authentication method is offered to clients. -keyfile accepts a normal
OpenSSH authorized_keys file, so multiple keys and comments work as expected.
Host key
A persistent Ed25519 host key is generated on first run and stored in
~/.config/portable-sftp/host_key, so your client won't warn about a changed
fingerprint every time you start the server. The fingerprint is printed at
startup — check it against what your client shows on first connection.
The key is deliberately kept outside the served directory, and the server
refuses to start if -hostkey points inside -root, since a client could
otherwise download it and impersonate the server.
Security
This is a tool for trusted local networks. Do not expose it to the internet.
What it does
- Serves exactly one directory. Paths are confined with
os.Root, which resolves every path component through the kernel (openat2withRESOLVE_BENEATHwhere available)..., absolute paths, and symlinks pointing outside the root are all rejected, with no window between checking a path and opening it. - Never creates symlinks or hard links on the client's behalf.
- Offers only the authentication method you configured.
- Compares credentials in constant time.
- Caps concurrent connections and bounds the pre-authentication handshake.
- Recovers from panics in a session without taking down the server.
What it does not do
- No rate limiting on failed passwords. SSH caps attempts per connection, but nothing stops a client from reconnecting. Use the generated password or a key; don't pick a short one.
- No encryption at rest, no auditing, no multi-user support. One user, one directory, one password or key set.
- No protection against whoever runs it. The server has your filesystem
permissions.
-rootis a boundary for the client, not a sandbox for you. - Not hardened for hostile networks. It has not been audited, and it is not a replacement for OpenSSH.
If you need a real SFTP server, use OpenSSH with ChrootDirectory.
Found a security problem? See SECURITY.md.
Development
go test ./... # unit and end-to-end tests
go test -race ./... # the end-to-end tests are concurrent
go vet ./...
govulncheck ./... # go install golang.org/x/vuln/cmd/govulncheck@latest
gofmt -l .
The test suite starts real servers on ephemeral ports and drives them with a real SFTP client, including regression tests for path escapes, authentication bypasses, malformed protocol messages, and connection-limit enforcement.
License
Documentation
¶
Overview ¶
Command portable-sftp is a single-binary SFTP server for ad-hoc file transfers on a trusted network.
Run it in a directory and connect with any SFTP client. It serves exactly one directory, confined with os.Root, and needs no system configuration, no daemon, and no root privileges.