TL;DR: Install SFTPGo on Ubuntu, get a web-based SFTP management interface with mandatory HTTPS. Costs $12/month vs $220/month for Azure Blob SFTP.
# Add repo and install
sudo add-apt-repository ppa:sftpgo/sftpgo
sudo apt update && sudo apt install sftpgo -y
# Configure firewall
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP (for SSL setup/redirect)
sudo ufw allow 443/tcp # HTTPS
sudo ufw allow 2022/tcp # SFTP
sudo ufw enable
# Set up HTTPS (see HTTPS Setup section - DO THIS BEFORE accessing web UI)
# Then access web UI and create admin account
# https://your_domain.com OR https://your_server_ip (with tunnel)Requirements:
- Ubuntu 24.04 or 22.04 LTS
- 2GB RAM minimum
- Root or sudo access
Create DigitalOcean Droplet:
- OS: Ubuntu 24.04 LTS
- Plan: Basic $12/month (2GB RAM)
- Choose datacenter region
- Authentication: SSH key recommended
Connect:
ssh root@your_server_ip# Update system
sudo apt update && sudo apt upgrade -y
# Add SFTPGo repository
sudo add-apt-repository ppa:sftpgo/sftpgo
# Install
sudo apt update
sudo apt install sftpgo -y
# Verify it's running
sudo systemctl status sftpgoSFTPGo automatically:
- ✅ Starts on installation
- ✅ Enables on boot
- ✅ Creates data directories at
/srv/sftpgo/data/
# Allow required ports
sudo ufw allow 22/tcp # SSH access
sudo ufw allow 80/tcp # HTTP (for SSL/redirects)
sudo ufw allow 443/tcp # HTTPS
sudo ufw allow 2022/tcp # SFTP connections
# Enable firewall
sudo ufw enable
# Check status
sudo ufw status
# Note: Port 8080 should NOT be publicly accessiblePrerequisites:
- Own a domain (e.g., yourdomain.com)
- Point DNS A record to your droplet IP:
sftp.yourdomain.com → your_server_ip
Setup:
1. Install Nginx and Certbot:
sudo apt install nginx certbot python3-certbot-nginx -y2. Create Nginx config:
sudo nano /etc/nginx/sites-available/sftpgoPaste this simple HTTP-only configuration (certbot will add SSL automatically):
server {
listen 80;
server_name sftp.yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}3. Enable site:
sudo ln -s /etc/nginx/sites-available/sftpgo /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default # Remove default site
sudo nginx -t
sudo systemctl restart nginx4. Get FREE SSL certificate:
Certbot will automatically:
- Get the SSL certificate
- Add HTTPS configuration to your Nginx config
- Set up HTTP to HTTPS redirect
- Add security headers
- Configure auto-renewal
sudo certbot --nginx -d sftp.yourdomain.com
# Follow prompts:
# Enter email: your-email@domain.com
# Agree to terms: Y
# Share email: N (optional)After certbot completes, it will have automatically modified your Nginx configuration to include SSL.
5. Verify the setup:
# Check the SSL configuration certbot added
sudo cat /etc/nginx/sites-available/sftpgo
# Test Nginx configuration
sudo nginx -t
# Restart to ensure everything is loaded
sudo systemctl restart nginx
# Verify HTTPS is working
curl -I https://sftp.yourdomain.com6. Verify certificate auto-renewal:
# Test renewal
sudo certbot renew --dry-run
# Check auto-renewal timer
sudo systemctl status certbot.timer
# Should show: active (waiting)7. Verify port 8080 is not publicly accessible:
sudo ufw status | grep 8080
# Should NOT show port 8080 allowed from anywhere✅ Access your admin panel: https://sftp.yourdomain.com
1. Install Nginx:
sudo apt install nginx -y2. Create certificate directory and generate self-signed certificate:
# Create certificate directory
sudo mkdir -p /etc/nginx/ssl
# Generate self-signed certificate (valid 365 days)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/sftpgo.key \
-out /etc/nginx/ssl/sftpgo.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=your_server_ip"
# Secure the files
sudo chmod 600 /etc/nginx/ssl/sftpgo.key
sudo chmod 644 /etc/nginx/ssl/sftpgo.crt3. Create Nginx config:
sudo nano /etc/nginx/sites-available/sftpgoPaste this configuration:
server {
listen 80;
server_name _;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name _;
# Self-signed certificate
ssl_certificate /etc/nginx/ssl/sftpgo.crt;
ssl_certificate_key /etc/nginx/ssl/sftpgo.key;
# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}4. Enable and restart:
sudo ln -s /etc/nginx/sites-available/sftpgo /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx5. Verify port 8080 is not publicly accessible:
sudo ufw status | grep 8080
# Should NOT show port 8080 allowed from anywhere✅ Access your admin panel: https://your_server_ip
Note: Browser will show "Not Secure" warning. Click "Advanced" → "Proceed" (or equivalent). Traffic is encrypted, but browser can't verify identity because the certificate is self-signed.
Best for: Solo admin, maximum security, no domain needed, no certificate setup needed.
No Nginx needed! Port 8080 remains blocked from the internet entirely.
From Your Local Machine:
Mac/Linux:
ssh -L 8080:localhost:8080 root@your_server_ip -NWindows (using PuTTY):
- Session → Host:
your_server_ip - Connection → SSH → Tunnels:
- Source port:
8080 - Destination:
localhost:8080 - Click "Add"
- Source port:
- Click "Open"
Then access: http://localhost:8080
Why this is secure:
- ✅ Traffic encrypted via SSH tunnel
- ✅ Port 8080 never exposed to internet
- ✅ No certificates needed
- ✅ Works without domain
- ✅ Maximum security
Downside: Must create tunnel each time you need admin access (takes ~5 seconds)
Ensure port 8080 is blocked:
# Verify 8080 is NOT in the firewall rules
sudo ufw status | grep 8080
# If it shows as allowed, you're good since it's already blocked by default✅ Access your admin panel: http://localhost:8080 (while SSH tunnel is active)
| Scenario | Best Option | Why |
|---|---|---|
| Have domain name | Option 1 (Let's Encrypt) | Free, trusted certificate, no warnings |
| No domain, multiple admins | Option 2 (Self-signed) | HTTPS protection, accessible to team |
| No domain, solo admin | Option 3 (SSH tunnel) | Most secure, zero certificate hassle |
| Temporary/testing | Option 3 (SSH tunnel) | Quick, no setup needed |
After setting up HTTPS using one of the three options above, open browser and navigate to your secure URL.
You'll see the first-time setup page:
- Enter admin username
- Create strong password (20+ characters)
- Click "Create Admin"
- You're in! 🎉
Security Note: Create the admin account immediately after installation. Anyone who accesses the web UI first can create it.
-
Navigate: Click "Users" → "+" button
-
Basic Info:
- Username:
company_a - Status: ✅ Enabled
- Password: Leave blank (using SSH keys)
- Home Dir:
/srv/sftpgo/data/company_a
- Username:
-
Add SSH Key:
- Click "Add" in Public keys section
- Paste the public key:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJl3dIeun... user@example.com
-
Set Permissions (check what you need):
- ✅ List items
- ✅ Download
- ✅ Upload
- ✅ Overwrite
- ✅ Delete
- ✅ Rename
- ✅ Create dirs
- ✅ Create symlinks
- ✅ Delete dirs
- ✅ Delete files
-
Quota (optional):
- Size:
50GB - Files:
10000files - (
0= unlimited)
- Size:
-
Bandwidth (optional):
- Upload:
0KB/s (unlimited) - Download:
0KB/s (unlimited)
- Upload:
-
Click Submit ✓
Same process for company_b, company_c, etc. Each user gets:
- ✅ Isolated home directory
- ✅ Cannot see other users' files
- ✅ Independent quotas and permissions
sftp -P 2022 -i ~/.ssh/id_ed25519 company_a@your_server_ipTest operations:
sftp> ls
sftp> mkdir test
sftp> put local_file.txt
sftp> get remote_file.txt
sftp> exitSetup:
- Edit → Settings → SFTP
- Add key file (private key)
- Click OK
Connect:
- Host:
sftp://your_server_ip - Port:
2022 - Username:
company_a - Password: (leave blank)
- Click "Quickconnect"
SFTP Server Connection Info:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Host: your_server_ip
Port: 2022
Username: company_a
Auth: SSH Key Only
Protocol: SFTP
View All Users:
- Click "Users" in sidebar
- See login times, disk usage, status
Edit User:
- Click username
- Modify any setting
- Click Submit (takes effect immediately)
Add SSH Key to User:
- Edit user → Public keys → Add
- Paste new key → Submit
- Now both keys work
Revoke SSH Key:
- Edit user → Find key
- Click 🗑️ trash icon
- Submit (immediate revoke)
Monitor Active Connections:
- Click "Connections"
- See who's connected right now
- View active transfers
- Force disconnect if needed
View Logs:
- Click "Logs"
- Filter by user, event type, date
- See logins, uploads, downloads, errors
Check Disk Usage:
- Users page shows quota usage
- Click user for detailed breakdown
- Manual quota scan available
Create shared folder:
- Click "Folders" → "+"
- Name:
shared_documents - Path:
/srv/sftpgo/data/shared - Submit
Mount to users:
- Edit user → Virtual folders → Add
- Select
shared_documents - Virtual path:
/shared - Set permissions → Submit
Now multiple users can access the same folder!
Create group:
- Click "Groups" → "+"
- Name:
premium_clients - Set default quota:
100GB - Configure default permissions
- Submit
Assign users:
- Edit user
- Select group from dropdown
- Submit
Group settings apply automatically to all members.
Limit by IP:
- Edit user
- IP address restrictions section
- Allowed IP/Mask:
203.0.113.0/24 - Submit
User can only connect from those IPs.
Set speed limits:
- Edit user
- Upload bandwidth:
5120KB/s (5 MB/s) - Download bandwidth:
10240KB/s (10 MB/s) - Submit
Automate actions:
- Click "Event Manager" → "+"
- Set trigger (e.g., "file uploaded")
- Add conditions (optional)
- Define action:
- HTTP webhook
- Execute command
- Send email
- Delete files
- Submit
Example: Email notification on every upload.
✅ Mandatory HTTPS - Admin interface never accessible over HTTP
✅ Chroot Isolation - Users can't escape their directories
✅ SSH Key Auth - No password brute-force attacks
✅ IP Whitelisting - Restrict by location
✅ Bandwidth Limits - Prevent abuse
✅ Quota Enforcement - Automatic disk limits
✅ Audit Logging - Complete activity trail
✅ 2FA Support - Optional TOTP
✅ Per-folder Permissions - Granular control
Let's Encrypt certificates expire every 90 days. Certbot auto-renews them:
# Test renewal (dry run)
sudo certbot renew --dry-run
# Check auto-renewal timer
sudo systemctl status certbot.timer
# Should show: active (waiting)
# Manual renewal (if needed)
sudo certbot renew
# Force renewal (for testing)
sudo certbot renew --force-renewalCertbot automatically renews certificates when they have 30 days left.
Set up renewal notifications:
# Add to /etc/letsencrypt/renewal-hooks/post/notify.sh
sudo nano /etc/letsencrypt/renewal-hooks/post/notify.shAdd:
#!/bin/bash
echo "SSL certificate renewed successfully" | \
mail -s "SSL Certificate Renewed" admin@yourdomain.comMake executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/notify.sh# Check SFTPGo service status
sudo systemctl status sftpgo
# Restart service
sudo systemctl restart sftpgo
# Check Nginx status (if using Options 1 or 2)
sudo systemctl status nginx
sudo nginx -t # Test configuration
# Check firewall
sudo ufw status
# View SFTPGo logs
sudo journalctl -u sftpgo -n 50 --no-pager
# View Nginx logs (if using Options 1 or 2)
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log# Check certificate expiry
sudo certbot certificates
# Test renewal
sudo certbot renew --dry-run
# Force renewal
sudo certbot renew --force-renewal
# Check Nginx SSL config
sudo nginx -t# Reset password
sudo sftpgo resetpwd --admin admin
# Enter new password when prompted# Verify SFTPGo is listening on port 2022
sudo ss -tlnp | grep 2022
# Check firewall allows 2022
sudo ufw status | grep 2022
# Test from server
sftp -P 2022 username@localhostCheck in web UI:
- User is enabled
- SSH key is correctly added (no extra spaces)
- Home directory path is correct
- No IP restrictions blocking them
Check logs:
- Web UI → Logs → Filter by username
# Trigger manual quota scan
# In web UI: Edit user → Click "Quota scan" button
# Or via command line
sudo sftpgo quota-scan --username company_a# Service management
sudo systemctl status sftpgo
sudo systemctl restart sftpgo
sudo systemctl stop sftpgo
sudo systemctl start sftpgo
# Nginx service (if using Options 1 or 2)
sudo systemctl status nginx
sudo systemctl restart nginx
sudo nginx -t # Test configuration
# View logs
sudo journalctl -u sftpgo -f # Follow logs
sudo journalctl -u sftpgo -n 100 # Last 100 lines
sudo journalctl -u sftpgo --since today # Today's logs
# Check config
sudo cat /etc/sftpgo/sftpgo.json
# Data directory
ls -lah /srv/sftpgo/data/
# Check port usage
sudo ss -tlnp | grep -E '2022|8080|443'Important files to backup:
# User database and config
/var/lib/sftpgo/
/etc/sftpgo/
# User data
/srv/sftpgo/data/
# SSL certificates (if using Option 2)
/etc/nginx/ssl/
# Let's Encrypt (if using Option 1)
/etc/letsencrypt/Simple backup script:
#!/bin/bash
BACKUP_DIR="/backup/sftpgo/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Stop service
sudo systemctl stop sftpgo
# Backup
sudo cp -r /var/lib/sftpgo "$BACKUP_DIR/"
sudo cp -r /etc/sftpgo "$BACKUP_DIR/"
sudo cp -r /srv/sftpgo/data "$BACKUP_DIR/"
# Backup SSL (if applicable)
[ -d /etc/letsencrypt ] && sudo cp -r /etc/letsencrypt "$BACKUP_DIR/"
[ -d /etc/nginx/ssl ] && sudo cp -r /etc/nginx/ssl "$BACKUP_DIR/"
# Start service
sudo systemctl start sftpgo
echo "Backup completed: $BACKUP_DIR"| Solution | Monthly Cost | Annual Cost |
|---|---|---|
| SFTPGo (Self-hosted) | $12 | $144 |
| Azure Blob SFTP | $220+ | $2,640+ |
| AWS Transfer Family | $216+ | $2,592+ |
| Your Savings | $208/month | $2,496/year |
- ❌ Access admin panel over HTTP
- ❌ Leave port 8080 open to public
- ❌ Use weak passwords
- ❌ Ignore certificate expiration warnings
- ❌ Share credentials between companies
- ❌ Disable SSL/TLS
- ✅ Use HTTPS for all admin access (one of the three secure methods)
- ✅ Use strong, unique passwords (20+ characters, mixed case, numbers, symbols)
- ✅ Enable 2FA if SFTPGo supports it (check latest version)
- ✅ Restrict admin access by IP when possible
- ✅ Monitor access logs regularly
- ✅ Keep SSL certificates up to date (Option 1 auto-renews)
- ✅ Regular backups of SFTPGo configuration
- ✅ Test disaster recovery procedures
- ✅ Keep system and SFTPGo updated
Pros:
- ✅ Web-based management (no CLI needed)
- ✅ Multi-tenant with isolation
- ✅ SSH key authentication
- ✅ Quota management
- ✅ Real-time monitoring
- ✅ Free and open source
- ✅ Active development
- ✅ Extensive documentation
- ✅ API for automation
- ✅ Cost-effective ($12/month)
- ✅ Secure HTTPS options built-in
Cons:
⚠️ Requires server management⚠️ You handle backups⚠️ You handle updates⚠️ No built-in redundancy (single server)
Perfect for:
- Companies sharing files with clients
- Agencies managing client uploads
- SaaS apps needing SFTP integration
- Replacing expensive managed SFTP services
- Teams that need web-based management
Enhance Security:
- Verify HTTPS is working correctly
- Enable 2FA for admin account
- Set up automated backups
- Implement IP whitelisting
- Configure fail2ban for brute-force protection
Scale Up:
- Move to PostgreSQL/MySQL for larger deployments
- Set up multiple SFTPGo instances with load balancer
- Integrate with LDAP/Active Directory
- Configure S3/Azure Blob as storage backend
- Set up monitoring with Prometheus/Grafana
Automate:
- Use SFTPGo REST API for user provisioning
- Set up event rules for automated workflows
- Create scripts for bulk user management
- Integrate with your billing system
- Official Docs: https://sftpgo.github.io/latest/
- GitHub: https://github.com/drakkan/sftpgo
- REST API Docs: https://sftpgo.github.io/latest/api/
- Docker: https://hub.docker.com/r/drakkan/sftpgo
# Installation
sudo add-apt-repository ppa:sftpgo/sftpgo && sudo apt update && sudo apt install sftpgo -y
# Set up HTTPS first (see HTTPS Setup section)
# Web UI (choose your secure method)
https://sftp.yourdomain.com # Option 1
https://your_server_ip # Option 2
http://localhost:8080 # Option 3 (via SSH tunnel)
# SFTP Connection
sftp -P 2022 -i ~/.ssh/key username@your_server_ip
# Service Commands
sudo systemctl {start|stop|restart|status} sftpgo
sudo systemctl {start|stop|restart|status} nginx # If using Options 1 or 2
# Logs
sudo journalctl -u sftpgo -f
sudo tail -f /var/log/nginx/error.log # If using Options 1 or 2
# Reset Admin Password
sudo sftpgo resetpwd --admin admin
# Quota Scan
sudo sftpgo quota-scan --username username
# SSL Certificate (Option 1)
sudo certbot renew --dry-run
sudo certbot certificatesSetup time: ~30-45 minutes (including HTTPS)
Learning curve: Low (web interface)
Maintenance: Minimal (mainly OS updates)
Security: Production-ready with mandatory HTTPS
Enjoy your cost-effective, professional, secure SFTP server! 🚀