Installation

sftproo ships as a single container image that runs the SFTP server, the web admin UI, and an optional backup service. This section walks through a self-hosted deployment with Docker Compose and the two cloud marketplace images.

Prerequisites

  • Docker and Docker Compose on the host
  • A server with at least 2 GB of RAM and 10 GB of free disk space (more if you plan to host large transfers)
  • TCP port 2222 (SFTP) and 8443 (web UI) reachable from your users
  • A domain name if you plan to terminate TLS with a public certificate; otherwise sftproo will generate a self-signed cert on first start

Quick Start with Docker Compose

1. Create a directory for sftproo and move into it:

mkdir /opt/sftproo
cd /opt/sftproo

2. Create a docker-compose.yml file. The snippet below is a minimal, security-sane starting point — each environment variable is explained in the Environment Variables section. Replace every change_me placeholder with a long random value before you start the stack:

services:
  sftproo:
    image: public.ecr.aws/solvedevops/sftproo:latest
    container_name: sftproo
    ports:
      - "2222:2222"   # SFTP
      - "8443:8443"   # Web UI (HTTPS)
    volumes:
      - ./data:/data
      - ./config:/etc/sftproo
    environment:
      - SFTPROO_HOST=0.0.0.0
      - SFTPROO_PORT=2222
      - SFTPROO_WEB_PORT=8443
      - SFTPROO_DB_HOST=mariadb
      - SFTPROO_DB_PORT=3306
      - SFTPROO_DB_NAME=sftproo
      - SFTPROO_DB_USER=sftproo
      - SFTPROO_DB_PASSWORD=change_me_db_password
      - SFTPROO_STORAGE_TYPE=local
      - SFTPROO_STORAGE_PATH=/data
      - SSH_HOST_KEY_PATH=/etc/sftproo/ssh_host_key
      - SFTPROO_CERT_FILE=/etc/sftproo/sftproo-server.crt
      - SFTPROO_KEY_FILE=/etc/sftproo/sftproo-server.pem
      - SFTPROO_SESSION_SECRET=change_me_long_random_hex
      - SFTPROO_ENCRYPTION_KEY=change_me_long_random_passphrase
      # Leave SFTPROO_DEFAULT_ADMIN_PASSWORD unset to have a random one-time
      # password printed to the container logs on first start.
    depends_on:
      - mariadb
    restart: unless-stopped

  mariadb:
    image: mariadb:10.11
    container_name: sftproo-db
    environment:
      - MYSQL_ROOT_PASSWORD=change_me_mariadb_root
      - MYSQL_DATABASE=sftproo
      - MYSQL_USER=sftproo
      - MYSQL_PASSWORD=change_me_db_password
    volumes:
      - ./database:/var/lib/mysql
    restart: unless-stopped

3. Start the services:

docker-compose up -d

4. Follow the logs to grab the one-time admin password, then open the web UI:

docker-compose logs -f sftproo
# Look for a line that begins with:
#   Password: ...   (shown only once)

# Then visit:
https://your-server:8443
Important: the first admin login is forced to choose a new password. If you set SFTPROO_DEFAULT_ADMIN_PASSWORD explicitly in the compose file the forced-change flow is skipped; the random-password path is safer unless you need a known value for automation.

AWS Marketplace Deployment

sftproo is available as a pre-configured AMI in the AWS Marketplace:

  1. Search for "sftproo" in the AWS Marketplace (or click here to get started).
  2. Pick an instance type — t3.small or larger is a reasonable default; size up if you expect heavy concurrent transfers.
  3. In the security group, allow inbound traffic on ports 22 (SSH), 2222 (SFTP) and 8443 (web UI) from the source ranges you trust.
  4. Launch the instance and wait for it to finish initialisation. SSH in to retrieve the generated admin credentials:
    ssh -i YOUR_SSH_KEY ubuntu@instance.ip.address
  5. Read /opt/default-sftproo-credentials.txt for the admin username and unique initial password:
    (username: admin, password: unique-password)
  6. Visit https://ip.add.re.ss:8443 and sign in with those credentials. You will be prompted to set a new password before anything else.

Azure Marketplace Deployment

Deploy sftproo from the Azure Marketplace:

  1. Search for "sftproo" in the Azure Marketplace (or click here to get started).
  2. Choose a VM size; B2s or larger is a reasonable default.
  3. Configure the network security group to allow inbound traffic on ports 22, 2222 and 8443.
  4. Launch the instance and SSH in with your Azure key pair:
    ssh -i YOUR_SSH_KEY azureuser@instance.ip.address
  5. Read /opt/default-sftproo-credentials.txt for the initial admin password.
  6. Visit https://ip.add.re.ss:8443, sign in, and set a new password when prompted.
Marketplace deployments come with a Professional license pre-applied — cloud backup, encrypted backups, and premium support are active without extra steps.

Environment Variables

sftproo is configured entirely through environment variables. The tables below group them by purpose. Variables marked required must be set for that feature to work; leaving them unset will either fail closed or fall back to an insecure default that the product will warn about in the logs.

Server & ports

Variable Purpose & why you set it Default
SFTPROO_HOST Bind address for the SFTP listener. Use 0.0.0.0 inside a container to accept connections on all interfaces. 0.0.0.0
SFTPROO_PORT TCP port for SFTP. 2222 avoids clashing with the host's own SSH daemon on 22. 2222
SFTPROO_WEB_PORT TCP port for the HTTPS admin UI. 8443

Database

sftproo stores all user, settings, license, and activity data in MariaDB / MySQL. These five variables are how the container finds the database at startup; if any of them is wrong the process aborts with a connection error.

Variable Purpose Required
SFTPROO_DB_HOSTHostname or IP of the database server. Use the docker-compose service name (e.g. mariadb) when running both containers in the same stack.Yes
SFTPROO_DB_PORTDatabase port.Yes (typically 3306)
SFTPROO_DB_NAMEDatabase / schema name.Yes
SFTPROO_DB_USERDatabase user.Yes
SFTPROO_DB_PASSWORDPassword for the database user.Yes

Storage & paths

Variable Purpose Default
SFTPROO_STORAGE_TYPE Where user files live. local is the only value supported at GA. S3 / Azure storage back-ends are on the roadmap and currently refuse to start. local
SFTPROO_STORAGE_PATH Directory inside the container that holds per-user home directories. Mount a persistent volume here. /data
SFTPROO_CONFIG_PATH Directory for generated configuration and the license file. Mount a persistent volume here so the license and SSH host key survive restarts. /etc/sftproo
SSH_HOST_KEY_PATH Path to the SFTP server's host key. If the file does not exist at startup, sftproo generates one; the generated key must be kept between restarts so clients do not see host-key-changed warnings. /etc/sftproo/ssh_host_key

TLS for the web UI

Variable Purpose Default
SFTPROO_CERT_FILE Path to the PEM-encoded TLS certificate for the admin UI. Mount a certificate from your CA or Let's Encrypt here; otherwise sftproo generates a self-signed cert that browsers will warn about. /etc/sftproo/sftproo-server.crt
SFTPROO_KEY_FILE Private key matching the certificate above. Keep this file readable only by the sftproo process. /etc/sftproo/sftproo-server.pem

Secrets & the first admin

Variable Purpose & why you set it Default / behaviour when unset
SFTPROO_SESSION_SECRET Signs the admin session cookie. Set this to a long, random, persistent value in production — when it is unset, sftproo generates a random one at every startup, which forces every admin to log in again on each restart. Random, regenerated on each start.
SFTPROO_ENCRYPTION_KEY Passphrase used to derive the key that encrypts stored cloud credentials (S3 secret keys, Azure account keys) in the database. Required to save S3 or Azure backup settings; the save call fails with a clear error when it is unset. Existing rows from older versions remain readable without it. Empty — cloud backup settings cannot be saved until set.
SFTPROO_DEFAULT_ADMIN_USER Username of the initial admin account created on first start. Only consulted on a truly empty database. admin
SFTPROO_DEFAULT_ADMIN_PASSWORD Initial password for the admin account. Leave unset to have sftproo generate a random password, print it once to the container logs, and force a password change on first login. Set an explicit value only when automation needs a known password. Random, shown once in the logs.
SFTPROO_DEFAULT_ADMIN_EMAIL Email recorded against the initial admin account. Does not send mail; used for display. admin@example.com
Treat SFTPROO_SESSION_SECRET and SFTPROO_ENCRYPTION_KEY the same way you would a database root password: generate them once with openssl rand -hex 32, store them in your secret manager, and do not commit them to source control.

Logging & diagnostics

sftproo uses GORM as its database layer. Out of the box GORM can print every SQL statement it issues; that is great for debugging, noisy in production, and can leak parameter values into your log stream. This variable controls that verbosity.

Variable Purpose & why you set it Default
SFTPROO_LOG_LEVEL Controls database query logging. One of:
  • silent — no GORM output at all.
  • error — only errors.
  • warn — errors plus slow queries. Recommended in production.
  • info — every SQL statement. Useful for short debugging sessions; do not leave enabled in production because query strings may contain sensitive values.
warn

Example — temporarily turn on full query logging to diagnose a problem, then turn it back off:

# Crank it up
SFTPROO_LOG_LEVEL=info docker-compose up -d sftproo
docker-compose logs -f sftproo

# Restore the default (warn) when you are done
unset SFTPROO_LOG_LEVEL
docker-compose up -d sftproo

In a persistent deployment, set the value in your .env file or docker-compose.yml:

environment:
  - SFTPROO_LOG_LEVEL=warn

First Login

On first start with a blank database, sftproo creates exactly one admin user. How it sets the password depends on whether SFTPROO_DEFAULT_ADMIN_PASSWORD is configured.

Self-hosted with random password (default)

  1. Start the stack: docker-compose up -d.
  2. Read the container logs: docker-compose logs sftproo. Look for a block similar to:
    Default admin user created with credentials:
    Username: admin
    Password: Hs5mPk3R-2pAu-fjVxQ9c7Yx
    WARNING: This password was generated randomly and is shown only once.
             You will be required to change it on first login.
  3. Open https://your-server:8443 and log in with that username and password.
  4. You will land on the change-password page. Choose a new password (minimum 12 characters) and continue.

Marketplace (AWS / Azure)

The AMI / VM image writes the initial credentials to /opt/default-sftproo-credentials.txt. SSH into the instance, read the file, then log in and change the password as above.

Automation

Set SFTPROO_DEFAULT_ADMIN_PASSWORD explicitly only when you are bootstrapping sftproo from Ansible / Terraform and cannot fish a password out of logs. In that case the forced-change flow is skipped, so choose a strong value and rotate it afterwards using the web UI.

The forced-change flow also triggers for any pre-existing admin that was still using the legacy default password admin123. If you are upgrading from an earlier release and that applies to you, the next login will redirect straight to the change-password page.

User Management

Creating users

To create a new user from the web UI:

  1. Go to Users in the admin panel.
  2. Click Add User.
  3. Fill in the form:
    • Username: unique, alphanumeric, no spaces — becomes the SFTP login.
    • Email: shown in the admin panel only.
    • Password: initial password for the user. The user can change it later from the web UI.
  4. Choose a role:
    • Admin: full access to the admin UI.
    • User: SFTP access only — no web UI beyond account settings.
  5. Click Create User. A per-user SSH key pair is generated; the private key is shown once and never stored on the server.

SSH keys

Every user can authenticate with a password, an SSH public key, or both. To manage keys:

  1. Open the user in the admin panel and click Manage SSH Keys.
  2. Either paste an existing OpenSSH public key, or generate a new pair — download the private key immediately because sftproo does not keep a copy.
  3. Save the changes.

Disabling users

Flipping the Active toggle off blocks the user from both SFTP and the web UI without deleting their home directory, so their files remain available if you need them for audit or later restoration.

Backup & Restore

What the backup contains

  • The MariaDB database (users, settings, licenses, activity logs)
  • The configuration directory (SFTPROO_CONFIG_PATH)
  • The SSH host key
  • Optionally, the user data directory (SFTPROO_STORAGE_PATH)

Scheduling backups

  1. Go to Settings → Backup.
  2. Enable Automated Backups.
  3. Pick a frequency and retention window.
  4. Choose a destination. Local is always available; S3 and Azure require a Professional license.

Encrypted backups

Backup encryption is a Professional feature. Each backup is sealed with AES-256-GCM under a key derived from your passphrase with argon2id and a per-backup random salt. A few things to know:

  • The passphrase must be at least 12 characters. Short passphrases are rejected when you save the settings.
  • Back up the passphrase yourself — it is not recoverable. Without it the backups cannot be decrypted.
  • Backups written by older versions remain decryptable — the decrypt_backup tool auto-detects the file format.

Restoring

If a backup is encrypted, first decrypt it with the bundled decrypt_backup tool (shipped inside the container at /app/tools/decrypt_backup):

decrypt_backup \
    -in  /backups/sftproo-2025-01-15.tar.gz.enc \
    -out /tmp/sftproo-2025-01-15.tar.gz \
    -password 'your-backup-passphrase'

Then stop the running service, extract the archive over the matching volumes, and start it again:

docker-compose stop sftproo
tar -xzf /tmp/sftproo-2025-01-15.tar.gz -C /opt/sftproo
docker-compose start sftproo
Tip: rehearse restores on a staging host at least once per quarter. A backup you have never restored is a guess, not a backup.

Security Settings

Access Control Lists (ACL)

Restrict who can reach sftproo by source IP. Go to Settings → Security → ACL to add IPv4 addresses or CIDR ranges, and toggle whitelist mode on to deny everything else. The host's own IPs are added automatically so you cannot accidentally lock out the server.

TLS / SSL

By default sftproo generates a self-signed certificate on first start. For production:

Option 1 — Let's Encrypt in front of sftproo: terminate TLS at a reverse proxy (Caddy, Traefik, nginx) and forward to 8443 over the container network.

Option 2 — Certificate files (recommended for fully self-contained deployments):

volumes:
  - ./certs/server.crt:/etc/sftproo/sftproo-server.crt:ro
  - ./certs/server.key:/etc/sftproo/sftproo-server.pem:ro

Forced password rotation

sftproo automatically flags any admin that is still using the old admin123 default, as well as the initial admin created from the random bootstrap password. Flagged accounts cannot reach any other page until they set a new password of at least 12 characters.

Audit logging

sftproo records:

  • Login attempts (successful and failed)
  • File uploads, downloads, renames, and deletions
  • User / role / settings changes
  • Backup runs and license changes

View them under Settings → Activity Logs or tail the container logs:

docker logs -f sftproo

Hardening checklist

  • Set SFTPROO_SESSION_SECRET and SFTPROO_ENCRYPTION_KEY to long random values and store them in a secret manager.
  • Replace the self-signed certificate with a real one.
  • Enable IP whitelisting if the admin UI is exposed publicly.
  • Prefer SSH-key authentication over passwords for SFTP users; disable password auth for sensitive accounts.
  • Monitor the activity log for repeated authentication failures.
  • Keep the container image up to date — security patches are only delivered in newer tags.

Getting Started (Users)

Welcome! This section is for people who have an sftproo account and want to move files in or out.

What your admin should give you

  • Server address: the hostname or IP of the SFTP server.
  • Port: usually 2222 (not the standard SSH port 22).
  • Username and an initial password, or an SSH private key file.
  • Web UI URL: something like https://server.example.com:8443, where you can change your own password and manage your SSH keys.

First connection

From the command line:

sftp -P 2222 username@server.example.com

You will be asked to accept the server's host key the first time; type yes to continue. You can also use any of the graphical clients listed in SFTP Clients — they often make things easier.

Changing your password

Log in at https://server.example.com:8443, open Change Password from the account menu in the top right, enter your current and new passwords, and save. If you were handed a temporary password by your admin, you may be redirected here automatically before anything else.

File Management

Basic SFTP commands

Once connected, use these commands to browse and transfer files:

Command Description Example
lsList files in the current directoryls -la
cdChange directorycd documents
pwdShow the current directorypwd
mkdirCreate a directorymkdir newfolder
putUpload a fileput localfile.txt
getDownload a fileget remotefile.txt
rmDelete a filerm oldfile.txt
rmdirDelete an empty directoryrmdir oldfolder
renameRename a file or directoryrename old.txt new.txt

Batch transfers

# Upload all .pdf files
put *.pdf

# Download a whole directory
get -r documents/

# Upload a whole directory
put -r local_folder/

Resuming interrupted transfers

# Resume an upload
reput largefile.zip

# Resume a download
reget largefile.zip

SSH Key Management

Generate a key pair

Linux / macOS:

ssh-keygen -t ed25519 -f ~/.ssh/sftproo_key -C "your_email@example.com"

Windows (PowerShell):

ssh-keygen -t ed25519 -f $HOME\.ssh\sftproo_key -C "your_email@example.com"

Add the public key

Option 1 — via the web UI:

  1. Log in to the web UI.
  2. Open Profile → SSH Keys.
  3. Click Add SSH Key.
  4. Paste the contents of sftproo_key.pub, give it a descriptive name, and save.

Option 2 — ask your administrator to add the public key for you.

Connect with the key

sftp -P 2222 -i ~/.ssh/sftproo_key username@server.example.com

SSH agent

Avoid typing -i every time by loading the key into your SSH agent:

eval $(ssh-agent)
ssh-add ~/.ssh/sftproo_key

# Now connect without specifying the key
sftp -P 2222 username@server.example.com

SFTP Clients

Graphical clients are usually friendlier than the command line. These all speak standard SFTP and work with sftproo out of the box.

Windows

  • WinSCP (free) — download from winscp.net. Pick SFTP as the protocol, enter the server and port 2222, and supply your username / password. To use a key, go to Advanced → SSH → Authentication.
  • FileZilla (free) — download from filezilla-project.org. Use sftp://server.example.com as the host and set the port to 2222.

macOS

  • Cyberduck (free) — download from cyberduck.io. Choose SFTP, enter the server and port 2222, and attach your key if needed.
  • Transmit (paid) — polished macOS experience with sync and automatic uploads.

Linux

  • FileZilla — available in most package managers.
  • Nautilus / Dolphin — built-in file managers. Use the address sftp://username@server:2222.

Mobile

  • iOS: FTPManager, Secure ShellFish.
  • Android: Total Commander, AndFTP.

Troubleshooting

Connection issues

Connection refused

  • Confirm the server address and port — sftproo listens on 2222, not the OS's SSH port 22.
  • Check for a firewall between you and the server blocking that port.
  • Ask your admin whether the service is up.

Authentication failed

  • Usernames are case-sensitive.
  • If you were given a temporary password, it may have been single-use — reset it from the web UI.
  • If you use key auth, point your client at the private key file explicitly, and make sure the public key is on file for your account.
  • Your source IP may not be whitelisted — ask your admin.

Permission denied

  • You are restricted to your own home directory; paths like ../ outside that root are rejected.
  • Check file permissions with ls -la before trying to overwrite.

Transfer issues

Slow transfers

  • Test your raw upload speed to the same host with iperf3 if possible — SFTP cannot go faster than the network beneath it.
  • Large files: let them run to completion instead of restarting; use reput / reget to resume rather than repeat.

Incomplete transfers

  • Use reput / reget to resume instead of restarting.
  • Check you have not exceeded your storage quota.

Still stuck?

  1. Capture the exact error message from your client.
  2. Send it and the steps to reproduce to your administrator, or open a ticket from the Contact page.

Licensing & Upgrades

sftproo is free to run for SFTP and local storage. A Professional license unlocks the paid features below. Licenses are cryptographically signed and validated locally — no call-home is required.

What a license unlocks

Feature What it does Plan
Backup to S3 Ship scheduled and manual backups to an AWS S3 bucket instead of (or in addition to) local disk. Professional
Backup to Azure Ship backups to an Azure Blob Storage container. Professional
Encrypted backups Seal each backup with AES-256-GCM under a passphrase you choose; the backup is unreadable without it, even if the storage bucket is compromised. Professional
24/7 support Priority email and ticket response from the sftproo team. Professional

If you try to enable a licensed feature on a free deployment, sftproo rejects the change and records the attempt in the activity log.

Getting a License

There are two routes to a Professional license:

1. Cloud Marketplace (recommended)

Launching sftproo from the AWS Marketplace or Azure Marketplace includes a Professional license that is applied on first boot. Billing is metered through your cloud account — no separate invoice from us. This is the simplest path if your organisation already procures software through AWS or Azure.

2. Buy a license directly

If you self-host on your own hardware, in a different cloud, or in an air-gapped environment, you can buy a license directly from us:

  1. Visit the Pricing section for the current plan.
  2. Reach us through the Contact page with your company name and expected deployment size. We issue an invoice and, on payment, email you a signed license key.
  3. Install the key on your sftproo instance using one of the methods below.
Licenses are perpetual — there is no expiry built into the key. Upgrades to new major versions may require a renewed key; we will contact you before that happens.

Installing a License

Once you have a license key, apply it one of two ways.

Via the web UI

  1. Log in to the admin UI.
  2. Open License from the sidebar.
  3. Paste the license key into the form and click Update License.
  4. The page refreshes and shows which features are now active.

Via the filesystem (air-gapped / immutable deployments)

If the web UI is not reachable, or you want the license in place before the process starts:

# Drop the key into the config volume
echo 'YOUR-BASE32-LICENSE-KEY' > /etc/sftproo/license_key.txt
chmod 600 /etc/sftproo/license_key.txt

# Restart the container so it picks it up
docker-compose restart sftproo

On startup, sftproo loads the file, verifies the signature against the compiled-in public key, and enables the licensed features.

Replacing a license

Uploading a new key from the License page overwrites the previous one. The activity log records every license change so you can audit when a feature set changed and who changed it.

If the license key is malformed or the signature does not verify, sftproo leaves the existing license in place and reports the error — you will not accidentally downgrade a working instance.