SFTPGo: A Modern Self-Hosted SFTP, FTP, and WebDAV Server
If you need a self-hosted file transfer server — for automated backups, secure file exchange with clients, or replacing a managed FTP service — SFTPGo covers all the bases. It supports SFTP, FTP/FTPS, WebDAV, and HTTP/WebDAV, with a web admin interface and support for local storage, S3, Azure Blob, and Google Cloud Storage.
Photo by Hassaan Here on Unsplash
It's a substantial upgrade over vanilla OpenSSH for multi-user file transfer.
What SFTPGo Provides
- Multiple protocols: SFTP, FTP, FTPS, WebDAV, HTTP file browsing
- Virtual users: Isolated user accounts with per-user storage quotas and chroot jails
- Storage flexibility: Local filesystem, S3, Azure Blob, GCS, or SFTP as backends
- Web admin UI: Full user management, transfer statistics, and configuration
- Web client: Optional browser-based file manager for end users
- Hooks: Pre/post-transfer events for integration with other systems
- Two-factor authentication: TOTP support for admin and user accounts
Docker Deployment
services:
sftpgo:
image: drakkan/sftpgo:latest
container_name: sftpgo
ports:
- "2022:2022" # SFTP
- "8080:8080" # Web admin + WebDAV
- "2121:2121" # FTP (if enabled)
environment:
- SFTPGO_COMMON__UPLOAD_MODE=2
- SFTPGO_DATA_PROVIDER__DRIVER=sqlite
- SFTPGO_DATA_PROVIDER__NAME=/var/lib/sftpgo/sftpgo.db
volumes:
- sftpgo_data:/var/lib/sftpgo
- sftpgo_home:/srv/sftpgo
restart: unless-stopped
volumes:
sftpgo_data:
sftpgo_home:
After starting, access the admin UI at http://localhost:8080/web/admin. On first run, it prompts you to create an admin account.
Creating Virtual Users
Virtual users are isolated file transfer accounts. Each user gets:
- A home directory (or virtual filesystem mapped to cloud storage)
- Configurable quotas (storage size, file count, bandwidth)
- SSH key or password authentication
- Protocol restrictions (SFTP only, FTP only, etc.)
Via Admin UI
- Go to Users → Add User
- Set username and authentication method (password or SSH key)
- Set Home Dir (e.g.,
/srv/sftpgo/users/alice) - Configure quotas and permissions
- Save
Via API
curl -X POST http://localhost:8080/api/v2/users \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"password": "secure-password",
"home_dir": "/srv/sftpgo/users/alice",
"permissions": {"/": ["*"]},
"quota_size": 5368709120
}'
SSH Key Authentication
For automated transfers, SSH key auth is more secure than passwords:
# Generate a key pair
ssh-keygen -t ed25519 -f sftpgo_client_key -N ""
# Get the public key
cat sftpgo_client_key.pub
In the user settings, add the public key under SSH public keys. The private key stays on the client:
# Connect with key
sftp -i sftpgo_client_key -P 2022 [email protected]
Virtual Filesystem: S3 Backend
Map a user's home directory to an S3 bucket instead of local disk:
In User settings → Virtual Filesystem, select S3 as storage type:
{
"filesystem": {
"provider": 1,
"s3config": {
"bucket": "my-uploads-bucket",
"region": "us-east-1",
"access_key": "AKIAIOSFODNN7EXAMPLE",
"access_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"key_prefix": "users/alice/"
}
}
}
Files transferred via SFTP land directly in S3 — no local disk involved. This is useful for ingestion pipelines, photo upload workflows, and keeping storage costs predictable.
WebDAV Access
WebDAV lets users mount their SFTPGo home directory as a network drive:
Enable WebDAV in sftpgo.json or environment:
SFTPGO_WEBDAVD__BINDINGS__0__PORT=8081
SFTPGO_WEBDAVD__BINDINGS__0__ADDRESS=0.0.0.0
macOS: Finder → Go → Connect to Server → http://your-server:8081/alice
Windows: Map Network Drive → \\your-server\alice (with WebDAV configured)
Linux: davfs2 mount or Nautilus/Dolphin file managers
Bandwidth and Quota Controls
Quota settings per user:
| Setting | Description |
|---|---|
| Max quota size | Total disk space (bytes) |
| Max quota files | Maximum file count |
| Upload bandwidth | Max upload speed (KB/s) |
| Download bandwidth | Max download speed (KB/s) |
| Max sessions | Concurrent connections |
Global defaults can be set in server settings; per-user overrides take precedence.
Transfer Logs and Hooks
SFTPGo logs every transfer. For integrations, hooks fire on events:
{
"hooks": {
"fs_events_worker_pools": 2,
"provider_events_worker_pools": 2
}
}
Hook types:
- Pre-upload/download: Validate before allowing transfer
- Post-upload/download: Trigger processing (e.g., run a script, notify a service)
- Quota exceeded: Notify or reject uploads over limit
Configure via the admin UI under Event Manager → Actions.
Two-Factor Authentication
Enable TOTP for admin and user accounts:
- Admin UI → Security → Two-Factor Auth
- Scan QR code with any TOTP app (Aegis, Authy, Google Authenticator)
- Confirm with a code
For web client users, 2FA works the same way from their profile page.
FTP/FTPS Configuration
FTPS (FTP over TLS) is available for legacy systems that can't use SFTP:
environment:
- SFTPGO_FTPD__BINDINGS__0__PORT=2121
- SFTPGO_FTPD__BINDINGS__0__FORCE_PASSIVE_IP=your-public-ip
- SFTPGO_FTPD__CERTIFICATE_FILE=/etc/ssl/certs/sftpgo.crt
- SFTPGO_FTPD__CERTIFICATE_KEY_FILE=/etc/ssl/private/sftpgo.key
Note: FTP without TLS is plaintext — only use FTPS or SFTP for anything sensitive.
vs. OpenSSH for File Transfer
| Feature | SFTPGo | OpenSSH SFTP |
|---|---|---|
| Multi-user management | Admin UI | System users |
| Storage quotas | Built-in | External tools |
| Cloud storage backends | ✓ | ✗ |
| FTP/WebDAV | ✓ | ✗ |
| Transfer stats | Built-in dashboard | Log parsing |
| Event hooks | ✓ | Manual scripting |
OpenSSH is simpler for single-user or trusted-user access. SFTPGo is the right choice when you need proper multi-user management, quotas, or cloud storage integration.
