FileBrowser Quantum¶
Overview¶
FileBrowser Quantum is an actively developed fork of the original File Browser: a web UI to browse, upload, download, preview and share files in a few directories. I use it for one thing: getting at a couple of NAS folders from a browser on a machine where I can't install anything (a work computer), without SMB or a VPN client.
Design rules that came out of an earlier, looser setup:
- Mount only what you need, never the whole pool. Two sources: a
Sharedfolder just for passing files around, andDocuments, which is the Syncthing copy of my desktop folders (edits there sync back to the desktop). - Run as the files' owner (same UID as Syncthing), so ownership stays consistent, with a read-only root filesystem and no capabilities.
- Two logins on the public path: SSO at the edge (Cloudflare Access in my case), then FileBrowser's own password with mandatory TOTP.
- Config in git, mounted read-only. Users, shares and UI settings live in FileBrowser's SQLite DB, so it never needs to write the config file.
Compose¶
compose.yaml
services:
filebrowser:
# 2.0.x is the stable line. Full image (not -slim) for PDF/office/video previews.
image: gtstef/filebrowser:2.0.1-stable
container_name: filebrowser
restart: unless-stopped
user: "<PUID>:<PGID>"
environment:
- FILEBROWSER_CONFIG=/home/filebrowser/config/config.yaml
- FILEBROWSER_DATABASE_PATH=/home/filebrowser/data/database.sqlite
- FILEBROWSER_ADMIN_PASSWORD=${FILEBROWSER_ADMIN_PASSWORD}
- FILEBROWSER_TOTP_SECRET=${FILEBROWSER_TOTP_SECRET}
- TZ=<TZ>
volumes:
- ./config.yaml:/home/filebrowser/config/config.yaml:ro
- /mnt/appdata/filebrowser/data:/home/filebrowser/data
- /mnt/appdata/filebrowser/cache:/home/filebrowser/cache
- /mnt/storage/filebrowser/shared:/srv/shared
- /mnt/storage/sync:/srv/documents
ports:
# LAN address only; the reverse proxy forwards to it
- "<YOUR_SERVER_IP>:89:80"
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
mem_limit: 1g
# Same command as the image's own HEALTHCHECK (curl is in the image)
healthcheck:
test: ["CMD", "curl", "-fsS", "-o", "/dev/null", "http://localhost:80/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
.env.example
FILEBROWSER_ADMIN_PASSWORD=<YOUR_PASSWORD> # initial admin password (12+ characters)
FILEBROWSER_TOTP_SECRET=<YOUR_TOKEN> # encrypts users' TOTP seeds in the DB: openssl rand -hex 32
The cache directory (thumbnails/previews) can be excluded from backups; the data directory (SQLite DB) can't.
config.yaml¶
config.yaml
http:
port: 80
baseURL: "/"
externalUrl: "https://files.<YOUR_DOMAIN>"
# The reverse proxy sets X-Real-IP / X-Forwarded-For, so the login rate limit and lockout see the client
trustProxyHeaders: true
# Not used; one less authenticated surface
disableWebDAV: true
server:
# Renovate tracks the image tag
disableUpdateCheck: true
cacheDir: "/home/filebrowser/cache"
cacheDirCleanup: true
logging:
- levels: "info|warning|error"
sources:
- path: "/srv/shared"
name: "Shared"
config:
defaultEnabled: true
- path: "/srv/documents"
name: "Documents"
config:
defaultEnabled: true
# No public share links out of the Syncthing folders
private: true
rules:
# Hide Syncthing internals: version history, folder markers, temp files
- folderName: ".stversions"
- folderName: ".stfolder"
- fileStartsWith: ".syncthing."
- fileName: ".stignore"
auth:
adminUsername: "<YOUR_USER>"
# Web session length; the SSO gateway has its own session in front of this
tokenExpirationHours: 8
methods:
password:
enabled: true
minLength: 12
signup: false
# Every password user must enroll TOTP at first login
enforcedOtp: true
passkey:
enabled: false
frontend:
name: "files"
Notes on the choices:
trustProxyHeadersonly belongs on an instance that is reachable only through your proxy (here: the port is bound to the LAN address and the proxy is the only thing that uses it). Otherwise clients could fake their IP.private: trueon the Syncthing source blocks public share links for anything in there.Sharedallows them, since handing a file to someone is its whole purpose.- The Syncthing rules keep
.stversionsand friends out of the UI; nobody should edit those by hand.