Skip to content

shivsarthak/holdfast

Repository files navigation

Holdfast icon

Holdfast

Dropbox-simple file storage you can self-host in minutes —
and that stays fast even with lots of files.

Status License: AGPL-3.0 Go SvelteKit

Holdfast is a self-hosted file storage service you run as a single Docker image (or build yourself into a single static binary). Upload, browse, organize, and share files through a fast, browser-first web dashboard — no desktop app, no sync client, nothing to install on your machine. No external database, no object store, no cloud dependencies — just SQLite and a directory on disk.

Holdfast dashboard — grid view with image thumbnails
Photo grid with generated thumbnails Dashboard in dark mode
Share-link dialog Sign-in page in dark mode

Project status

  • ⚠️ The project is under very active development.
  • ⚠️ Expect bugs and breaking changes.
  • ⚠️ Do not use Holdfast as the only place you store important files.
  • ⚠️ Always follow the 3-2-1 backup plan for data you care about!

Is Holdfast for you?

For you if:

  • You want a Dropbox-like web dashboard for files, self-hosted, with no monthly fee.
  • You're comfortable running a Docker container (or a Go binary) on a home server, NAS, or VPS you control.
  • You mainly upload, browse, and share files through the browser — on desktop or mobile web.
  • You're fine tolerating an early-stage project and keeping real backups.

Not for you if:

  • You need a desktop or mobile app that keeps a local folder in sync with the server — Holdfast has no sync client, and none is planned (see Non-goals).
  • You need real-time collaborative editing, groupware, or federation.
  • You need this to be rock-solid today — the project is under active development and the API/schema can still change between releases.

Features

  • Web dashboard — a polished SvelteKit app with grid/list views, drag-and-drop upload, multi-select, keyboard navigation, and full dark mode.
  • Resumable uploads — chunked uploads over the tus protocol; interrupted transfers resume from the last good chunk, even for very large files.
  • Share links — anonymous, unguessable capability URLs for any file or folder. Recipients need no account; owners can revoke a link at any time.
  • Trash with retention — deletes are soft; items are restorable until a configurable background purge removes them for good.
  • Previews — thumbnails are generated asynchronously after upload. Images are handled in-process; video and PDF previews use ffmpeg/pdftoppm when available and degrade gracefully to type icons when not.
  • Search — instant filename search across your own files and folders.
  • Multi-user — an admin bootstraps the instance and creates accounts; every user gets a private file tree. No open registration.
  • Self-healing — the database is authoritative and the on-disk tree mirrors it; a background reconcile scan detects and repairs drift between the two.
  • Zero-config first run — start the binary, open the browser, create the admin account. Configuration is optional environment variables.

Quick start

Docker (recommended)

Create a directory and download the two deployment files from the latest release:

mkdir holdfast && cd holdfast
curl -LO https://github.com/shivsarthak/holdfast/releases/latest/download/compose.yaml
curl -L https://github.com/shivsarthak/holdfast/releases/latest/download/env.example -o .env
docker compose up -d

Open http://localhost:8080. On the first boot, Holdfast detects that no Admin exists and redirects you to the one-time setup screen. Create the initial Admin User there; this account can create and manage all other Users. As soon as the Admin is created, bootstrap closes and cannot be used to create another Admin. Subsequent visits show the normal login screen. The named volume persists the database, Files, Trash, and Preview cache across container replacements.

To update later:

docker compose pull
docker compose up -d --remove-orphans

For anything reachable beyond localhost, edit .env and set the public URL to the HTTPS address users open:

HOLDFAST_PUBLIC_BASE_URL=https://files.example.com

By default, Compose keeps all persistent state in the managed holdfast-data volume. To store it directly in a host directory, create the directory and set HOLDFAST_DATA_PATH in .env:

mkdir -p /srv/holdfast/data

The process inside the container runs as an unprivileged User with UID/GID 10001, never as root. A bind-mounted host directory keeps its host permissions though, so on first start the container's entrypoint fixes ownership of the mounted directory (a one-time step that needs no sudo from you) before dropping to UID 10001. No manual chown is required.

HOLDFAST_DATA_PATH=/srv/holdfast/data

The database, Files, Trash, Upload state, and Preview cache will then be visible under /srv/holdfast/data. See the deployment guide before converting an existing named-volume installation.

For a compact homelab installation, keep the data beside compose.yaml and .env:

holdfast/
├── compose.yaml
├── .env
└── data/

From inside the holdfast directory:

mkdir data

Then set the relative path in .env:

HOLDFAST_DATA_PATH=./data

Compose resolves ./data relative to the directory containing compose.yaml.

Single binary

There's no prebuilt binary download — releases currently only publish the container image. Build one yourself; requires Go 1.24+, Node.js 24, and pnpm 10:

make build
./build/holdfast

The binary embeds the frontend and serves everything on http://localhost:8080, writing state to ./data. Without ffmpeg/pdftoppm on PATH it still runs; image previews keep working and other formats show type icons.

Configuration

Holdfast boots with no configuration. Everything is tunable via environment variables:

Variable Default Description
HOLDFAST_PORT 8080 TCP port for the HTTP server.
HOLDFAST_DATA_DIR data Directory for the database and all file state.
HOLDFAST_PUBLIC_BASE_URL http://localhost:${PORT} Browser-facing URL for share links and cookies.
HOLDFAST_TRASH_RETENTION 720h How long trashed items stay before purge.
HOLDFAST_TRASH_PURGE_INTERVAL 1h How often the trash purge runs (0s disables).
HOLDFAST_RECONCILE_INTERVAL 1h How often reconcile scans run (0s disables).

See the configuration guide for details and the deployment guide for reverse-proxy (TLS), systemd, Docker Compose, and backup instructions.

Documentation

Guide Contents
Configuration Every environment variable, data directory layout.
Deployment Docker, Compose, systemd, reverse proxies, backups, upgrades.
Architecture How the pieces fit: DB-as-truth, uploads, previews, reconcile.
HTTP API Full endpoint reference and a curl walkthrough.
Development Building, testing, and repository layout for contributors.
Releases Versioning, image tags, prereleases, and the release checklist.
Product context Domain glossary and v1 scope.
Frontend The SvelteKit app: dev server, design system, e2e tests.

How it works

The SQLite database is the source of truth for the file and folder tree; the directory tree under the data directory is a faithful mirror of it. That makes your data transparent — files sit on disk under their real names, ready for standard backup tools — while renames, moves, and shares stay instant and consistent because they are database operations. A background reconcile scan (startup, interval, and on-demand) detects drift between the two and repairs the database to match reality.

data/
  holdfast.db           SQLite database (authoritative)
  files/<user-id>/      mirrored active file/folder tree
  uploads/<user-id>/    in-progress resumable upload chunks
  trash/<user-id>/      soft-deleted content awaiting purge
  previews/<user-id>/   cached preview images

Read more in the architecture guide.

Non-goals (v1)

Holdfast deliberately stays small. Out of scope for now: desktop sync clients, groupware, plugins, real-time collaborative editing, federation, folder ZIP download, anonymous "drop box" upload links, quota enforcement, and share-link expiry/passwords. The full scope is recorded in CONTEXT.md.

Contributing

Contributions are welcome — see CONTRIBUTING.md for how to set up a development environment, run the test suites, and submit changes. Security vulnerabilities should be reported privately to mail@shivsarthak.com (see SECURITY.md) instead of the public tracker.

License

AGPL-3.0. You can use, modify, and self-host Holdfast freely — but if you run a modified version for others over a network, you must make your modified source available to them. This keeps improvements to Holdfast open for everyone.


Made with ⚓ by shivsarthak

About

Self-hosted, Dropbox-simple file storage that ships as a single Docker image or static binary. Fast web dashboard, resumable uploads (tus), shareable links, multi-user, SQLite + local disk - no cloud dependencies.

Topics

Resources

License

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors