Published: October 8, 2025
Last updated: April 23, 2026

The fastest way to get started with FileBrowser Quantum.

Available Images

Images from Docker Hub (gtstef/filebrowser) and GitHub Container Registry (ghcr.io/gtsteffaniak/filebrowser):

TagSizeFeaturesArchitectures
latest, stable60 MBFFmpeg + document previewarm64, amd64
stable-slim15 MBCore service only (no media/office)arm64, arm32, amd64
beta60 MBFFmpeg + document previewarm64, amd64
beta-slim15 MBCore service only (no media/office)arm64, arm32, amd64

Learn more about the versions and tags here.

Quick Try

Test without persistence (changes not saved). In this example we run it mounting the local path:

BASH
1
2
3
4
docker run -d \
  -v $(pwd):/srv \
  -p 80:80 \
  gtstef/filebrowser:stable

Access at http://localhost with admin / admin

Basic Setup with Docker Compose

Step 1: Create a base folder for FileBrowser

BASH
1
mkdir -p filebrowser/data && cd filebrowser

Step 2: Create Config

Add a config.yaml file inside the data directory:

BASH
1
touch ./data/config.yaml

Then fill out your config as needed, for example:

YAML
1
2
3
4
5
6
server:
  cacheDir: /home/filebrowser/data/tmp # using the data volume so it can persist across restarts
  sources:
    - path: /folder # Do not use a root "/" directory or include the "/var" folder
      config:
        defaultEnabled: true

Step 3: Create Docker Compose

Create docker-compose.yaml in the directory.

BASH
1
touch docker-compose.yaml

Then type in the below docker configuration.

YAML
1
2
3
4
5
6
7
8
9
services:
  filebrowser:
    image: gtstef/filebrowser:stable
    volumes:
      - /path/to/your/folder:/folder # Do not use a root "/" directory or include the "/var" folder
      - ./data:/home/filebrowser/data
    ports:
      - 80:80 # exposes port 80 to host, the left-side number can be changed without config.yaml changes.
    restart: unless-stopped

Step 4: Start

BASH
1
docker compose up -d

Healthcheck Configuration

The FileBrowser Docker image includes a default healthcheck that uses port 80:

DOCKERFILE
1
2
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:80/health || exit 1

If you configure FileBrowser to use a different port in your config.yaml, you must override the healthcheck in your docker-compose.yaml to match:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  filebrowser:
    image: gtstef/filebrowser:stable
    volumes:
      - /path/to/your/folder:/folder
      - ./data:/home/filebrowser/data
    ports:
      - 80:8080  # Filebrowser listens on 8080 inside docker, but here we are exposing the host port as 80 still.
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"] # port should match the internal port 8080 
      interval: 30s
      timeout: 3s
      start_period: 10s
      retries: 3
    restart: unless-stopped

Healthcheck options:

  • test - Command to run (must match your configured port)
  • interval - Time between health checks (default: 30s)
  • timeout - Time to wait for response (default: 3s)
  • start_period - Grace period on startup (default: 10s)
  • retries - Number of failures before marking unhealthy (default: 3)

Database Location

Running container with a different user

FileBrowser Quantum docker images have a non-default filebrowser user built-in. This user has UID:GID of 1000:1000. In v1.2.x and earlier you need to specify this user manually:

Add to docker-compose.yaml:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
services:
  filebrowser:
    image: gtstef/filebrowser:stable
    user: filebrowser
    volumes:
      - /path/to/files:/folder
      - ./data:/home/filebrowser/data
    ports:
      - 80:80
    restart: unless-stopped

You can also specify any user UID:GID, but if you choose a UID other than 1000, you will need to make sure the mounted data directory has the same permissions (See cacheDir config)

for example if you wanted to use 1001:1001 user for Unraid installs.

BASH
1
chown -R 1001:1001 ./data

Privileged ports and container capabilities

In-container listen (Linux containers)

Linux treats ports below 1024 as privileged: a non-root user needs the NET_BIND_SERVICE capability (or a lowered net.ipv4.ip_unprivileged_port_start) to bind there.

On rootful Docker Engine or Docker Desktop, the container still usually gets NET_BIND_SERVICE in the default capability set, so that user can listen on 80 or 443 without extra flags. bind: permission denied on a low server.port shows up more often when:

  • you use a rootless container engine (Docker rootless, Podman rootless), or
  • the runtime uses a stricter capability profile (some Podman installs, explicit --cap-drop, hardened policies), So the v1.3 switch to a non-root default pairs with those environments: the process is no longer UID 0, and if NET_BIND_SERVICE is not effective, the kernel rejects the bind. It is not “non-root in Docker always breaks port 443 on every machine.”

non-root runtimes can use NET_BIND_SERVICE

Allow binding to ports below 1024 inside the container:

YAML
1
2
3
4
services:
  filebrowser:
    cap_add:
      - NET_BIND_SERVICE

For docker run, use --cap-add=NET_BIND_SERVICE. Podman supports the same flag (or the equivalent in your compose file). Prefer this over --privileged unless you need broader host access.

Further reading: Docker: Runtime privilege and Linux capabilities.

Next Steps