Deploying SFTPGo as an Azure Storage SFTP Alternative on Linux

작성자

카테고리:

← 피드로
DEV Community · Sanskriti Harmukh · 2026-07-08 개발(SW)

Azure Storage SFTP is Microsoft’s managed file transfer service on top of Azure Blob Storage, convenient, but billed continuously per endpoint (roughly $0.30/hour, ~$220/month) and tied to Azure AD. SFTPGo is an open-source file transfer server offering SFTP, FTP/S, and WebDAV with pluggable storage backends (local disk, Azure Blob, S3-compatible, GCS) and no per-endpoint charge. This guide deploys SFTPGo with Docker Compose and Traefik, sets up user auth (password + SSH key + 2FA), connects S3-compatible object storage, and covers the migration path from Azure Storage SFTP. By the end, you’ll have a self-hosted file transfer server with the same capabilities at zero endpoint cost.

Azure Storage SFTP → SFTPGo Mapping

Azure Storage SFTP SFTPGo Equivalent Notes SFTP Endpoint SFTPGo SFTP Server Configurable port, default 2022 Azure Blob Storage Azure Blob backend Native support; point at the same container, no migration needed Azure AD Authentication LDAP/OIDC plugin External identity provider via plugin Local Users Web UI / REST API user management Hierarchical Namespace Virtual directories No HNS requirement Azure Monitor Built-in logging + webhooks/syslog

Prerequisite: Linux server with Docker + Compose, a DNS A record for your domain, and (if migrating) an existing Azure Storage account with SFTP enabled plus the Azure CLI installed locally.

Deploy with Docker Compose

1. Create the project directories:

$ mkdir -p ~/sftpgo/{data,config}
$ cd ~/sftpgo

Enter fullscreen mode Exit fullscreen mode

2. Create the environment file:

$ nano .env

Enter fullscreen mode Exit fullscreen mode

DOMAIN=sftp.example.com
[email protected]

Enter fullscreen mode Exit fullscreen mode

3. Create the Compose manifest:

$ nano docker-compose.yml

Enter fullscreen mode Exit fullscreen mode

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:

Enter fullscreen mode Exit fullscreen mode

Traefik terminates TLS on 80/443 for the admin UI; SFTP/FTP/S/WebDAV listen directly on 2022/2121/10080. Port 8080 (the admin UI’s internal port) is never exposed to the host — Traefik proxies to it over the Docker network.

4. Start the stack:

$ docker compose up -d
$ docker compose ps
$ docker compose logs

Enter fullscreen mode Exit fullscreen mode

Initial Admin Setup

  1. Open https://sftp.example.com/web/admin.
  2. Create the administrator: username, strong password, confirm, Create admin and Sign in.
  3. Review Server Manager → Configurations — check the SFTP, ACME, and SMTP sections match your requirements.

Create a User and Configure Authentication

1. Password auth: Users → Add — username, password, Status: Active, File system: Local disk, Root directory: /srv/sftpgo/USERNAME. Save.

2. SSH key auth (passwordless, mirrors Azure’s SSH key support):

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

Enter fullscreen mode Exit fullscreen mode

Paste the public key into Users → Edit → Public keys, then test:

$ sftp -i ~/.ssh/sftpgo_key -P 2022 [email protected]

Enter fullscreen mode Exit fullscreen mode

3. 2FA: Users → Edit → ACLs → Require 2FA for — select the protocols to gate. The user sets up their authenticator app on next WebClient login.

Connect S3-Compatible Object Storage

SFTPGo supports Azure Blob directly, but also any S3-compatible provider — useful if you’re consolidating storage away from Azure.

  1. Gather your endpoint URL, access key, secret key, and bucket name from the provider.
  2. Users → Edit → File system → Storage: S3 (Compatible).
  3. Fill in Bucket, Region, Access Key, Access Secret, Endpoint (full URL).
  4. Enable Use path-style addressing.
  5. Save, then verify:
$ echo "Hello SFTPGo" > testfile.txt
$ sftp -P 2022 [email protected]
sftp> put testfile.txt
sftp> ls
sftp> exit

Enter fullscreen mode Exit fullscreen mode

S3 backend limitations: resume uploads disabled, no symlinks, non-atomic directory rename, chmod/chown silently ignored.

Test All Protocols

$ echo "Hello SFTPGo" > testfile.txt
$ sftp -P 2022 [email protected]
sftp> put testfile.txt
sftp> get testfile.txt /tmp/testfile-downloaded.txt
sftp> exit

$ sftp -i ~/.ssh/sftpgo_key -P 2022 [email protected]

$ sudo apt install lftp -y
$ lftp -u USERNAME -p 2121 ftp://sftp.example.com
lftp> ls
lftp> exit

Enter fullscreen mode Exit fullscreen mode

Migrate from Azure Storage SFTP

Export Users

$ az storage account local-user list --account-name STORAGE_ACCOUNT --resource-group RESOURCE_GROUP
$ az storage account local-user show --account-name STORAGE_ACCOUNT --resource-group RESOURCE_GROUP --name USERNAME

Enter fullscreen mode Exit fullscreen mode

Record username, SSH public keys, home directory (container + path), and permission scope for each user.

Recreate Users in SFTPGo

$ curl -u ADMIN_USERNAME:ADMIN_PASSWORD https://sftp.example.com/api/v2/token

Enter fullscreen mode Exit fullscreen mode

Copy the access_token — it expires in 15 minutes.

$ 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": {"/": ["*"]}
    }'

Enter fullscreen mode Exit fullscreen mode

"status": 1 is required — without it the account is created disabled.

Migrate Data

If SFTPGo will use Azure Blob as its own backend, just point users at the same container — no data transfer needed. For local-disk backends, pull the data down:

$ az storage blob download-batch --account-name STORAGE_ACCOUNT --source CONTAINER_NAME --destination ~/sftpgo/data/USERNAME/
$ sudo chown -R 1000:1000 ~/sftpgo/data/

Enter fullscreen mode Exit fullscreen mode

Map Authentication Methods

Azure Method SFTPGo Equivalent SSH Public Keys Public Keys (direct) Local User Passwords Password Authentication Azure AD (Preview) LDAP/OIDC plugin, or external auth hook

Update Clients

Document the new endpoint (sftp.example.com, port 2022, SSH key or password) and roll it out before decommissioning the Azure endpoint. Export SFTPGo’s SSH host key (/var/lib/sftpgo/id_*) and share the fingerprint so clients don’t hit host-key warnings.

Things to Watch

  • Hierarchical Namespace: Azure Storage SFTP requires HNS; SFTPGo simulates directories without it — check any app that depends on HNS-specific behavior.
  • Container-level permissions: map to SFTPGo’s per-directory ACLs.
  • Lifecycle policies: SFTPGo doesn’t manage Azure Blob lifecycle rules — keep configuring those in Azure if you stay on the Blob backend.
  • Azure Monitor: replace with SFTPGo’s logging, syslog, or webhook integrations.

Next Steps

SFTPGo is running as a self-hosted Azure Storage SFTP replacement with zero per-endpoint charge. From here you can:

  • Enable the Azure Blob backend directly if you want to keep data in place
  • Set quotas, bandwidth limits, and IP ACLs per user under Edit → Disk quota / ACLs
  • Wire event hooks (webhooks/syslog) to replace Azure Monitor alerting

For the full guide with additional tips, visit the original article on Vultr Docs.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다