Back

R2 Manager

A self-hosted file manager for your Cloudflare R2 buckets — browse, upload, preview, edit, and share from the browser.

R2 Manager
TypeScriptReactHonoPostgreSQLDrizzleTailwindDocker

Cloudflare R2 is cheap, fast object storage, but the dashboard is built for operators, not for the people who actually need the files. R2 Manager is the missing front end: a file manager you host yourself, where you own the server, the database, and the keys.

What it does

  • Browse, upload, preview — list and grid views, folders, filtering, and drag-and-drop for whole folders. Images, PDF, Markdown, CSV, and JSON preview in place without a download.
  • Edit in the browser — text, Markdown, CSV, and JSON are editable, with ETag conflict detection so two people never silently overwrite each other.
  • Share links — public links with an optional password, expiry, and download limit, revocable at any time. Files stream through the app or via short-lived presigned URLs.
  • Roles and grants — admin, editor, and viewer roles, scoped to a whole bucket or just a folder prefix.
  • Sign-in and security — email and password with TOTP 2FA and recovery codes, or Cloudflare Access in front. Brute-force limits on login, 2FA, and reset; same-origin checks on every mutation; a strict CSP on share pages; and secrets encrypted at rest.
  • Audit trail — every action is logged with its actor, target, and outcome, searchable from the admin area.

How it's built

The UI is React 19 with Vite, TanStack Query, Tailwind v4, and shadcn/ui. A single Hono server on Node serves the UI, the API, and the share pages. Uploads never pass through it: the server starts a multipart upload and signs the part URLs, and the browser sends the bytes straight to R2 — so file size isn't capped by the server.

PostgreSQL, through Drizzle, holds users, grants, share links, the audit log, and settings, and also backs the rate limits and job state, so there's no Redis or queue to run. Migrations apply on every start. A two-stage Dockerfile ships an esbuild bundle with no node_modules at runtime, and it deploys with Docker Compose (with Caddy for automatic HTTPS), Dokploy, or Vercel.

Postgres is the only thing you need to back up.