CraftFileGate
CraftFileGate is a file server: an SFTP client, an HTTP script or a browser
puts files on it and takes files from it, and the server stores them on one
or more storages. It replaces a classic SFTP server (ProFTPD, OpenSSH
internal-sftp) when the files do not all live on a local disk, or when the
accounts come from an identity provider.
What it does
| Need | Answer |
|---|---|
| Put and take files | SFTP, REST file API, web file explorer |
| Store the files | local disk, upstream SFTP server, S3 and compatibles, HDFS via Knox (read only) |
| Authenticate | password, SSH public key, JWT token (secret, public key or JWKS) |
| Grant rights | roles, which mount storages and grant rights on them by path; refusal by default |
| Monitor | audit trail, JSON logs, Prometheus metrics, OpenTelemetry traces |
| Administer | admin API and web console: sessions, bans, configuration in force |
| Deploy | a static binary, Docker images, a Helm chart |
The words of this guide
| Word | Meaning |
|---|---|
| backend | a named storage, described in [[backends]] |
| role | a set of mounts; a user receives one or more |
| mount | a backend seen by the user at a path (mount_path), starting from a subdirectory (home_dir), with its ACL |
| ACL | the rights (read, write, list, delete, rename) by path, within a mount |
| door | a way in: SFTP, REST API, file explorer, admin console |
The chapter Users, roles and mounts explains them with examples.
Quick start
A server on a local disk, a user alice who sees only her directory.
1. Generate a host key
ssh-keygen -t ed25519 -f /etc/craft-file-gate/host_ed25519 -N ""
A key listed in host_keys but missing refuses startup.
2. Write the configuration
Create /etc/craft-file-gate/config.toml:
#:schema ./config.schema.json
[server]
shutdown_grace_period_secs = 30
# max_sessions_per_user = 10 # optional, unlimited by default
[sftp]
listen = "0.0.0.0:2222"
host_keys = ["/etc/craft-file-gate/host_ed25519"]
# login_grace_secs = 120 # unauthenticated connection cut after this (0 = never)
[auth]
jwt_sentinel_username = "jwt"
timeout_secs = 5
# roles_file = "/etc/craft-file-gate/roles.toml" # optional, otherwise inline [[roles]]
# authz_base_url = "https://authz.internal" # optional, remote mapping service
[auth.jwt]
secret = "changez-moi-en-production"
# public_key_file = "/etc/craft-file-gate/jwt_public.pem" # alternative to the secret
# jwks_url = "https://idp.interne/.well-known/jwks.json" # alternative: identity provider keys
# jwks_refresh_interval_secs = 3600 # default, minimum 1
# username_path = "/sub" # default
# authorities_path = "/groups" # default
[auth.methods]
jwt = { enabled = true }
# Password and public key are proofs of the local store, not separate
# methods: you declare them under `local`.
local = { enabled = true, password = true, pubkey = true }
[admin]
listen = "127.0.0.1:8080"
bearer_token = "changez-moi-en-production"
[log]
level = "info"
format = "json"
# ── Storage and rights ──
[[backends]]
name = "local"
type = "local"
root = "/srv/sftp"
[[roles]]
name = "utilisateurs"
[[roles.mounts]]
backend = "local"
home_dir = "/{username}" # alice sees /srv/sftp/alice as her root /
create_home = true
[[roles.mounts.acl]]
path = "/"
rights = ["read", "write", "list", "delete", "rename"]
recursive = true
# ── Local users ──
[[users]]
username = "alice"
# password: changez-moi-en-production
password_hash = "$argon2id$v=19$m=19456,t=2,p=1$QzIrOEdtBZI4UL4ddXDbkg$yudDYsZSLamFZHWeKlFpFWtkP4kX6ALV8GNKs3pEXBk"
# authorized_keys = ["ssh-ed25519 AAAA... alice@poste"]
authorities = ["utilisateurs"]
The JWT secret, the admin token and alice’s password (changez-moi-en-production) are public. The server starts with them, but emits one WARN per example value still in place. To replace alice’s [[users]] block:
echo -n "mot-de-passe" | craft-file-gate hash-password --user alice
The process must be able to write to /srv/sftp: create_home creates alice/ there at her first login.
3. Start the server
craft-file-gate --config /etc/craft-file-gate/config.toml
For Docker and Kubernetes, see the guide (“Operating”).
4. Connect
sftp -P 2222 alice@votre-serveur
ls shows the content of /srv/sftp/alice, and nothing above it.
What next
| To | Read |
|---|---|
| give everyone what they should see | Users, roles and mounts, Recipes |
| connect S3 or an upstream SFTP server | Backends |
| connect an identity provider | Authentication |
| deploy in a container | Docker, Kubernetes |
| understand a refusal | Troubleshooting, Audit |
| look up a key | Configuration reference |