Dissimilis/DirForge

📂 File Systems🟢 Verified Active
0 Views
0 Installs

️⃣ 🏠 🍎 🪟 🐧 - Read-only directory listing web app with a built-in MCP server: directory browsing, file reading, content search, archive inspection, file hashes, and disk usage tools over a configured root.

Quick Install

One-Click IDE Configuration
claude_desktop_config.json
{
  "mcpServers": {
    "dissimilis-dirforge": {
      "command": "npx",
      "args": [
        "-y",
        "dissimilis-dirforge"
      ]
    }
  }
}
Or

Using an AI coding agent (Claude Code, Cursor, etc.)? Copy a ready-made prompt that tells it to fetch the setup instructions and install this server for you.

Documentation Overview

DirForge

DirForge logo

CI Latest Release GHCR Buy Me a Coffee

A stateless, read-only web file browser for homelab and NAS power users. No database, no background workers, no disk writes - just point it at a mounted path and go.

DirForge directory listing

Live Demo

Browse files in a clean web UI with search, previews, and archive inspection. Download individual files or entire folders as ZIP. Access the same data through a RESTful JSON API, an S3-compatible endpoint for tools like rclone, a read-only WebDAV mount for native OS file managers, or an MCP server for AI assistants. Everything runs in a single stateless container with no external dependencies.

Quick Start

Prerequisite: Docker or Podman (images are published for amd64 and arm64).

Docker run

docker run -d \
  --name dirforge \
  -p 8091:8080 \
  -e RootPath=/data \
  -v /srv/share:/data:ro \
  ghcr.io/dissimilis/dirforge:latest

Docker Compose

cp .env.example .env
# edit HOST_PATH, BasicAuthUser, and BasicAuthPass in .env
docker compose up -d

Warning: The default compose file falls back to admin/dirforge credentials if you don't set BasicAuthUser and BasicAuthPass in your .env. Change these before exposing the service on your network.

Podman

The same commands work with Podman. Replace docker with podman:

podman run -d \
  --name dirforge \
  -p 8091:8080 \
  -e RootPath=/data \
  -v /srv/share:/data:ro \
  ghcr.io/dissimilis/dirforge:latest

For Compose, use podman compose (Podman 4.1+):

cp .env.example .env
# edit HOST_PATH in .env
podman compose up -d

Notes for Podman users:

  • podman compose is a built-in subcommand in Podman 4.1+, not the older third-party podman-compose Python package.
  • DirForge uses ports above 1024, so rootless Podman works without extra configuration.
  • On SELinux systems (Fedora, RHEL), add :z to volume mounts: -v /srv/share:/data:ro,z.

Standalone (Windows)

  1. Download dirforge-win-x64.zip from the latest release
  2. Extract to a folder (e.g. C:\DirForge)
  3. Edit appsettings.json — set RootPath to the directory you want to share
  4. Console mode: Double-click DirForge.exe to run interactively
  5. Windows Service: Right-click install-service.bat → Run as administrator. DirForge will start on boot automatically. Use uninstall-service.bat to remove the service.

Standalone (Linux)

  1. Download dirforge-linux-x64.tar.gz (or linux-arm64) from the latest release
  2. Extract: tar -xzf dirforge-linux-x64.tar.gz -C /opt/dirforge
  3. Edit appsettings.json — set RootPath to the directory you want to share
  4. Run directly: ./DirForge
  5. Install as systemd service:
    sudo useradd -r -s /usr/sbin/nologin dirforge
    sudo cp dirforge.service /etc/systemd/system/
    # Edit /etc/systemd/system/dirforge.service to adjust paths if needed
    sudo systemctl daemon-reload
    sudo systemctl enable --now dirforge
    

The tarball includes an example dirforge.service file with systemd hardening options.

Open http://localhost:8091. With the default config profile in this repository, sharing, dashboard, and metrics are enabled.

Features

Browsing

  • List and grid view layouts
  • Sortable columns (name, size, date)
  • Light and dark themes (toggle or set default via DefaultTheme)
  • File preview modal for text, images, video, audio, and PDF
  • Inline archive browser for .zip, .tar, .tar.gz, .tgz, and .gz
  • Image lightbox with navigation
  • Recursive search with configurable depth and time budget
  • Age badges on files and folders
  • Custom site title via SiteTitle

Sharing & Downloads

  • Direct file downloads
  • Folder download as ZIP archive (with configurable max size)
  • Signed share links with expiry
  • One-time share links
  • QR code generation for share links
  • File hash calculation (CRC32, MD5, SHA-1, SHA-256, SHA-512)
  • Sidecar checksum verification (.md5, .sha1, .sha256, .sha512, .sfv)

WebDAV

  • Read-only WebDAV endpoint at /webdav/ (DAV Class 1)
  • Supports OPTIONS, PROPFIND, GET, and HEAD methods
  • Compatible with Windows Explorer, macOS Finder, and other WebDAV clients
  • Same security policies as the web UI (hidden paths, denied extensions, auth)

S3-Compatible API

  • Read-only S3 endpoint at /s3/ for scripted and programmatic access
  • Compatible with aws cli, rclone, MinIO client, and other S3-compatible tools
  • AWS Signature V4 authentication (access key + secret key)
  • Supports ListBuckets, GetBucketLocation, ListObjectsV2, GetObject, HeadObject
  • HTTP Range requests for partial downloads
  • Hidden paths, denied extensions, and auth enforced

Security & Operations

  • HTTP Basic Auth (username + password)
  • Bearer token auth via configurable header (for MCP clients, API consumers, automation)
  • External auth via reverse proxy headers (e.g. Authelia, Authentik)
  • Hide files by dotfile flag or glob patterns
  • Deny downloads by file extension
  • Fixed-window rate limiting (per-IP and global)
  • Health endpoints (/health, /healthz, /readyz)
  • In-memory dashboard at /dashboard with optional dedicated credentials
  • Prometheus metrics at /metrics
  • RESTful JSON API at /api/ (browse, search, share, archive)
  • MCP server at /mcp/ (JSON-RPC 2.0, Streamable HTTP transport)
  • Integration stats JSON at /dashboard/stats
  • Distroless chiseled container image

Configuration

Defaults are defined in src/DirForge/appsettings.json. Override any value with an environment variable of the same name. Boolean values must be true or false. For the full list of options, see .env.example.

VariableDefaultDescription
RootPath.Root directory to browse.
Port8080HTTP listen port.
ListenIp0.0.0.0IP address the app binds to.
BasicAuthUserunsetBasic Auth username.
BasicAuthPassunsetBasic Auth password.
BearerTokenunsetBearer token for token-based auth (MCP clients, API consumers, automation).
BearerTokenHeaderNameAuthorizationHeader to read the bearer token from.
EnableSharingtrueEnable HMAC-signed share links.
ShareSecretemptySecret for signing share links. Set a long random value in production; if empty an in-memory secret is generated at startup.
HideDotfilesfalseHide entries starting with ..
DenyDownloadExtensionsenv,key,pem,...Extensions blocked in direct and ZIP downloads.
DefaultThemedarkUI theme (dark or light).
SiteTitleDirForgeCustom page title/header label.
EnableWebDavtrueRead-only WebDAV at /webdav/.
EnableS3EndpointfalseRead-only S3 API at /s3/.
EnableJsonApitrueRESTful JSON API at /api/.
EnableMcpEndpointtrueMCP server at /mcp/.
CalculateDirectorySizesfalseAuto-calculate subdirectory sizes on page load (slow on large trees).
DirectorySizeCacheTtlSeconds300Cache TTL for computed directory sizes in seconds (0–2592000; 0 disables).
ListingCacheTtlSeconds2Directory listing cache TTL in seconds (1–2592000).

Security

Hardened example profile - copy into your .env and adjust:

BasicAuthUser=admin
BasicAuthPass=change-this
BearerToken=replace-with-long-random-token
ShareSecret=replace-with-long-random-value
ForwardedHeadersKnownProxies=10.0.0.2
DashboardAuthUser=metrics
DashboardAuthPass=change-this-too
  • Mount only directories you want to expose; prefer read-only mounts (:ro).
  • Baseline defaults are homelab-oriented, not internet-hardened.
  • Set BasicAuthUser / BasicAuthPass when exposed outside a trusted network.
  • Set BearerToken for token-based auth (useful for MCP clients, API consumers, and automation that poorly support Basic Auth). Both auth methods can be enabled simultaneously, either one grants access.
  • When BearerTokenHeaderName is Authorization (default), the middleware accepts Authorization: Bearer <token> and Authorization: <token>. Set a custom header name (e.g. X-API-Key) to read the raw token from that header instead.
  • Set ShareSecret to a long random value in production. If empty, DirForge uses an in-memory secret and share links reset on restart.
  • For reverse proxy auth, set ExternalAuthEnabled=true and pin ForwardedHeadersKnownProxies. Bearer token auth is also bypassed when external auth is enabled.
  • Hidden paths and denied extensions are enforced for both direct downloads and ZIP output.
  • Dashboard and metrics data are in-memory only and reset on restart.
  • If DashboardAuthUser / DashboardAuthPass are set, /dashboard and /metrics accept only those credentials.
  • /dashboard/stats uses the same dashboard auth behavior: if dashboard credentials are configured, they are required.
  • Static UI assets are served from /dirforge-assets/* (plus /favicon.ico) and are intentionally public.

WebDAV

DirForge includes a read-only WebDAV endpoint at /webdav/ (DAV Class 1), enabled by default. It supports OPTIONS, PROPFIND, GET, and HEAD. All write methods return 405 Method Not Allowed.

Client Access

ClientConnection
macOS FinderFinder → Go → Connect to Server → http://host:port/webdav/
Windows ExplorerMap Network Drive → http://host:port/webdav/ (requires HTTPS or registry tweak, see below)
Linux (GVFS)dav://host:port/webdav/ in Nautilus/Thunar
cadaver / curlcadaver http://host:port/webdav/

Windows HTTP Limitation

Windows Explorer's WebDAV client (Mini-Redirector) refuses Basic Auth over plain HTTP by default. You must either:

  • Use HTTPS (via reverse proxy, recommended)
  • Set the registry key HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel to 2 and restart the WebClient service

Security

WebDAV requests follow the same auth and security pipeline as the web UI:

  • Basic Auth or bearer token credentials are required when configured
  • External auth headers are honored when ExternalAuthEnabled=true
  • Hidden paths (HideDotfiles, HidePathPatterns) and denied extensions (DenyDownloadExtensions) are enforced
  • Path traversal protection applies to all WebDAV paths

Set EnableWebDav=false to disable the endpoint entirely.

S3-Compatible API

DirForge includes a read-only S3-compatible endpoint at /s3/, disabled by default. It implements the minimal subset of the S3 API needed for listing and downloading files with standard S3 tools.

Supported Operations

OperationDescription
ListBucketsGET /s3/ - returns a single virtual bucket
GetBucketLocationGET /s3/{bucket}?location - returns configured region
ListObjectsV2GET /s3/{bucket}?prefix=...&delimiter=/&max-keys=... - list objects with pagination
GetObjectGET /s3/{bucket}/{key} - download a file (supports Range header)
HeadObjectHEAD /s3/{bucket}/{key} - file metadata without body

All write operations (PUT, POST, DELETE) return 405 Method Not Allowed.

Authentication

S3 requests use AWS Signature V4 - the same signing protocol as real AWS S3. Your secret key is never sent over the wire; clients sign each request with an HMAC-based signature that the server verifies.

By default, the S3 endpoint reuses your BasicAuthUser / BasicAuthPass as access key / secret key. Set S3AccessKeyId and S3SecretAccessKey for dedicated S3 credentials.

Credentials are required - the app will not start with EnableS3Endpoint=true and no credentials configured.

Client Examples

aws cli:

export AWS_ACCESS_KEY_ID=mykey
export AWS_SECRET_ACCESS_KEY=mysecret
aws --endpoint-url http://localhost:8091/s3 s3 ls
aws --endpoint-url http://localhost:8091/s3 s3 ls s3://dirforge/
aws --endpoint-url http://localhost:8091/s3 s3 ls s3://dirforge/subdir/
aws --endpoint-url http://localhost:8091/s3 s3 cp s3://dirforge/file.txt .

rclone:

rclone config create myremote s3 \
  provider=Other \
  endpoint=http://localhost:8091/s3 \
  access_key_id=mykey \
  secret_access_key=mysecret \
  region=us-east-1

rclone ls myremote:dirforge
rclone copy myremote:dirforge/file.txt .

Security

S3 requests bypass Basic Auth (they use SigV4 instead) but enforce all the same file-level policies:

  • Hidden paths (HideDotfiles, HidePathPatterns) are not visible
  • Denied extensions (DenyDownloadExtensions) return 403 Access Denied
  • Path traversal and symlink containment checks apply

Set EnableS3Endpoint=false (default) to disable the endpoint entirely.

MCP (Model Context Protocol)

DirForge exposes an MCP endpoint at /mcp that lets AI assistants browse directories, read files, search by name or content, check hashes, find duplicates, get disk usage reports, and more. Requires EnableMcpEndpoint=true (default) and a BearerToken set in your DirForge config. All hide/deny/auth policies apply.

Setup (Claude Code, Codex, etc.)

Just ask your AI assistant:

"Add DirForge MCP server at http://localhost:8091/mcp with bearer token changeme"

Then swap changeme for your actual BearerToken in a file config was added.

Symlinks and Hardlinks

DirForge follows symlinks but enforces strict containment: every symlink target must resolve to a path under RootPath. Links that escape the root are silently blocked.

Symlinks

When a request path contains a symlink, DirForge resolves it segment-by-segment. At each level, if a path component is a reparse point (symlink or junction), the final target is resolved and checked against RootPath. If the resolved target is outside the root, the entire path is rejected.

This means you can use symlinks freely inside your shared directory tree — for example, to present files from multiple physical locations under a single virtual layout — as long as every target points somewhere within RootPath.

During recursive operations (search, ZIP download, S3 listing), it tracks visited canonical paths to prevent infinite loops caused by circular symlinks. A directory that has already been visited (after symlink resolution) is skipped.

Hardlinks

Hardlinks are regular directory entries that share an inode with another file. They have no special metadata that distinguishes them from normal files, so DirForge treats them as ordinary files. Both names are listed and downloadable independently. There is no risk of escaping RootPath through hardlinks since they cannot point outside the filesystem they reside on, and they cannot reference directories.

Summary

Link TypeFollowedRoot ContainmentCycle Protection
SymlinkYesEnforced per-segmentYes (visited set)
Junction (Windows)YesEnforced per-segmentYes (visited set)
HardlinkN/A (treated as regular file)N/AN/A

Integrations API

For homelab dashboards (Homarr, Homepage, etc.), DirForge exposes:

  • GET /dashboard/stats

The endpoint returns compact JSON with 11 basic fields: generatedAtUtc, ready, uptimeSeconds, totalRequests, inFlightRequests, requestsPerMinute, averageLatencyMs, totalDownloadTrafficBytes, totalDownloadCount, fileCount, zipCount.

Contributing

See CONTRIBUTING.md.

Development

dotnet restore src/DirForge/DirForge.csproj
dotnet build src/DirForge/DirForge.csproj -c Release --no-restore
docker build -t dirforge:dev .    # or: podman build -t dirforge:dev .

Image Tags

Images are published to ghcr.io/dissimilis/dirforge.

TagWhen pushedUse for
latestEvery non-pre-release GitHub ReleaseStable production use
1.2.0Every GitHub ReleasePinned stable version
devEvery push to mainLatest development build
dev-<sha>Every push to mainPinned to a specific commit

License

MIT. See LICENSE.

Third-Party Attribution

  • File icon vector set in src/DirForge/wwwroot/file-icon-vectors/ is attributed to dmhendricks.

Related MCP Servers

modelcontextprotocol/server-filesystemVerified

📇 🏠 - Direct local file system access.

📂 File Systems1 views
8b-is/smart-tree

🦀 🏠 🍎 🪟 🐧 - AI-native directory visualization with semantic analysis, ultra-compressed formats for AI consumption, and 10x token reduction. Supports quantum-semantic mode with intelligent file categorization.

📂 File Systems0 views
aadilr/changethisfile-mcp

📇 ☁️ - Free file conversion between 690+ formats. Tools: convertfile (URL or base64 in → signed download URL out) and listconversions. Covers image, video, audio, document, data, font, ebook, and archive formats. No auth or signup required; remote streamable-HTTP endpoint available (see README).

📂 File Systems0 views
alebgl77/ftp-deploy-mcp

📇 🏠 🍎 🪟 🐧 - Deploy files from AI agents to your own FTP/FTPS/SFTP servers — multi-server config, recursive deploy with dry-run and gitignore-like excludes, per-server path jail and read-only mode, FileZilla import, one-command setup for popular MCP clients.

📂 File Systems0 views

Engagement

Views
0
Installs
0
Upvotes
0

Views and upvotes are unique per visitor network (hashed IP). Installs count copy actions.

Status

Health: Active

Recent health check succeeded.

Last checked: 7/28/2026, 10:16:58 PM

Unclaimed listing (imported or pending owner verification). Claim it →
★ Spotlight Slot

Feature Your MCP Server

Get maximum visibility for your server across our directory, search results, and detail pages.

Spotlight Your Server

Own this project?

This directory is pre-filled from public sources. Claim via GitHub README, site badge, or DNS TXT to get the verified badge and attach your website.

Claim this listing

Promote this listing

Optional paid placement. Free listings stay free forever.

Share & Embed

Add our SVG badge (dark/light directory styles) or embeddable widget to your site.