How to Deploy SFTPGo as a Self-Hosted Azure Storage SFTP Alternative

Updated on 16 April, 2026
Deploy SFTPGo as a cost-effective alternative to Azure Storage SFTP with Docker.
How to Deploy SFTPGo as a Self-Hosted Azure Storage SFTP Alternative header image

SFTPGo is an open-source SFTP server that provides multi-protocol file transfer (SFTP, FTP/S, WebDAV), a web administration interface, and support for multiple storage backends. SFTPGo provides equivalent functionality with Azure Blob Storage as a backend, user management, and protocol support without the continuous hourly charges.

This article explains how to deploy SFTPGo. It covers Docker-based installation, user authentication configuration, and migration strategies from Azure Storage SFTP.

Prerequisites

Before you begin, ensure you have:

Understanding SFTPGo Architecture

SFTPGo maps directly to Azure Storage SFTP features while providing additional flexibility. The following table compares Azure Storage SFTP components with their SFTPGo equivalents:

Azure Storage SFTP SFTPGo Equivalent Description
SFTP Endpoint SFTPGo SFTP Server Accepts SFTP connections on configurable port (default: 2022)
Azure Blob Storage Azure Blob Backend Native support for Azure Blob Storage containers
Azure AD Authentication LDAP/OIDC Integration External identity provider support via plugins
Local Users User Management Create and manage users via web interface or REST API
Hierarchical Namespace Directory Structure Virtual directory support without requiring HNS
Azure Monitor Event Logging Built-in logging with webhook and syslog integrations

Key components of SFTPGo include:

  • Protocol Handlers: Listeners for SFTP (port 2022), FTP/S (port 2121), and WebDAV (port 10080)
  • Web Admin Interface: Browser-based dashboard on port 8080 for configuration and monitoring
  • Data Provider: SQLite, MySQL, or PostgreSQL database for storing user and configuration data
  • Storage Backends: Pluggable layer supporting local filesystem, Azure Blob Storage, S3-compatible storage (including Vultr Object Storage), and Google Cloud Storage

Deploy SFTPGo with Docker Compose

The stack consists of two containers: SFTPGo handles file transfer and user management, and Traefik acts as a reverse proxy that provisions a Let's Encrypt TLS certificate and routes HTTPS traffic to the SFTPGo admin interface on port 8080. Including Traefik from the start ensures that credentials and configuration are never transmitted over an unencrypted connection.

  1. Create the project directory with subdirectories for data and configuration persistence.

    console
    $ mkdir -p ~/sftpgo/{data,config}
    
    • data: Stores user files served over SFTP.
    • config: Holds SFTPGo configuration and the SQLite database.
  2. Switch to the project directory.

    console
    $ cd ~/sftpgo
    
  3. Create an environment file for domain configuration. Replace sftp.example.com with your domain and admin@example.com with your email address for Let's Encrypt notifications.

    console
    $ nano .env
    
  4. Add the following variables:

    ini
    DOMAIN=sftp.example.com
    LETSENCRYPT_EMAIL=admin@example.com
    

    Save and close the file.

  5. Create the Docker Compose configuration file.

    console
    $ nano docker-compose.yml
    
  6. Add the following service definition:

    yaml
    services:
      traefik:
        image: traefik:v3.6
        container_name: traefik
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "letsencrypt:/letsencrypt"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
        restart: unless-stopped
    
      sftpgo:
        image: drakkan/sftpgo:v2.7
        container_name: sftpgo
        restart: unless-stopped
        ports:
          - "2022:2022"
          - "2121:2121"
          - "10080:10080"
        environment:
          - SFTPGO_HTTPD__BINDINGS__0__PORT=8080
          - SFTPGO_HTTPD__BINDINGS__0__ADDRESS=0.0.0.0
          - SFTPGO_SFTPD__BINDINGS__0__PORT=2022
          - SFTPGO_FTPD__BINDINGS__0__PORT=2121
          - SFTPGO_WEBDAVD__BINDINGS__0__PORT=10080
          - SFTPGO_DATA_PROVIDER__DRIVER=sqlite
          - SFTPGO_DATA_PROVIDER__NAME=/var/lib/sftpgo/sftpgo.db
        volumes:
          - ./data:/srv/sftpgo
          - ./config:/var/lib/sftpgo
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.sftpgo.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.sftpgo.entrypoints=websecure"
          - "traefik.http.routers.sftpgo.tls.certresolver=letsencrypt"
          - "traefik.http.services.sftpgo.loadbalancer.server.port=8080"
        healthcheck:
          test: ["CMD", "sftpgo", "ping", "-c", "/var/lib/sftpgo"]
          interval: 30s
          timeout: 10s
          retries: 3
    
    volumes:
      letsencrypt:
    

    Save and close the file.

    This configuration exposes:

    • Port 80/443: Traefik handles HTTP-to-HTTPS redirection and TLS termination for the web admin interface
    • Port 2022: SFTP protocol
    • Port 2121: FTP/S protocol
    • Port 10080: WebDAV protocol

    The web admin interface on port 8080 is not exposed directly to the host. Traefik proxies requests to it internally over the Docker network.

  7. Launch the stack.

    console
    $ docker compose up -d
    
  8. Confirm all containers are running and healthy.

    console
    $ docker compose ps
    
  9. Review the container logs to verify that no startup errors occurred.

    console
    $ docker compose logs
    

    For more information on managing a Docker Compose stack, see the How To Use Docker Compose article.

Configure SFTPGo Server

The web-based administration interface handles initial setup and ongoing server configuration.

  1. Open a web browser and navigate to https://sftp.example.com/web/admin, replacing sftp.example.com with your configured domain.

    SFTPGo web admin dashboard

  2. Create an administrator account on first access:

    • Enter a username (for example, admin)
    • Set a strong password
    • Confirm the password in the Confirm password field
    • Click Create admin and Sign in

    The dashboard loads.

    Dashboard

  3. Navigate to Server Manager > Configurations in the sidebar to review default settings.

  4. Review the SFTP, ACME, and SMTP sections to confirm that the default configuration matches your requirements.

Set Up User Authentication

SFTPGo supports password authentication, SSH public keys, and multi-factor authentication. Azure Storage SFTP local users can be recreated with equivalent access controls.

Create an SFTP User

  1. Navigate to Users in the sidebar.

  2. Click Add to create a new user.

    SFTPGo Add User form showing Username, Password, Public keys, TLS certificates, and File system sections

  3. Configure the account settings:

    • Username: Enter the SFTP username
    • Password: Set a strong password
    • Under Profile, set Status to Active
  4. Under File system, keep Local disk selected for local storage.

  5. Set the Root directory to /srv/sftpgo/USERNAME, replacing USERNAME with the SFTP username configured in the previous step.

  6. Click Save.

Configure SSH Key Authentication

SSH keys provide passwordless authentication similar to Azure Storage SFTP's SSH key support.

  1. Generate an SSH key pair on the client machine if one does not exist.

    console
    $ ssh-keygen -t ed25519 -f ~/.ssh/sftpgo_key -C "sftp-user"
    

    When prompted for a passphrase, press Enter twice to create the key without a passphrase for passwordless authentication.

  2. Display the public key.

    console
    $ cat ~/.ssh/sftpgo_key.pub
    

    Output:

    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGx... sftp-user
  3. In the SFTPGo web interface, navigate to Users, click Actions next to the target user, and select Edit.

  4. Locate the Public keys section.

  5. Paste the public key string into the text field.

  6. Click Save.

  7. Test key-based authentication from the client. Replace USERNAME with your SFTPGo username.

    console
    $ sftp -i ~/.ssh/sftpgo_key -P 2022 USERNAME@sftp.example.com
    

Enable Multi-Factor Authentication

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Expand the ACLs section and locate Require 2FA for.

  3. Select the protocols requiring two-factor authentication.

  4. Click Save.

    The user configures their authenticator app on next login via the WebClient portal.

Configure Storage Backends

SFTPGo supports local storage and S3-compatible object storage.

Configure Local Filesystem Storage

Local storage is the default backend. Files are stored under /srv/sftpgo/data/USERNAME/.

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Under File system, verify that Local disk is selected in the Storage dropdown.

  3. Set the Root directory to /srv/sftpgo/USERNAME, replacing USERNAME with the SFTP username.

  4. Click Save.

Configure S3-Compatible Object Storage

SFTPGo supports any S3-compatible storage service as a user backend, including MinIO and Vultr Object Storage.

  1. Gather the following credentials from your S3-compatible storage provider:

    • Endpoint URL (for example, https://ewr1.vultrobjects.com).
    • Access Key.
    • Secret Key.
    • Bucket name.
  2. In the SFTPGo web interface, navigate to Users, click Actions next to the target user, and select Edit.

  3. Under File system, select S3 (Compatible) from the Storage dropdown.

    SFTPGo File system section with S3 (Compatible) selected, showing Bucket, Region, Access Key, Access Secret, Endpoint, and path-style addressing fields

  4. Fill in the S3 backend fields:

    • Bucket: Enter your bucket name.
    • Region: Enter the region code (for example, ewr1).
    • Access Key: Enter your access key.
    • Access Secret: Enter your secret key.
    • Endpoint: Enter the full endpoint URL (for example, https://ewr1.vultrobjects.com).
  5. Enable Use path-style addressing for S3-compatible endpoints.

  6. Click Save.

  7. Create a test file on the client machine.

    console
    $ echo "Hello SFTPGo" > testfile.txt
    
  8. Connect via SFTP to verify the configuration. Replace USERNAME with your SFTPGo username and sftp.example.com with your configured domain.

    console
    $ sftp -P 2022 USERNAME@sftp.example.com
    
  9. Upload the test file.

    console
    sftp> put testfile.txt
    
  10. Verify that the file appears in the bucket.

    console
    sftp> ls
    
  11. Close the SFTP session.

    console
    sftp> exit
    

S3 Backend Limitations

S3-compatible backends have behavioral differences from local storage:

  • Resume uploads are disabled by default.
  • Symbolic links are not supported.
  • Directory rename operations are not atomic.
  • chmod and chown operations are silently ignored.

Set Up SFTP Access

SFTPGo runs SFTP on port 2022 by default and also supports FTP with TLS (FTP/S) and WebDAV for legacy clients and HTTP-based file access. Each protocol uses its own listener port and shares the same user accounts, authentication backends, and storage configuration.

Set Up Access Controls and Quotas

SFTPGo enforces quotas, bandwidth limits, IP restrictions, and per-directory permissions at the user level. Configure these controls to replicate Azure Storage SFTP access policies.

Configure User Quotas

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Expand the Disk quota and bandwidth limits section.

  3. Configure quota settings:

    • Quota size: Maximum storage allocation. The field accepts values with size suffixes (for example, 10 GB or 500 MB).
    • Quota files: Maximum number of files
  4. Click Save.

Configure Bandwidth Limits

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Expand the Disk quota and bandwidth limits section.

  3. Set bandwidth restrictions:

    • Bandwidth UL (KB/s): Maximum upload speed in KB/s (for example, 5120 for 5 MB/s)
    • Bandwidth DL (KB/s): Maximum download speed in KB/s (for example, 5120 for 5 MB/s)
  4. Click Save.

Configure IP Restrictions

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Expand the ACLs section and locate Allowed IP/Mask.

  3. Add permitted IP addresses or CIDR ranges:

    192.168.1.0/24
    10.0.0.0/8
  4. Optionally configure Denied IP/Mask to block specific addresses.

  5. Click Save.

Configure Directory Permissions

  1. Navigate to Users, click Actions next to the target user, and select Edit.

  2. Expand the ACLs section and under Per-directory permissions, configure access:

    • Click Add to create a permission entry
    • Specify the Path (for example, /uploads)
    • Select allowed operations: List, Download, Upload, Delete, Rename, Create directories
  3. Click Save.

Configure Event Notifications and Logging

Set up logging and event hooks to replace Azure Monitor integration.

Configure File Logging

  1. Create a logs directory for persistent log storage.

    console
    $ mkdir -p ~/sftpgo/logs
    
  2. Open docker-compose.yml to add logging configuration.

    console
    $ nano ~/sftpgo/docker-compose.yml
    
  3. Append the logs volume to the existing volumes: block under the sftpgo service:

    yaml
    - ./logs:/var/log/sftpgo
    
  4. Append the following logging environment variables to the existing environment: block under the sftpgo service:

    yaml
    - SFTPGO_LOG_FILE_PATH=/var/log/sftpgo/sftpgo.log
    - SFTPGO_LOG_MAX_SIZE=10
    - SFTPGO_LOG_MAX_BACKUPS=5
    - SFTPGO_LOG_MAX_AGE=28
    - SFTPGO_LOG_LEVEL=info
    

    Save and close the file.

  5. Apply the updated configuration.

    console
    $ docker compose up -d
    

Configure Event Hooks

SFTPGo supports HTTP webhooks for event notifications, replacing Azure Monitor alerts.

  1. Navigate to Event Manager, then click Actions in the left sidebar.

  2. Click Add to create a new action.

  3. Configure the action:

    • Name: Enter an action name (for example, webhook-action).
    • Type: Select HTTP.
    • Server URL: Enter your webhook URL.
    • Method: Select POST.
  4. Click Save.

  5. Click Rules in the left sidebar.

    SFTPGo Event Manager Rules page showing the rules table with Name, Status, Trigger, and Actions columns

  6. Click Add to create a new event rule.

  7. Configure the event trigger:

    • Name: Enter a descriptive name (for example, upload-notification).
    • Trigger: Select Filesystem events.
    • Fs events: Select upload.
  8. Under Actions, select the previously created action.

  9. Click Save.

Configure Syslog Integration

Forward logs to a centralized logging system as an alternative to Azure Monitor.

  1. Open docker-compose.yml and add syslog configuration. Replace SYSLOG-SERVER with your syslog server address.

    console
    $ nano ~/sftpgo/docker-compose.yml
    
  2. Append the following environment variables to the existing environment: block under the sftpgo service:

    yaml
    - SFTPGO_SYSLOG__ENABLED=true
    - SFTPGO_SYSLOG__ADDRESS=udp://SYSLOG-SERVER:514
    - SFTPGO_SYSLOG__FACILITY=local0
    

    Save and close the file.

  3. Apply the updated configuration.

    console
    $ docker compose up -d
    

Test SFTP Connections

Verify the deployment by testing file transfer operations.

Test with Command-Line SFTP Client

  1. Create a test file on the client machine.

    console
    $ echo "Hello SFTPGo" > testfile.txt
    
  2. Connect to the SFTP server. Replace USERNAME with your SFTPGo username.

    console
    $ sftp -P 2022 USERNAME@sftp.example.com
    
  3. Enter the password when prompted.

  4. List directory contents.

    console
    sftp> ls -la
    
  5. Upload the test file.

    console
    sftp> put testfile.txt
    
  6. Download the file to verify.

    console
    sftp> get testfile.txt /tmp/testfile-downloaded.txt
    
  7. Exit the session.

    console
    sftp> exit
    

Test with SSH Key Authentication

  1. Connect using your private key. Replace USERNAME with your SFTPGo username.

    console
    $ sftp -i ~/.ssh/sftpgo_key -P 2022 USERNAME@sftp.example.com
    
  2. Verify that the connection is established without a password prompt.

  3. Exit the session.

    console
    sftp> exit
    

Test FTP/S Connection

  1. Install an FTP client such as lftp.

    console
    $ sudo apt install lftp -y
    
  2. Connect with explicit TLS. Replace USERNAME with your FTP username.

    console
    $ lftp -u USERNAME -p 2121 ftp://sftp.example.com
    
  3. List files to verify the connection.

    console
    lftp> ls
    
  4. Exit the session.

    console
    lftp> exit
    

Migrate from Azure Storage SFTP to SFTPGo

Migrating from Azure Storage SFTP requires recreating user accounts in SFTPGo, transferring stored data to the new storage backend, and updating client connection settings to point to the new server.

User Migration

Export local user configurations from Azure Storage and recreate them in SFTPGo.

  1. List Azure Storage SFTP local users using the Azure CLI. Replace STORAGE-ACCOUNT with your storage account name and RESOURCE-GROUP with your resource group name.

    console
    $ az storage account local-user list --account-name STORAGE-ACCOUNT --resource-group RESOURCE-GROUP
    
  2. Export user details including SSH keys. Replace USERNAME with the local user name to export.

    console
    $ az storage account local-user show --account-name STORAGE-ACCOUNT --resource-group RESOURCE-GROUP --name USERNAME
    
  3. For each user, record:

    • Username
    • SSH public keys
    • Home directory (container and path)
    • Permission scope
  4. Generate an API access token using your SFTPGo admin credentials. Replace ADMIN-USERNAME and ADMIN-PASSWORD with your SFTPGo admin credentials and sftp.example.com with your configured domain.

    console
    $ curl -u ADMIN-USERNAME:ADMIN-PASSWORD https://sftp.example.com/api/v2/token
    

    The response contains an access_token value. Copy it for use in the next step. The token expires after 15 minutes.

  5. Create the user via the REST API. Replace ACCESS-TOKEN with the token from the previous step.

    console
    $ curl -X POST "https://sftp.example.com/api/v2/users" \
        -H "Authorization: Bearer ACCESS-TOKEN" \
        -H "Content-Type: application/json" \
        -d '{
          "username": "USERNAME",
          "password": "PASSWORD",
          "status": 1,
          "public_keys": ["SSH-PUBLIC-KEY"],
          "home_dir": "/srv/sftpgo/data/USERNAME",
          "permissions": {"/": ["*"]}
        }'
    

    Replace:

    • sftp.example.com with your configured domain.
    • USERNAME with the migrated SFTP username.
    • PASSWORD with a strong password for the user.
    • SSH-PUBLIC-KEY with the user's SSH public key string.

    The "status": 1 field activates the user account. Without it, the user is created in a disabled state and cannot log in.

Data Migration

Transfer data from Azure Blob Storage to the SFTPGo storage backend.

  1. If using Azure Blob as the SFTPGo backend, point users to the same container. No data migration is required.

  2. For local filesystem backend, download data using Azure CLI. Replace the placeholders with your storage account details.

    console
    $ az storage blob download-batch --account-name STORAGE-ACCOUNT --source CONTAINER-NAME --destination ~/sftpgo/data/USERNAME/
    
  3. Set correct ownership on downloaded files.

    console
    $ sudo chown -R 1000:1000 ~/sftpgo/data/
    

Authentication Migration

Convert Azure authentication methods to SFTPGo equivalents.

Azure Authentication SFTPGo Equivalent
SSH Public Keys Public Keys (direct migration)
Local User Passwords Password Authentication
Azure AD (Preview) LDAP/OIDC Plugin

For Azure AD integration, configure an external authentication hook that validates against your identity provider.

Client Configuration Updates

Update SFTP client applications with the new endpoint.

  1. Document the new connection parameters:

    • Host: sftp.example.com (your SFTPGo server)
    • Port: 2022 (SFTP)
    • Authentication: SSH key or password
    • Protocol: SFTP
  2. Distribute updated connection details to users.

  3. Update automated scripts and integrations.

  4. Test each client before disabling Azure Storage SFTP.

Things to Consider During Migration

Address Azure-specific features when migrating:

  • Hierarchical Namespace: Azure Storage SFTP requires HNS. SFTPGo simulates directories without this requirement, which may affect applications that depend on HNS behavior.

  • Container-Level Permissions: Azure assigns permissions per container. Map these to SFTPGo's per-directory permissions under the ACLs section.

  • Azure AD Authentication: If using Azure AD (preview), configure SFTPGo with an external authentication hook or LDAP plugin to integrate with your identity provider.

  • Storage Lifecycle Policies: SFTPGo does not manage Azure Blob lifecycle rules. Configure lifecycle policies directly in Azure Storage if continuing to use Azure Blob as the backend.

  • Azure Monitor Integration: Replace Azure Monitor logging with SFTPGo's built-in logging, syslog forwarding, or webhook integrations.

  • Managed SSH Host Keys: Export the SSH host key from SFTPGo (/var/lib/sftpgo/id_*) and distribute the fingerprint to clients to avoid host key warnings.

Conclusion

You have deployed SFTPGo as a self-hosted alternative to Azure Storage SFTP using Docker Compose. The setup includes SFTP protocol support, Azure Blob Storage backend integration, user authentication with SSH keys and passwords, and access controls matching Azure Storage SFTP capabilities. This configuration eliminates the $0.30/hour (~$220/month) charge while providing equivalent file transfer functionality. For additional features including plugins, clustering, and enterprise options, refer to the official SFTPGo documentation.

Comments