Local
The local backend serves a directory of the server’s file system, its
root (root). Each mount has its own subdirectory there, home_dir.
[[backends]]
name = "disque"
type = "local"
root = "/srv/sftp"
[[roles]]
name = "utilisateurs"
[[roles.mounts]]
backend = "disque"
home_dir = "/{username}"
create_home = true
acl = [{ path = "/", rights = ["read", "write", "list", "delete", "rename"], recursive = true }]
alice uploads /rapport.txt: the file is /srv/sftp/alice/rapport.txt.
The keys
All keys: Reference [[backends]] type = “local”;
common keys: Backends.
The root and symbolic links
No operation leaves the mount’s root + home_dir, whatever links are
there, including what the server does itself (in-flight file, lock, sweep).
A link to another mount’s home_dir leaves it just as much as a link
outside the root.
| Setting | A link within the mount | A link that leaves it |
|---|---|---|
follow_symlinks = false (default) | never followed | never followed |
follow_symlinks = true | followed if it stays under root + home_dir | never followed |
- A link is listed as a link (type
l;"is_symlink": truein REST), or, when followed, as its target. Deleting or renaming acts on the link. - With
hidden_stores, an upload onto a file link replaces the link; the target stays intact. - No door creates links: they come from another process or a restore.
- The root and its ancestors are trusted (a root through a link is followed): writable by the administrator only.
- On a shared volume (NFS…), mount the root
nosymfollow(Linux 5.10 and later).
Case of ACL paths
On a storage that ignores case (NTFS, APFS and HFS+ by default, SMB/CIFS,
ext4 or tmpfs casefold), the ACL compares folded paths: NFD, removal
of ignorable code points (U+200B…), full case folding
(straße = strasse), NFC.
| Setting | Comparison of ACL paths |
|---|---|
case_insensitive = true | folded |
case_insensitive = false | byte by byte, without normalization |
| key absent | a probe decides, at startup and at each roles reload |
The probe creates a lowercase file and looks for it in uppercase in
each directory where an entry resolves (folding is set per directory,
chattr +F): one folding directory makes the backend fold, an
inconclusive result counts as folding. A missing directory or one under
{username} is not probed, and a case-sensitive APFS volume stays
insensitive to normalization: when in doubt, case_insensitive = true.
Where the ACL folds, and on a Windows server, a short 8.3 name (PROTEG~1)
or one ending in . or a space is not a valid path: disable short names
(fsutil 8dot3name).
The common keys on a local backend
| Key | On a local backend |
|---|---|
home_dir (mount) | a subdirectory of root: /partenaire/in/x of a mount at /partenaire with home_dir = "/partenaires/acme" is /srv/sftp/partenaires/acme/in/x |
create_home (mount) | true: creates home_dir if missing, when the session opens, one level at a time, never through a link |
hidden_stores | a file being transferred next to the destination, published by rename |
stale_partials | the sweep of those files, on the file system’s clock |
cross_instance_reservation | a lock file next to the destination; false by default on Windows: one instance per root |
lock_prefix | the name of those locks |
The process acts under its own uid; file modes follow its umask.
On Linux 5.6 and later, the kernel enforces the confinement (openat2(2),
RESOLVE_BENEATH); without openat2, each component is opened
O_NOFOLLOW (reported once as INFO); on Windows, the parent is checked
just before the call.
Performance and limits
- A rename and the publication of an upload use
RENAME_NOREPLACE. Where the file system lacks it (NFS, FUSE including sshfs, 9p), they fall back torename(2): a concurrent overwrite is not detected there, and the audit of an upload that overwrites saysreplaced=unknown. - No
fsync: a success does not promise durability on disk. mkdircreates one level; the missing parents of an upload are created one by one, each judged by the ACL.- Deleting a tree is not counted: the audit says
removed=unknown.
What you will see
| When | Line |
|---|---|
| startup, case probe | INFO with backend, acl_paths = folded or exact |
create_home creates a directory | INFO created missing home directory, field home_dir |
| startup, sweep of leftovers | INFO stale in-flight files: ..., fields backend, grace_secs, age_check |