Homelab storage, file explorer, embeddable picker, Relay users, and SMB integration. Planning scaffold.
  • Rust 49.3%
  • JavaScript 26.6%
  • Svelte 10%
  • CSS 7.4%
  • Python 5.5%
  • Other 1.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-14 17:39:19 +02:00
docs Fix mobile virtual table widths and touch double-tap opening 2026-10-14 17:39:19 +02:00
frontend Fix mobile virtual table widths and touch double-tap opening 2026-10-14 17:39:19 +02:00
reviews Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
scripts Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
src Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
static Fix mobile virtual table widths and touch double-tap opening 2026-10-14 17:39:19 +02:00
tests Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
.dockerignore Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
.env.example Fix upload contention and large queues, sync pins, and improve previews 2026-10-13 16:30:00 +02:00
.gitignore Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
.prettierignore Refactor Vault into domain modules and stabilize responsive explorer 2026-10-13 12:21:22 +02:00
.prettierrc.json Refactor Vault into domain modules and stabilize responsive explorer 2026-10-13 12:21:22 +02:00
AGENTS.md Refactor Vault into domain modules and stabilize responsive explorer 2026-10-13 12:21:22 +02:00
bugs.md Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
Cargo.lock Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
Cargo.toml Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
compose.dev-local.yml Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
compose.dev.yml Fix upload contention and large queues, sync pins, and improve previews 2026-10-13 16:30:00 +02:00
compose.local.yml Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
compose.slow.yml Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
compose.smb.yml Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
compose.yml Fix upload contention and large queues, sync pins, and improve previews 2026-10-13 16:30:00 +02:00
DESIGN.md Complete explorer features and independent split workspaces 2026-10-12 23:31:03 +02:00
Dockerfile Harden storage operations and virtualize explorer file lists 2026-10-14 15:22:38 +02:00
FEATURE-IDEAS.md Complete explorer features and independent split workspaces 2026-10-12 23:31:03 +02:00
LICENSE Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
NOTICE Implement Vault explorer, storage administration, and documented demos 2026-10-12 13:59:39 +02:00
package-lock.json Fix upload contention and large queues, sync pins, and improve previews 2026-10-13 16:30:00 +02:00
package.json Fix upload contention and large queues, sync pins, and improve previews 2026-10-13 16:30:00 +02:00
pyproject.toml Refactor Vault into domain modules and stabilize responsive explorer 2026-10-13 12:21:22 +02:00
README.md Add experimental archive upload batches and improve explorer responsiveness 2026-10-13 22:33:02 +02:00
requirements-dev.txt Refactor Vault into domain modules and stabilize responsive explorer 2026-10-13 12:21:22 +02:00

Vault

A self-hosted file explorer, storage administration dashboard, embeddable picker, and optional SMB server. Relay owns web identity; Vault manages storage using stable Relay user IDs, SQLite metadata, and filesystem-backed files.

The interface follows Hostwatch and Relay: Cal Sans headings, Inter text, a compact sidebar, flush tables, restrained controls, and persistent light/dark preferences. Fonts are served locally with their SIL Open Font Licenses.

SMB access is stable for managed storage with verified ZFS quotas and encrypted SMB3 clients. Application/picker integrations remain experimental.

Vault file explorer with personal, shared, local, and pinned folders

More demos: Dark theme, Storage settings, Grant storage, and Folder permissions. These images use synthetic accounts and files. To reproduce them, build the frontend, run python3 docs/readme-demo.py, and open http://127.0.0.1:3013 at a 1440 × 1000 viewport. The demo serves the real interface with synthetic fixtures, rejects API writes, and never connects to Relay or a storage database.

Features

  • Fast and optional slow managed storage volumes, with admin-controlled folder creation grants and a combined folder limit, owner-managed sharing permissions, and conversion between personal and shared folders. Folders appear together, with a shared icon only when another user has access.
  • Admin-only linking of existing local host folders, including a configured ~/, with read-only defaults, optional writes, and safe unlinking.
  • Live WebSocket updates for web and filesystem changes, scoped to each user, with automatic reconnect and preservation of unsaved edits.
  • Independent, resizable split explorers with per-pane navigation, search, selections, editors, previews, and bottom status bars. URLs restore both locations, open files, focus, and divider position after refresh.
  • Pinned subfolders, breadcrumb navigation, hidden-file visibility, sortable list and thumbnail grid views, Ctrl/Cmd/Shift selection, and bulk copy, move, trash, ZIP creation, and ZIP download.
  • Cross-storage move/copy with browsable destinations and drag-and-drop onto folders, sidebar roots, or the other pane. Failed copies retain the source.
  • Resumable file and folder uploads with per-file progress, pause, resume, cancellation, and duplicate choices: Ask, Keep both, or Replace. Ask offers Keep both, Replace, or Skip, including conflicts at upload completion.
  • Experimental, opt-in archive upload batches for folder selections: bounded Store ZIPs, durable browser spooling, asynchronous extraction, per-file outcomes and choices, and Resume all. Enable Use archive batches (experimental) in the Upload menu to try them. Performance and browser compatibility are still being evaluated; ordinary uploads remain the default.
  • Search across a folder, storage root, or all accessible storage, with content, type, size, and date filters; Recent files and permission-scoped Activity.
  • Syntax-highlighted UTF-8 editing with conflict-safe saves and independent drafts in split view. Markdown supports edit, split, and rendered preview modes. Text editing and text-content search are limited to 2 MiB.
  • Image/PDF/audio/video, CSV, and ZIP previews; Space for quick preview; previous/next preview navigation; arrow-key and Vim-style file navigation.
  • Create ZIP archives directly in storage and safely extract archives into new folders without downloading or replacing the original ZIP.
  • Retained file revisions, text comparisons, and restore as a copy, including externally observed changes. Retained versions are not independent backups.
  • Expiring, revocable file and folder share links, folder ZIP downloads, and upload requests that keep existing files. Active links are listed separately above revoked and expired links.
  • Open with registered applications using explicit scoped read/write consent.
  • Trash and restore with configurable retention; trash and temporary uploads count toward storage limits. Storage insights show large folders, remaining allowance, trash usage, and backup status.
  • Administrator assignment of homes and quotas, storage usage, pool capacity, permissions, and ownership transfers.
  • Origin-validated open-file, select-folder, and save-as pickers, with file filters, multiple file selection, stable IDs, scoped read/write tokens, and revocation.
  • Optional Samba access to the same files, separate SMB passwords, share permissions, individual and aggregate ZFS kernel quotas, reconciliation of external file changes, and copy buttons for usernames and share names.
  • Docker Compose deployment through Relay, with configurable Debian/ZFS host integration and no privileged application container.

Using the explorer

Click an item to select it, click again to deselect it, and double-click or press Enter to open it. Ctrl/Cmd-click toggles individual items, Shift-click selects a range, and Select all changes to Clear when all visible items are selected. Bulk actions appear alongside the existing creation and upload controls. Hold the actions button, move to a menu option, and release to activate it; normal clicking and keyboard menu navigation also work.

Use the split icon to open two normal explorers side by side. Click either pane to focus it; sidebar navigation applies to that pane. Drag the divider to resize, use its arrow keys for keyboard resizing, or double-click it to reset the split. Files open within their pane, with filenames in the breadcrumb path. Preview navigation stays at the pane bottom and skips files that need the text editor. Press Space on a selected file for a quick preview; text previews offer Open editor. Arrow keys and h/j/k/l navigate files; g/G jumps to the first/last item.

Upload offers files and folders from one menu. Settings → Transfers shows progress and controls each upload. Up to three files upload in parallel; chunks within each file stay sequential. Active and queued transfers appear first, followed by the most recently updated transfers. Sessions last 24 hours; after refreshing, select the same files again in the original destination to resume. Duplicate handling uses readable choice buttons, and interrupted uploads retain completed chunks. Cancel discards the unfinished session. Clipboard and pane-copy actions show a brief checkmark after success.

Pinned folders are saved per member on the server and sync across signed-in devices. Existing browser pins are imported once when that browser next opens Vault. The Transfers panel offers Resume all for queued, paused, and failed uploads; after a page reload, reselect the original files to resume their saved sessions. Failures retain their reason and show guidance for storage limits, access problems, and interrupted connections. Large folder selections are prepared in batches, and transfer history is paginated. Resume information is saved asynchronously in browser storage; existing saved sessions migrate on the next visit.

Settings also contains Storage insights and Share links. Create or revoke links explicitly; sharing a folder downloads it as a ZIP. Configure Relay's Public with members mode if guests should use these tokenized links. Vault still requires sign-in and storage permissions for ordinary browsing and management. Members-only Relay ingress additionally requires recipients to sign in.

See Explorer features for detailed recovery, archive, transfer, search, and application-integration limits.

Install

Use a Debian host with Docker Compose, an existing OpenZFS pool, Python 3, curl, systemd, and Relay. All dataset names, host paths, origins, networks, and SMB endpoints are installation settings. The project contains no workstation configuration. See deployment instructions and environment template.

Deploy the web service with docker compose up -d --build after configuring the host identity/quota sync service and .env. Register the upstream through Relay using Members access, grant members access to the production environment, then sign in, open Settings → Storage, and grant your Relay user fast and/or slow storage allowances. Then create a personal folder on a volume with an allowance. Users start with no allowance or home by default. SMB is disabled by default and requires the optional Compose overlay with an explicit LAN/VPN endpoint. Set a separate SMB password in Settings → Desktop access, then copy the username and storage share name to connect from your desktop. See the SMB and Linux client instructions.

Picker/API

See picker integration for embedding, origin validation, postMessage contracts, and selected-resource API calls. Other applications receive IDs and metadata, never host filesystem paths. Use X-Vault-Token for API calls through Relay. Users can revoke grants in Settings → App access. Browser integrations use the signed-in picker request bridge. Relay Members or Public with members ingress recognizes the user; Vault enforces the resource grant and current permissions.

Storage and access model

Relay's enabled-user directory is synced locally by a host service. Web requests trust identity only from the actual Relay connection peer. Users cannot browse other homes; administrator status permits storage configuration, not implicit access to their contents. Disabled/deleted users lose access while their files remain available for administrator-directed transfer.

Administrators grant per-user Fast and Slow allowances without creating folders. Users or administrators can then create personal or shared folders on each granted volume, with a fixed folder limit or Unlimited within the allowance. Folder limits are independent ceilings: multiple unlimited folders and overlapping fixed limits share the owner's total allowance on that volume. Existing managed folders keep their placement and limits; upgrades preserve their existing allowances. The optional slow volume setup adds separate capacity and per-volume homes without moving existing files.

Each managed root has its own immutable filesystem UID. Logical byte limits are enforced by Vault; the ZFS helper sets matching per-UID folder quotas and per-owner group quotas, which also cover SMB writes. Shared files charge their folder owner's allowance. Quotas do not reserve disk space. ZFS allocated-space accounting may differ from the explorer's logical byte totals. See quota and backup details.

Administrators can link existing folders in Settings → Storage → Create folder → Local folder when the optional local folder deployment is configured. Links expose the original files without moving or copying them and start read-only. The selected owner and explicit sharing grants determine access; administrators do not gain implicit access to another owner's contents. ~/ means the configured host home, rather than the browser user's home. Write-enabled links modify the actual host files. Existing file ownership and mode bits are preserved when editing; new files inherit their parent folder's ownership. Unlinking removes Vault metadata and grants while leaving local files on disk. Linked folders have no quota and are excluded from ZFS quota provisioning and SMB shares. Include linked folders in your own backups. Symlinks and special files are excluded from the explorer.

The Rust rewrite retains the existing SQLite schema, storage root IDs, filesystem UIDs, files, permissions, and grants. Back up files and metadata before upgrading.

Current boundaries: arbitrary external SMB mounts are not supported, and web writes do not participate in Samba advisory locks. Retained file revisions are not independent backups; include revision storage in capacity and backup planning. External changes to indexed files are observed in a background worker, so intermediate writes between observations may not be recoverable. Browser edits compare a content revision before saving; this detects completed external changes but cannot coordinate writes from an SMB handle already open during the save. SMB recycle preserves names rather than original directory paths. Use SMB3 clients for mandatory transport encryption. Relay and host sync must remain available for access.

Development and checks

The HTTP backend uses Rust, Axum, and SQLite. The frontend uses Svelte 5 components and reactive state, shared CSS, and locally bundled CodeMirror, Marked, and DOMPurify. Rust authenticates each page request and prepares its initial route, including split panes, open files, previews, and settings. A bundled Svelte server renderer produces the requested page, and the browser hydrates that content without first showing a different folder or rebuilding the layout. Node.js runs the renderer in the application container and builds the frontend. JavaScript assets are fingerprinted and precompressed, while settings, dialogs, and the editor load on demand. The host quota and optional Samba provisioning helpers use Python's standard library; the web service has no Python backend.

cargo test --locked
cargo clippy --all-targets --locked -- -D warnings
npm ci
npm run build
npm run check
npm test
python3 -m py_compile scripts/*.py tests/*.py
docker compose config --quiet
docker compose build

For an isolated preview, use compose.dev.yml with VAULT_DEV_ORIGIN, VAULT_DEV_FAST_FILES, VAULT_DEV_SLOW_FILES, and VAULT_DEV_IDENTITY set to private development values. The identity directory must contain a fresh host-synced users.json including the dev origin for permitted users. Register VAULT_DEV_ALIAS (default vault-dev) with Relay using Members access and grant intended members access to that dev environment. The development container rebuilds and restarts on source edits.

Run the optional Samba integration in a separate container without networking, host ports, or production mounts:

docker run --rm --network none --cap-drop ALL \
  --cap-add CHOWN --cap-add DAC_OVERRIDE --cap-add FOWNER \
  --cap-add SETUID --cap-add SETGID \
  --tmpfs /state --tmpfs /files --tmpfs /slow-files --tmpfs /identity \
  --tmpfs /run/samba --tmpfs /var/log/samba \
  -e RUN_SMB_TEST=1 -e VAULT_STATE=/state -e VAULT_FILES=/files \
  -e VAULT_SLOW_FILES=/slow-files -e VAULT_DIRECTORY=/identity/users.json \
  -v "$PWD:/workspace:ro" -w /workspace --entrypoint python3 vault-app \
  -m unittest discover -s tests -p test_smb.py -v

This exercises encrypted SMB3 transfers, immutable file ownership, read-only permissions, recycling, disabled-user access, and stale-quota fail-closed behavior.

Rust tests use disposable synthetic identities and temporary files. They cover identity isolation, permissions, quotas, failed-upload cleanup, paths/symlinks, downloads/ranges, trash and stable IDs, external renames, retention, app grant scope/revocation, folder creation, and conflicting writes. They do not alter a Relay deployment or enable SMB. Kernel quota and live Samba testing additionally require a dedicated disposable ZFS dataset; do not test against user files.

See DESIGN.md for the original shared visual reference. Contributions should preserve both themes, accessible dialogs, and phone layouts. Keep secrets, private paths, real identities, and installation details outside tracked files.

Contributor documentation

See docs/ARCHITECTURE.md for module ownership, docs/CONTRIBUTING.md for editing and verification, and bugs.md for known issues. Automated contributors must follow AGENTS.md.

License

Apache License 2.0. See LICENSE, NOTICE, and the vendored font licenses in static.