Skip to content

Run a hub

Self-hosting is a first-class, fully supported path forever: AGPL, no features held back. One static Go binary, one config file, any object store (or a plain directory).

Terminal window
brew install runbear-io/tap/beardrive # macOS / Linuxbrew
# or: go install github.com/runbear-io/beardrive/cmd/bdrive@latest
# or: a release tarball — https://github.com/runbear-io/beardrive/releases

Any of s3://bucket/prefix, gs://bucket/prefix, an S3-compatible endpoint, or — simplest for a first run — a plain directory (file:///var/lib/bdrive/storage).

Files and change journals live there. Hub metadata (accounts, projects, orgs) lives in the database you pick in step 3. Clients never see this storage; they sync through the hub over HTTPS.

Credentials use each provider’s standard chain — nothing BearDrive-specific:

Storage Credentials
s3://bucket/prefix AWS_PROFILE, ~/.aws/credentials, env vars, IAM roles. S3-compatible stores via AWS_ENDPOINT_URL.
gs://bucket/prefix Application Default Credentials (gcloud auth application-default login) or GOOGLE_APPLICATION_CREDENTIALS.
file:///path none — any local or network-mounted directory
{
"remote": "file:///var/lib/bdrive/storage",
"addr": ":4173",
"upload": true,
"auth": {
// Signup is invite-only by default — the safe posture for a public URL.
// Your first account: start once with signup gated (or use an org
// invite), then invite teammates from the web UI.
"admins": ["you@example.com"],
"users_db": "/var/lib/bdrive/auth.json"
},
"reads": { "enabled": true }, // agent read analytics (Insights)
"database": { "driver": "sqlite", "dsn": "/var/lib/bdrive/hub.db" }
}

Every knob: Hub config. Signup postures and SMTP: Authentication. Storage for metadata: Database.

Terminal window
bdrive web -c config.json

Put TLS in front — Caddy, nginx, or your platform’s load balancer. Device tokens travel as bearer tokens.

For containers, the repository ships a Dockerfile (distroless, CGO-free) with a Cloud Run recipe in deploy/. Any container platform works the same way.

  1. Open https://your-hub/ and create your account. Use the signup posture you configured; hub admins are the admins emails.
  2. On any machine, bdrive login https://your-hub, then in the folder you want synced: bdrive init --name wiki --yes — or --shared docs inside a repository to sync only that subfolder.
  3. Invite a teammate: sidebar footer → ManageNew invite. The join link both creates their account and adds them to your org.
  4. Connect agents: the project’s home page shows one-paste setup for Claude Code, Hermes, and Codex, with the hub URL and project id already filled in. See Set up with your agent.

In hub mode the server hosts many projects on one storage root. Each project’s data lives under its own prefix (<root>/<project-id>/), and a registry maps project ids to names. Client devices sync whole folders through the hub without ever knowing where the storage is or holding cloud credentials — the server is the only machine configured with the bucket.

Projects are walled by organization. Every project belongs to one org, and only that org’s members — accounts with the owner or member role — can see, browse, or sync it. Your first bdrive init creates an org automatically; an owner invites teammates from the web UI (the org name in the sidebar footer → Invite mints an expiring /join/<token> link). Public share links stay outside the wall on purpose.

A hub upgraded from a pre-org version sweeps its existing projects into a default org that all existing accounts join, so nothing breaks.

Everything irreplaceable is in two places: the storage root (blobs and journals — files and their entire history) and the metadata database (accounts, projects, orgs, shares). Snapshot both; restore is copy-back.

brew upgrade beardrive. Clients and hub are the same binary — keep them roughly in step. The sync protocol is append-only journals plus blobs, which old clients read forward.