Repository navigation
v0.48.1
filex v0.48.1
Self-hosted file manager — Go single binary + multi-framework frontend.
Download a binary below, or pull a Docker image:
docker pull ghcr.io/brf-tech/filex:slim-v0.48.1
docker pull ghcr.io/brf-tech/filex:full-v0.48.1What changed
0.48.0 was tagged but its release run failed a test (where the draft
close question put the focus, now fixed); nothing was published — 0.48.1
carries it.
Apps can bring an interface of their own, a new document stays a draft until
its first save, encrypted folders can hide their names too and be made from a
folder you already have — or from a single file — and the desktop app gets the
notification bell and the account menu in its window. Every newer version of
an app now waits for an administrator, and the iframe converter is gone.
⚠ Nothing updates itself any more (Changed): 0.47 installed
a newer version of an app by itself when it asked for no new permission.
Now every version waits for an administrator's Review update; the
per-app automatic-update switch is gone andPATCH …/app-plugins/{id}with
auto_updateanswers400.
⚠ filex in someone else's frame (Changed): a dashboard that
shows filex in an<iframe>(Homarr, Organizr and the like) needs its
origin in the newFILEX_FRAME_ANCESTORS; otherwise the browser refuses the
frame. The embedded explorer is not a frame and is not affected.
⚠ The iframe converter is removed (Removed): conversion is
the Convert app.FILEX_CONVERT_URL, the composeconvertprofile and the
Helmconvertvalues are gone; a server that still sets the variable says
so once, at start.
⚠ For app authors (Changed): the app platform API is
narrower — paths an app passes must be the call's inputs or files it keeps
state on,share_createandfile_lockneed editor, anhttp:
permission names a host, and screen calls are capped per app. The two
published apps are unaffected.
⚠ For integrators (Changed):
@brftech/filex-corenow
depends on@headlessui/vue,lucide-vue-nextand the new
@brftech/filex-app-ui.
⚠ Encrypted folders get a level, and level 2 is refused by older filex
(Added): level 1 (contents only) stays the default and keeps its
v2 key file, which every filex since 0.31 opens. Level 2 (contents and
names) — chosen in the create dialog, or later in the folder's settings —
writes marker v3, which filex 0.47 and older will not open: on purpose,
because they would upload files under their plaintext names next to the
encrypted ones. Every folder that already exists stays at level 1.
⚠ Large and single encrypted files need filex 0.48 (Added): a
file over 200 MB in an encrypted folder is now written as a stream (header
0x02) and a single encrypted file is a.fxe; filex 0.47 and older open
neither. The folder, and its files up to 200 MB, still open there.
Added
- An app may bring its own interface
(docs/APP-PLUGINS.md). Besides
the screens filex draws, an app can ship HTML, CSS and JavaScript of its
own — an editor, a viewer — and an app can be only that, with no
WebAssembly module at all.- filex serves the interface from the app's package (a zip pinned by its
SHA-256, checked once at install and never unpacked) and runs it in a
sandboxed frame whose policy allows no connection, no storage, no cookie
and no reach into the page around it. The page policy is built from what
you approved, never from the package: scripts only from the package,
connect-src 'none'. - Everything the interface does goes through filex over one checked
channel: reading the files it was opened with, saving over them (a new
version, or the draft it is), a new file where the person picks, asking
the app's own module (ui_call), a toast, a question. The server checks
every save again. - A new placement, viewer: an app opens a file type the way filex's
own viewers do, and the file menu gets Open with . Unsaved
changes are asked about before the interface closes; drafts (#71) work
unchanged. - The install review has an Interface group: the package, every
address outside it — mirrored (filex downloads it once and serves it
itself) or live (the reader's browser fetches it; a permission, in
yellow, with what that means) — the script-policy exceptions, and a
plain note that a browser cannot fully stop a page sending data out
(WebRTC). An upgrade that adds an address asks again. - An interface may read its own package at run time
(ui.package_fetch, permissionui:package-fetch, on the review as
"reads its own package") — what an editor that loads its own shape
libraries and translations needs. Only that version's files: the page'sconnect-srcand
Chrome'sConnection-Allowlistname the package's own path; another
app, filex's API and the network stay closed. Every interface's
allowlist now names its package path instead of filex's whole origin. - New document can make an app's kind of file (
new_documents,
docs/APP-PLUGINS-API.md): a row
in the app's own words under Apps, made from the app's template (or
empty) and opened in the app's viewer — a draft until its first save.
Each kind is on the install review (ui-new:.<ext>); the rows are told
to signed-in people only, while the app runs. - An interface may hand you a file for your own disk (
ui.downloadin
the manifest,fx.downloadin the SDK, permissionui:download): filex
does it, on your click in the interface or your yes, never over 256 MiB —
in Chromium streamed into the file you pick, elsewhere a download. - The editor tab (
/files/edit, Open in new tab) opens a file in the
app that views it, by the explorer's own rule (Open with's choice
travels asapp=<plugin>/<view>); before, the tab showed filex's own
viewer. - What holds an interface in: an address outside its package is a plain
public https address — no IP, no internal name; its page is revalidated
at every opening, so a narrowed grant takes effect at once; a signed
app's module must describe the same interface as its manifest, and a
mirrored file is served only as the kind it was declared; a viewer names
the file types it opens, each a line of the review (ui-viewer:.md), so
an update that widens them asks again; a save counts against the quota,
and "save as" keeps to the view's file type and never writes into an
encrypted folder; the interface is told an error code, never the
server's text; a job or a clipboard write needs a gesture in its frame or
the person's yes, and everything filex draws for it names the app; one
frame's calls are capped, and its calls to the module share the app's
screen-call ceiling; filex's pages frame interfaces by path
(<host>/_appui/), so an interface cannot send its frame to another
filex page; and the interface's page switches off every powerful browser
feature (devices, sensors, credentials, ads). - For authors: the
@brftech/filex-app-uiSDK (a few KB, no
dependency),pluginkitPlugin.UI+plugintestHarness.UICall,
and Writing an interface.
FILEX_APP_PLUGIN_MAX_UI_MB(128) caps a package; migration00065
addsapp_plugins.ui_sha256.
- filex serves the interface from the app's package (a zip pinned by its
- A new document is a draft until its first save
(#71). Choosing New
document, naming it and closing the editor used to leave an empty file in
the folder. Now Create makes a draft — a real file with the name and type
you chose, kept in your own drafts area of that storage — and the folder
gets nothing until you press Save
(docs/ONLYOFFICE.md).- The editor opens on the draft under a bar that says where it will go,
and every editor writes into it as you type: the text, code and Markdown
editors every few seconds, the document server and the diagram editor
through their own saves. The browser asks before a tab with unsaved
changes is closed, and so does the desktop app's document window. - Save puts it in its folder. If a file has taken the name meanwhile,
filex asks — save asreport (2).txtinstead? — and nothing moves
before the answer; a save never replaces a file. - Closing a draft that was never saved asks Save to disk, Keep in
Drafts (the default) or Discard, which moves it to the Trash;
restoring it from there puts it back in Drafts. - Drafts, in the navigation panel beside Recent, Starred and Trash,
lists your drafts from every storage in the explorer's own table — name,
where it will be saved, storage, modified — with Open, Save to disk and
Delete, and the panel shows how many there are. No notifications. - A draft is its owner's alone: not in any listing, search, share, WebDAV,
S3, SFTP, FTPS or NFS view, desktop sync, storage usage figure or version
history, and not shown to anybody else — administrators included. On
disk it is.filex-drafts/<user id>/<key>/<name>, one of the names filex
keeps for itself. - At most 50 drafts per person by default: Admin → Protection →
Drafts (1–1000), orFILEX_DRAFTS_LIMITon a fresh install. At the limit
New document says so and offers Drafts; it never creates the file in the
folder instead. - For integrators:
POST /api/files/draftstakesnewfile's body, with
GET,…/count,…/{key},POST …/{key}/save(409 TARGET_TAKENwith
asuggestedname) andDELETE …/{key}
(docs/BACKEND.md). Drafts belong to a person, so
an app token and an embed confined to one folder by its host keep
creating the file directly;capabilities.draftsis present exactly when
the caller's New document makes drafts. Migration00064adds the
draftstable.
- The editor opens on the draft under a bar that says where it will go,
- Encryption levels, and encrypted file and folder names. An encrypted
folder has a level: 1 · Contents only (the default) or 2 · Contents
and names, chosen in the create dialog, shown in the strip, changed in the
folder's new Encryption settings… (which also hold the password and the
escrow slot). At level 2 the names are encrypted in the browser too —
AES-SIV (RFC 5297) under a name key sealed by the folder key, with the id of
the folder a name is in as associated data, so the same name in two folders
is two different stored names; base64url on the server, a folder's id
carried in its own name, long names shortened with a sidecar. The server
stores and indexes only ciphertext names; every surface of the explorer —
listing, split pane, breadcrumb, tabs, destination picker, Recent, Starred,
tags, Home, trash, search, the details panel, uploads, downloads — shows the
plaintext while the folder is unlocked and "🔒 Encrypted item" while it is
not. The vault level is designed, not built, and not offered.
E2E-ENCRYPTION.md → Encryption levels and names - Encrypt a single file. Right-click any file and choose Encrypt with
E2EE…: it becomes one self-contained<name>.fxe, encrypted in the browser
under a password of its own, with a recovery key shown once and — where the
installation has key escrow — an escrow slot, said up front. Open, preview
and download decrypt in the browser; Change password… rewrites the header
only; Remove encryption… puts the plaintext back. The name can be hidden
too (encrypted-<hex>.fxe). The dialog says what the server already saw of
the original (the trash, its versions, a thumbnail, backups) before
anything happens.
E2E-ENCRYPTION.md → Single encrypted files - Desktop app: the notification bell and your account menu in the top bar.
The app raised a native notification for everything new and had nowhere in
its window to read one, mark it read or follow it — and no account menu at
all. The top bar now ends as the web app's does: the bell (the unread
count on it, the newest fifteen, Mark all read, View all with pages and
Unread only) and the avatar, which holds your settings as a person:
User settings opens the web app's settings dialog inside the window
(profile, time zone, appearance, compact list, default folder view,
notification switches, password, two-factor sign-in), Admin panel ↗ for an
administrator, and the file list's shortcut and tour rows that sat behind
the "…". A click on a notification lands in the window: the folder with the
file selected, the Trash with the item selected, or an app's home view. They
are the web app's own components, not a second copy — see Changed.
Signing out stays where the app's own settings are, Settings → Accounts,
with the language, sync and the other accounts.
(docs/DESKTOP.md → Notifications and your account) - Encrypt a folder you already have, in place. Right-click a folder →
Encrypt with E2EE…: the same dialog as creating one (level 1 by
default), and every file is encrypted where it is, resumably; at level 2 the
names follow. The server keeps no plaintext version of those writes, and
when it finishes drops the thumbnails and extracted text it held for the
folder and — the owner's choice, on by default — its older versions and
trash entries (POST /api/files/e2e/cleanup). The key file carries the new
required featureconvwhile it runs, which filex 0.47 and older refuse.
E2E-ENCRYPTION.md → Encrypting a folder you already have - Raise a folder you already have to level 2. Encryption settings… →
Change level…, after saying what changes; nothing is proposed on unlock.
It renames only (no content is touched), writes the key file first, and an
interrupted run continues where it stopped. Fix names in the same place
renames stray plaintext names written later over WebDAV or the CLI, and
repairs names moved in from another folder outside filex. - Change an encrypted folder's password. Encryption settings… → Change
password…, proved with the current password or the recovery key. A
folder created since v0.31 rewrites only its key file — no file is touched,
the recovery key, escrow and encrypted names keep working. A folder from
before v0.31, whose key comes from its password, is re-keyed: a new folder
key, every file's key re-wrapped (the contents are not re-encrypted),
resumable, with a new recovery key; any folder can be re-keyed on purpose
("Also replace the folder key"), which is also how a leaked recovery key is
revoked. Opening a folder with its recovery key now asks for a new password
straight away. Every change is recorded in the audit log and the folder's
owner is notified (e2e.password_changed, subscribable by webhook).
E2E-ENCRYPTION.md → Changing the password - No size limit in encrypted folders. A file over 200 MB is encrypted in
the browser as a STREAM (chunked AES-256-GCM, 1 MiB chunks, truncation and
reordering detected) while it uploads, and decrypted as it downloads —
nothing is held in memory. These files use header version0x02, which
filex 0.47 and older refuse (the folder and its smaller files still open
there); files up to 200 MB are written exactly as before.
E2E-ENCRYPTION.md → Streaming content - Download an encrypted folder decrypted. Downloading an unlocked
encrypted folder, a subfolder or a selection inside one now gives a zip with
the real names and the decrypted content, made in the browser as it is
saved; Download encrypted copy keeps the server's ciphertext zip. Chrome,
Edge and the desktop app save it straight to disk at any size; Firefox and
Safari up to 1 GB, and say so above that.
E2E-ENCRYPTION.md → Downloading a decrypted copy - The escrow key opens a single encrypted file — and its owner is told.
On an installation with key escrow, the unlock dialog of a.fxesealed to
its key offers Use the escrow key: the same flow as an encrypted folder's,
the browser proving it holds the private key and the server notifying the
file's owner before anything is decrypted./api/files/e2e/escrow/challenge
and/usedaccept a.fxepath.
E2E-ENCRYPTION.md → Key escrow - A
.fxepassword change is announced, and the server sees it too. The
owner is notified and the audit log recordse2e.password_change, as for a
folder; independently, every rewrite of a.fxeon any surface is audited
by the server ase2e.fxe_header_rewritten(password, recovery key, escrow,
content…), and a changed password deletes the versions that would still
open the file's current contents with the old one.
E2E-ENCRYPTION.md → Who is told - Delete the original for good while encrypting it (administrators). The
encrypt dialog offers an administrator to delete the original's versions and
its trash entry as soon as the encrypted copy is saved; for someone else's
file it names the owner and asks a second, explicit confirmation.
E2E-ENCRYPTION.md → What the server already saw - Over 1 GB in Firefox or Safari, the decrypted download says so and hands
over the way out. Instead of an error line, a dialog — before the password
is asked, for a.fxe— with Download encrypted file (or the encrypted
folder as a zip) and thefilex decryptcommand to copy. Chrome, Edge and
the desktop app still stream it to disk at any size.
E2E-ENCRYPTION.md → Where a decrypted download goes filex decrypt— decrypts a downloaded encrypted folder (or its zip, or
one file) on your own machine, with the folder password or the recovery
key, offline, into a folder with the original names. The password is read
from the terminal or standard input, never from an argument; a wrong password
or a damaged file stops it with no partial output. Reads every marker version.
CLI.md → filex decryptfilex decrypt file.fxewrites a single encrypted file back under its
original name (or-o), andfilex decryptstreams0x02folder files; a
wrong password (exit 5) or a damaged, truncated or extended file (exit 6)
leaves nothing behind.
CLI.md → A single encrypted file- The server records every rewrite of an encrypted folder's key file — an
audit rowe2e.key_file_rewrittenwith which slots changed (password,
recovery_key,escrow,level,rekey) and the surface it came from,
whether or not the client announced it. When the password or recovery slot
changed, the key file's earlier versions are deleted: each of them still
opened the folder with the old password.
E2E-ENCRYPTION.md → Who is told - Notifications never print an encrypted name. A row about an item inside
an encrypted folder carriesmeta.e2e_root; the bell, the notifications
page, the browser toast and the desktop app show "🔒 Encrypted item" — or
the real name, where this tab's explorer has the folder unlocked — instead
of the ciphertext the server stores.
NOTIFICATIONS.md
This release has more to it than fits on one page. The rest of the
entry — and every earlier release — is in CHANGELOG.md.
Verify: sha256sum -c checksums.txt
- Documentation — https://docs.filex.sh
- Report a bug — https://github.com/BRF-Tech/filex/issues
- Full changelog — https://github.com/BRF-Tech/filex/blob/main/CHANGELOG.md
- Every release — https://github.com/BRF-Tech/filex/releases