Sftpgo
YAML
services:
sftpgo:
image: "drakkan/sftpgo:v2-alpine"
# default user id
user: "1000"
restart: unless-stopped
# expose:
# # HTTP
# - "8080"
# # HTTPS
# - "443"
# # WebDav
# - "5007"
ports:
- 8080:8080
environment:
# These are the settings to access your db
SFTPGO_WEBDAVD__BINDINGS__0__PORT: 5007
SFTPGO_DATA_PROVIDER__DRIVER: "mysql"
SFTPGO_DATA_PROVIDER__NAME: "sftpgo"
SFTPGO_DATA_PROVIDER__HOST: "mysql"
SFTPGO_DATA_PROVIDER__PORT: 3306
SFTPGO_DATA_PROVIDER__USERNAME: "sftpgo"
SFTPGO_DATA_PROVIDER__PASSWORD: "password"
SFTPGO_COMMON_DEFENDER__ENABLED: "true"
SFTPGO_COMMON_DEFENDER__BAN_TIME: 15
SFTPGO_COMMON_DEFENDER__BAN_TIME_INCREMENT: 100
SFTPGO_COMMON_DEFENDER__THRESHOLD: 5
SFTPGO_COMMON_DEFENDER__OBSERVATION_TIME: 15
volumes:
- ./data:/srv/sftpgo
mysql:
image: mysql:8.0.41-bookworm
restart: always
environment:
MYSQL_DATABASE: "sftpgo"
MYSQL_USER: "sftpgo"
MYSQL_PASSWORD: "password"
MYSQL_ROOT_PASSWORD: "rootpassword"
volumes:
- ./database:/var/lib/mysql
Prod Setup
YAML
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "5"
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: sftpgo
POSTGRES_USER: sftpgo
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeMePg!}
TZ: Europe/Belgrade
volumes:
- ./postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sftpgo -d sftpgo || exit 1"]
interval: 10s
timeout: 5s
retries: 6
logging: *logging
sftpgo:
image: drakkan/sftpgo:v2.6.6
# match your SMB mount ownership for seamless writes
user: "1000:1000"
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
TZ: Europe/Belgrade
# --- Data provider: PostgreSQL (use separate fields) ---
SFTPGO_DATA_PROVIDER__DRIVER: "postgresql"
SFTPGO_DATA_PROVIDER__HOST: "postgres"
SFTPGO_DATA_PROVIDER__PORT: "5432"
SFTPGO_DATA_PROVIDER__NAME: "sftpgo" # DB name (not a file path)
SFTPGO_DATA_PROVIDER__USERNAME: "sftpgo"
SFTPGO_DATA_PROVIDER__PASSWORD: "${POSTGRES_PASSWORD}"
# --- Services/ports ---
SFTPGO_HTTPD__BIND_ADDR: "0.0.0.0"
SFTPGO_HTTPD__BIND_PORT: "8080"
SFTPGO_WEBDAVD__BIND_ADDR: "0.0.0.0"
SFTPGO_WEBDAVD__BIND_PORT: "8081"
SFTPGO_WEBDAVD__ENABLED: "true"
SFTPGO_SFTPD__BIND_ADDR: "0.0.0.0"
SFTPGO_SFTPD__BIND_PORT: "2022"
# Disable FTP/FTPS unless you need them
SFTPGO_FTPD__ENABLED: "false"
SFTPGO_FTPD__BIND_PORT: "2121"
SFTPGO_FTPSD__ENABLED: "false"
# Logging
SFTPGO_LOG__LEVEL: "info"
# Map ports like this if NPM runs on the **host**.
# If NPM is Dockerized, put NPM and this stack on a shared network and skip host binds.
ports:
# - "127.0.0.1:8080:8080" # Web/admin UI -> NPM
# - "127.0.0.1:8081:8081" # WebDAV -> NPM (optional)
- "2022:2022" # SFTP (direct, not via NPM)
volumes:
- ./local_data:/srv/sftpgo
# SFTPGo internal state (keys, web sessions, etc.)
- ./sftpgo:/var/lib/sftpgo
# Optional: drop a custom config file here if you want deep tuning later
# - ./config:/etc/sftpgo
# sensible hardening + healthcheck
security_opt:
- no-new-privileges:true
cap_drop: [ "ALL" ]
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz || exit 1"]
interval: 30s
timeout: 5s
retries: 5
logging: *logging
networks:
default:
external: true
name: core-net