WebDAV server
filex serves every configured storage over WebDAV at:
https://<your-filex>/dav/<storage-name>/<path>The first segment also accepts the storage's uid — assigned once, never changed — which is what a permanent mount should be given, because renaming the storage re-addresses the name and every mount written against it answers 404. See STORAGE.md.
Mount your filex drives in Windows Explorer, macOS Finder, or any WebDAV client (rclone, Cyberduck, WinSCP, davfs2, Kodi, Documents by Readdle, …) — uploads, downloads, rename/move, delete and folder creation all work, and every change is mirrored into the filex index (listings, search, thumbnails) just like an upload through the web UI.
Enable / disable
The WebDAV surface is on by default. To turn it off entirely set:
FILEX_DAV=0(or dav.enabled: false in config.yaml). The whole /dav subtree then answers 404. Class-2 locking (LOCK/UNLOCK) is always on when the server is enabled — Windows refuses to mount a read-write drive without it — and the locks are durable: they are written to <data>/dav/dav-locks.json and read back at boot, so a deploy no longer silently forgets every lock it was holding.
Authentication
Every request needs HTTP Basic credentials:
| Field | Value |
|---|---|
| Username | your filex account e-mail |
| Password | your account password, or a filex API token |
Both secrets are accepted in the same password field — filex first tries the account password, then falls back to interpreting the value as an API token (mint one under API / MCP in the admin UI, or — for any account — from the file explorer's navigation panel under Connections → API keys). Failures return 401 with WWW-Authenticate: Basic realm="filex".
⚠ The API keys entry is missing when the explorer is an embed proxied with one shared app token — those credentials belong to a person, and an app token is not one (MCP.md). Sign in to filex directly, or ask an admin to mint the token at POST /api/admin/ai-tokens.
Notes:
- Use HTTPS. Basic auth sends the secret with every request; only expose
/davbehind TLS (Windows additionally refuses Basic over plain HTTP by default). - Accounts with TOTP/2FA enabled cannot use their password here (Basic auth has no second-factor slot). Mint an API token and use that instead — this is also the recommended setup for any always-on mount.
- API tokens are honored with their verb scopes:
readcovers browsing and downloads,writecovers uploads/mkdir/move/copy/locks,deletecovers deletes. A token with no scopes grants everything its user may do. - Tokens carrying a
root:confinement scope are rejected on/dav— the WebDAV tree has no confinement middleware, so accepting a subtree-limited token would widen its reach. Use an unconfined token (or RBAC grants) for WebDAV.
Connecting
💡 filex generates this page filled in. Everything below is also available inside the app with your real host, your storage name and your own username already substituted, plus a copy button per command:
- the file explorer's navigation panel → How to connect — the same entry on every surface that draws the panel, for every signed-in user;
- admins also reach it from Connections in the admin sidebar.
Both routes render the same component from
@brftech/filex-core, so they cannot drift apart from each other — but they can drift from this file. A correction here belongs inpackages/core/src/lib/connectionGuides.tstoo, and the other way round.
Windows (map network drive)
- Open File Explorer → right-click This PC → Map network drive…
- Pick a drive letter, and as the folder enter:
https://fm.example.com/dav/(or a single storage:https://fm.example.com/dav/depo/) - Check Connect using different credentials, then sign in with your e-mail + password/token as above.
Command-line equivalent:
net use Z: "https://fm.example.com/dav/" /user:you@example.com <password-or-token> /persistent:yesTips — and Windows has three built-in limits that will look like filex bugs if you do not know about them. All three live under HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters, and the WebClient service must be restarted after any change (net stop webclient && net start webclient).
Transfers stop at ~47.7 MB.
FileSizeLimitInBytesdefaults to 50,000,000 bytes, not 4 GB — 4 GB (0xFFFFFFFF) is the largest value you may set, not the default. Raise it with:batreg add "HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters" /v FileSizeLimitInBytes /t REG_DWORD /d 4294967295 /fFolders with roughly a thousand files fail to open, often reported as "Disk is not formatted" or error 31.
FileAttributesLimitInBytesdefaults to 1,000,000 bytes, which is the total size of the properties returned for one collection — about 1,000 entries. See Microsoft KB 912152.batreg add "HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters" /v FileAttributesLimitInBytes /t REG_DWORD /d 20000000 /fHTTPS is mandatory.
BasicAuthLeveldefaults to1, meaning "Basic authentication over SSL only" — over plainhttp://Windows silently refuses to send your credentials and the mount fails with no useful message. Do not set it to2; use TLS.The mapped drive will not survive a sign-out. Since Windows 7, Basic authentication credentials cannot be persisted by Credential Manager — this is by design (KB 2673544), and
/persistent:yesdoes not change it. Re-runnet usefrom a logon script if you need the drive back automatically.If mounting fails at all, make sure the WebClient service is running (
sc config WebClient start= auto && net start WebClient). On Windows Server it ships only with the WebDAV Redirector feature installed.A slow first connection is usually proxy auto-detection: untick Automatically detect settings in Internet Options → Connections → LAN settings.
macOS (Finder)
- Finder → Go → Connect to Server… (⌘K)
- Enter
https://fm.example.com/dav/and connect. - Authenticate with your e-mail + password/token.
The drive appears under Locations; each storage is a top-level folder.
rclone
# ~/.config/rclone/rclone.conf
[filex]
type = webdav
url = https://fm.example.com/dav
vendor = other
user = you@example.com
pass = <output of: rclone obscure "your-password-or-token">rclone lsd filex: # list storages
rclone lsl filex:depo # list one storage
rclone copy ./local filex:depo/backup # upload a tree
rclone mount filex: /mnt/filex # FUSE mount (Linux/macOS)Linux (davfs2 / GNOME / KDE)
sudo mount -t davfs https://fm.example.com/dav/ /mnt/filex
# or in GNOME Files / Dolphin: davs://fm.example.com/dav/Permissions
WebDAV enforces exactly the same authorization model as the web UI:
- The
/dav/root lists only the storages you may see. On an RBAC-enabled storage that means: at least one grant. - On RBAC storages, per-folder/file grants apply:
viewercan browse and download,editor/ownercan also write. Paths outside your grants answer 404 (not 403), so the tree never leaks what exists. - Read-only storages and grant levels below editor make every mutation (
PUT,DELETE,MKCOL,MOVE,COPY,LOCK) return 403. - Admin accounts see and write everything (subject only to the storage read-only flag).
Limits & behavior notes
DELETE goes to the trash, exactly like the web UI. A
DELETE— of a file or of a whole collection — renames the object into the hidden.filex-trash/bucket and flags the node row; the item then appears in the trash listing and can be restored, and it is only destroyed for good when the retention window expires or an admin empties the trash. See TRASH-VERSIONING.md.- A collection goes in as one restorable unit: restoring the folder brings its whole subtree back with it.
- Trashed bytes still count against the owner's quota until they are purged — the same rule the web UI follows. Deleting over WebDAV does not free space; emptying the trash does.
- The only way a WebDAV delete destroys data outright is a storage backend that supports neither move nor copy, since there is then no way to preserve the bytes. None of the shipped drivers (local, S3, SFTP, FTP, SMB, WebDAV) are in that category. When it does happen the item is not placed in the trash, so nothing offers a restore that could not work, and the emitted event is
file.deletedrather thanfile.trashed.
This changed in the release that added
trash.Put. Earlier documentation described WebDAVDELETEas permanent. Treat a sync client's delete as recoverable, but note the flip side: a largerclone sync --deleterun fills the trash rather than freeing space.Cross-storage MOVE is not supported (drivers can't rename across backends) — the server answers
502; do COPY + DELETE instead. COPY across storages works (it streams through the server).Uploads are spooled server-side and written to the backing driver as a whole object on close — very large files need matching temp-dir space on the filex host.
Locks are persisted to disk (
<data>/dav/dav-locks.json) and survive a restart. ⚠ They are still per node: the file lives under that instance's data directory, so replicas do not share them. If the directory cannot be written, filex logsdav: locks are memory-onlyand falls back to the old in-memory behaviour rather than refusing to serve/dav. They exist to satisfy class-2 clients (Windows, Office); filex itself does not arbitrate concurrent edits beyond them.The filex-internal buckets (
.filex-trash,.versions,.thumbs) are hidden and unreachable over WebDAV.Changes made over WebDAV are indexed best-effort right away (node cache, search, thumbnails); if anything hiccups, the storage's scheduled sync run reconciles later.
A
PUTalso announces itself on the realtime socket, so a browser with that folder open sees the file appear (measured at 21 ms from the write). ⚠ Before v0.34.0 the whole/davsurface was silent: the row and the index were correct, nothing was broadcast, and an open explorer — which does not poll while its socket is healthy — never showed the file at all (REALTIME.md).⚠ A
PUTover an existing path emitsfile.updated; aPUTthat creates a file emitsfile.uploaded. Until v0.34.0 both werefile.uploaded, so a webhook that wanted only new arrivals could not have one (NOTIFICATIONS.md).⚠ A
PUTthat replaces a file over WebDAV does take a version snapshot first; the same operation over SFTP, FTPS or NFS does not. See TRASH-VERSIONING.md.Multi-tenant installs:
/davis tenant-scoped. The scope comes from the authenticated user's provider — not the request Host — so it matches what the JSON API and the web UI apply. A caller sees only their own provider's storages in the root, and any path under another provider's storage answers404(a foreign storage is indistinguishable from one that isn't there). Admins of the supertenant provider stay confine-exempt and see everything;role: adminon a regular tenant means admin of that tenant. Suspended-tenant users are refused at login.Before this,
/davresolved storages globally by name, so any tenant admin could list, read, write and permanently delete every other tenant's files.
