siftp

Users and access

Where users come from

SourceManaged byDurable
[[users]] in the config fileYou, in the fileYes; read-only through the API
User store ([server].user_store)Admin API and MCPYes; atomic writes, survives restart and crash
LDAPYour directorySession only; nothing is stored

Lookup order at login: config file, then store, then LDAP.

Permissions

BitAllows
rDownload, SFTP read, WebDAV GET
wUpload, SFTP write, SETSTAT, MFMT, symlinks
dDelete files and directories
nRename (needed on both ends)
mCreate directories
lList, stat, WebDAV PROPFIND

A missing bit is permission_denied before any file is touched.

Groups and directory rules

[[groups]]
name = "staff"
permissions = "rwdnml"

[[groups.directories]]
path = "/archive"
permissions = "rl"

[[users]]
name = "carol"
password_hash = "$argon2id$..."
groups = ["staff"]

[[users.directories]]
path = "/incoming"
permissions = "wl"

SSH keys

ssh_public_keys = [
  'expiry-time="20271231" ssh-ed25519 AAAAC3... laptop',
  "no-pty ecdsa-sha2-nistp256 AAAAE2... ci",
]

Passwords

curl -X POST -H "Authorization: Bearer $SIFTP_ADMIN_TOKEN" \
  http://127.0.0.1:8080/api/v1/users/bob/password
# {"name":"bob","generated":true,"password":"Xk4...","password_set_unix":1791849600}

Without a body a 24-character password is generated and shown once. With {"password":"..."} the given one is set.

Login protection

SettingDefaultEffect
max_failed_logins / ban_window_secs5 / 600Failures from one IP in the window ban it
ban_duration_secs900Ban length; covers every listener and the admin API
max_connections / max_connections_per_ip512 / 32Shared by FTP, FTPS, SFTP, WebDAV
max_sessions (per user)unlimitedConcurrent logins per user

Wrong admin or MCP tokens count as failed logins.

LDAP

[ldap]
url = "ldaps://ldap.example.com"
bind_dn = "cn=siftp,ou=services,dc=example,dc=com"
bind_password = "${ENV:SIFTP_LDAP_PASSWORD}"
base_dn = "ou=people,dc=example,dc=com"
user_filter = "(uid={user})"
group_attribute = "memberOf"
require_group = true

[ldap.group_map]
"cn=ftp-staff,ou=groups,dc=example,dc=com" = "staff"