WinDirStat-style disk-usage visualizer for your NAS — interactive treemap, background scanning.
410
A self-hosted, WinDirStat-style disk-usage visualizer for your NAS or server. It scans mounted directories in the background into a SQLite store and renders them as a zoomable, nested treemap in the browser — so you can see, at a glance, what's eating your space.
linux/amd64 + linux/arm64), non-root.docker run -d --name webdirstat \
-p 8080:8080 \
-v /path/to/scan:/data:ro \
-v /path/to/appdata/webdirstat:/db \
-e ROOTS="Data=/data" \
treewyrm/webdirstat:latest
Then open http://SERVER-IP:8080/ and press Start to run the first scan.
services:
webdirstat:
image: treewyrm/webdirstat:latest
container_name: webdirstat
ports:
- "8080:8080"
volumes:
- /path/to/scan:/data:ro # the share(s) you want to analyze — read-only
- /path/to/appdata/webdirstat:/db # writable store (must NOT be the scanned share)
environment:
ROOTS: "Data=/data"
PUID: "1000" # uid/gid that owns your /db appdata dir
PGID: "1000"
# PASSWORD: "changeme" # uncomment to require login
# TZ: "Europe/London" # for scheduled scan windows
restart: unless-stopped
| Path | Mode | Purpose |
|---|---|---|
/data | read-only | The directory (or directories) to analyze. Mount :ro — the app never writes here. |
/db | writable | The SQLite store. Must be writable storage, and must not be the scanned share. |
Mount multiple shares under /data/<name> (e.g. /mnt/user/movies:/data/movies:ro) and
point ROOTS at each, or add more volumes and reference them in ROOTS.
| Container | Purpose |
|---|---|
8080 | Web UI + API (HTTP). |
| Variable | Default | Description |
|---|---|---|
ROOTS | Data=/data | The directories to scan, as Label=/path,Label2=/path2. Paths are the in-container mount points (/data), not host paths. A bare path (ROOTS=/data) derives its label from the basename. Because = and , are legal in paths, a path containing , must use the explicit Label=/path form. |
PUID | 1000 | User id the app runs as. Set to the owner of your /db appdata directory so the store is writable. |
PGID | 1000 | Group id the app runs as. |
TZ | container/UTC | Timezone, used to interpret scheduled scan windows. |
| Variable | Default | Description |
|---|---|---|
PASSWORD | (unset) | Shared login password. Unset = open (no login). |
SESSION_SECRET | (random) | ≥32-char secret that seals the session cookie. If unset, an ephemeral key is generated and all logins reset on restart — set a fixed value in production. |
The session cookie is sent over plain HTTP (works on a LAN). For exposure beyond a trusted network, put TLS in front (reverse proxy, Tailscale, etc.).
Automatic scanning is opt-in — off unless you set SCAN_ENABLED=true or express any
schedule intent (SCAN_INTERVAL / SCAN_WINDOWS). With it off, the service is manual-only
(Start/Stop in the UI). Everything below can also be set per-root in the UI.
| Variable | Default | Description |
|---|---|---|
SCAN_ENABLED | (auto) | true/1 to enable automatic scanning. Defaults on if an interval or window is set. |
SCAN_INTERVAL | (none) | Staleness threshold before a rescan, e.g. 24h, 7d, 90m. |
SCAN_WINDOWS | (none) | Weekly time windows when scanning is allowed, e.g. Mon-Fri 02:00-05:00. |
SCAN_MIN_INTERVAL | 1h | Minimum floor between rescans, regardless of other triggers. |
SCAN_CONCURRENCY | 4 | Max concurrent filesystem syscalls during a walk. |
SCAN_ON_WINDOW_END | finish | finish lets an in-flight scan complete past a window's end; abort stops it. |
HISTORY_GENERATIONS | 0 | How many past scan generations to retain (0 = keep only the live one). |
| Variable | Default | Description |
|---|---|---|
COMPRESSION | true | brotli/gzip content-negotiated compression of API + SPA. false to disable. |
COMPRESSION_QUALITY | 5 | brotli quality, 0–11. |
COMPRESSION_MIN_SIZE | 1024 | Minimum response size (bytes) to compress. |
PUID/PGID (default 1000) to match the owner of your /db
appdata directory; the container adjusts the runtime user to those ids and chowns /db
on start, so the store is writable without any manual chown. The read-only /data share
is never touched./api/health, which also pings the store, so your
orchestrator shows green/red honestly.latest, plus semver X.Y.Z and X.Y per release.Source, issues, and full docs: https://github.com/treewyrm/webdirstat License: MIT.
Content type
Image
Digest
sha256:17a578e90…
Size
56.8 MB
Last updated
2 months ago
docker pull treewyrm/webdirstat