Open-source file storage and knowledge platform. A self-hostable alternative to Dropbox and Google Drive — with built-in search, document transcription, and an AI-powered knowledge base.
ls, cd, find, cat, grep, etc. via just-bashlocker/
├── apps/web/ Next.js web app
│ ├── app/ Pages and API routes
│ ├── components/ Shared UI components
│ ├── features/ Feature modules (files, knowledge-bases)
│ ├── server/ tRPC routers, auth, and plugin system
│ └── lib/ Utilities
├── packages/
│ ├── common/ Shared types, validation, constants
│ ├── database/ Drizzle schema and database client
│ ├── email/ Email templates and sending (Resend)
│ └── storage/ Storage provider adapters
├── services/
│ ├── fts/ Full-text search microservice (SQLite FTS5)
│ └── qmd/ Semantic search microservice
├── e2e/ Playwright end-to-end tests
├── docker-compose.yml PostgreSQL + optional search services
└── turbo.json Build pipeline
pnpm install
docker compose up -d
cp .env.example .env
The defaults work out of the box for local development. Edit .env to change the storage provider or add OAuth credentials.
pnpm db:generate
pnpm db:migrate
pnpm dev
Open http://localhost:3000, create an account, and start uploading files.
Locker auto-detects which platform it's running on and adjusts its capabilities accordingly. Persistent runtimes (Docker, Fly.io, Railway) support all features. Serverless runtimes (Vercel) disable long-running operations like store sync and bulk KB ingestion.
Every deployment needs:
BETTER_AUTH_SECRET — generate with openssl rand -base64 32NEXT_PUBLIC_APP_URL — the public URL of your deploymentThe included docker-compose.yml bundles PostgreSQL, migrations, and the web app. This is the fastest way to self-host.
# 1. Clone and configure
git clone https://github.com/zmeyer44/Locker.git && cd Locker
cp .env.example .env
# 2. Set the required secret
# Replace the placeholder in .env or export it:
export BETTER_AUTH_SECRET=$(openssl rand -base64 32)
# 3. Start everything
docker compose up -d
Open http://localhost:3000. Files are stored on a Docker volume (blob_data) by default.
To use S3 or R2 instead of local storage, set BLOB_STORAGE_PROVIDER and the matching credentials in your .env before starting.
To enable optional search services:
docker compose --profile search up -d
Railway provides managed PostgreSQL and persistent disk, so all features work out of the box.
Create a new project and add a PostgreSQL service. Copy the DATABASE_URL.
Add a new service from the Locker repo. Railway will detect the Dockerfile automatically.
Set these environment variables on the web service:
| Variable | Value |
|---|---|
DATABASE_URL | The PostgreSQL connection string from step 1 |
BETTER_AUTH_SECRET | openssl rand -base64 32 |
BETTER_AUTH_URL | Your Railway public URL (e.g. https://locker-production.up.railway.app) |
NEXT_PUBLIC_APP_URL | Same as BETTER_AUTH_URL |
BLOB_STORAGE_PROVIDER | local (default) or s3 / r2 with matching credentials |
If using local storage, attach a volume mounted at /app/local-blobs.
Deploy. Railway runs migrations automatically via the migrate service in Docker Compose, or you can add a deploy command: pnpm db:migrate && node apps/web/server.js.
Fly provides persistent VMs with attached volumes.
Create a PostgreSQL cluster:
fly postgres create --name locker-db
Launch the app from the repo root:
fly launch --dockerfile Dockerfile
Attach the database:
fly postgres attach locker-db
Create a volume for local storage:
fly volumes create blob_data --size 10 --region your-region
Add to fly.toml:
[mounts]
source = "blob_data"
destination = "/app/local-blobs"
Set secrets:
fly secrets set \
BETTER_AUTH_SECRET=$(openssl rand -base64 32) \
BETTER_AUTH_URL=https://your-app.fly.dev \
NEXT_PUBLIC_APP_URL=https://your-app.fly.dev
Run migrations and deploy:
fly deploy
./Dockerfile./app/local-blobs for local file storage.DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL.Vercel runs Next.js on serverless functions. Locker auto-detects this and disables features that require a persistent runtime:
You must use a cloud storage provider (Vercel Blob, S3, or R2).
Import the repo into Vercel.
Set the framework preset to Next.js and the root directory to apps/web.
Add a PostgreSQL database (Vercel Postgres, Neon, Supabase, etc.) and set DATABASE_URL.
Set environment variables:
| Variable | Value |
|---|---|
BETTER_AUTH_SECRET | openssl rand -base64 32 |
BETTER_AUTH_URL | Your Vercel deployment URL |
NEXT_PUBLIC_APP_URL | Same as BETTER_AUTH_URL |
BLOB_STORAGE_PROVIDER | vercel (recommended) or s3 / r2 |
BLOB_READ_WRITE_TOKEN | From Vercel Blob (if using vercel provider) |
Deploy. Run migrations manually or via a build command: pnpm db:migrate && pnpm build.
Locker detects the hosting platform automatically from environment variables (VERCEL, FLY_REGION, RAILWAY_ENVIRONMENT, etc.). If detection is wrong or you want to test serverless behavior locally, set:
LOCKER_RUNTIME_ENV=vercel # or: docker, fly, railway, render, development
Set BLOB_STORAGE_PROVIDER in .env to configure the default storage backend for new workspaces:
| Provider | Value | Required Env Vars |
|---|---|---|
| Local filesystem | local | LOCAL_BLOB_DIR |
| AWS S3 | s3 | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET |
| Cloudflare R2 | r2 | R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET |
| Vercel Blob | vercel | BLOB_READ_WRITE_TOKEN |
Workspace admins can attach additional stores from Settings > Stores. Each store can be configured as:
Stores use their own credentials (BYOB), so different teams can bring different backends. A primary store is designated per workspace for new uploads; replicas receive copies automatically.
Locker ships with a built-in plugin system. Plugins are installed per-workspace and can add search, transcription, file actions, and more.
| Plugin | Description |
|---|---|
| QMD Search | Semantic document search powered by QMD embeddings |
| Full-Text Search | Lightweight SQLite FTS5 search — no external service required |
| Document Transcription | AI-powered OCR for images and PDFs, making non-text files searchable |
| Google Drive Sync | Import files from and export files to Google Drive |
| Knowledge Base | Build an AI-powered wiki from tagged documents with chat and graph view |
QMD and FTS run as standalone microservices. Enable them with the search Docker Compose profile:
docker compose --profile search up -d
| Command | Description |
|---|---|
pnpm dev | Start all packages in dev mode |
pnpm build | Production build |
pnpm typecheck | Type-check all packages |
pnpm lint | Lint all packages |
pnpm db:generate | Generate a new Drizzle migration |
pnpm db:migrate | Apply pending migrations |
pnpm db:seed | Seed the database |
pnpm format | Format code with Prettier |
Locker includes a read-only virtual filesystem over workspace files/folders, powered by just-bash.
The shell API is available on tRPC router vfsShell:
vfsShell.createSession({ cwd? }) → create a workspace-scoped shell sessionvfsShell.exec({ sessionId, command, timeoutMs? }) → run a bash commandvfsShell.session({ sessionId }) → get session cwd + expiryvfsShell.closeSession({ sessionId }) → close a sessionImplementation details:
folders + files and cached in memory.rm, mv, redirections, etc.) fail with EROFS (read-only filesystem).MIT
(top 24 of 27)
741 followers · starred Apr 2026
1,198 followers · starred Apr 2026
8 followers · starred Apr 2026
122 followers · starred Jun 2026
Open-source file storage and knowledge platform. A self-hostable alternative to Dropbox and Google Drive — with built-in search, document transcription, and an AI-powered knowledge base.
ls, cd, find, cat, grep, etc. via just-bashlocker/
├── apps/web/ Next.js web app
│ ├── app/ Pages and API routes
│ ├── components/ Shared UI components
│ ├── features/ Feature modules (files, knowledge-bases)
│ ├── server/ tRPC routers, auth, and plugin system
│ └── lib/ Utilities
├── packages/
│ ├── common/ Shared types, validation, constants
│ ├── database/ Drizzle schema and database client
│ ├── email/ Email templates and sending (Resend)
│ └── storage/ Storage provider adapters
├── services/
│ ├── fts/ Full-text search microservice (SQLite FTS5)
│ └── qmd/ Semantic search microservice
├── e2e/ Playwright end-to-end tests
├── docker-compose.yml PostgreSQL + optional search services
└── turbo.json Build pipeline
pnpm install
docker compose up -d
cp .env.example .env
The defaults work out of the box for local development. Edit .env to change the storage provider or add OAuth credentials.
pnpm db:generate
pnpm db:migrate
pnpm dev
Open http://localhost:3000, create an account, and start uploading files.
Locker auto-detects which platform it's running on and adjusts its capabilities accordingly. Persistent runtimes (Docker, Fly.io, Railway) support all features. Serverless runtimes (Vercel) disable long-running operations like store sync and bulk KB ingestion.
Every deployment needs:
BETTER_AUTH_SECRET — generate with openssl rand -base64 32NEXT_PUBLIC_APP_URL — the public URL of your deploymentThe included docker-compose.yml bundles PostgreSQL, migrations, and the web app. This is the fastest way to self-host.
# 1. Clone and configure
git clone https://github.com/zmeyer44/Locker.git && cd Locker
cp .env.example .env
# 2. Set the required secret
# Replace the placeholder in .env or export it:
export BETTER_AUTH_SECRET=$(openssl rand -base64 32)
# 3. Start everything
docker compose up -d
Open http://localhost:3000. Files are stored on a Docker volume (blob_data) by default.
To use S3 or R2 instead of local storage, set BLOB_STORAGE_PROVIDER and the matching credentials in your .env before starting.
To enable optional search services:
docker compose --profile search up -d
Railway provides managed PostgreSQL and persistent disk, so all features work out of the box.
Create a new project and add a PostgreSQL service. Copy the DATABASE_URL.
Add a new service from the Locker repo. Railway will detect the Dockerfile automatically.
Set these environment variables on the web service:
| Variable | Value |
|---|---|
DATABASE_URL | The PostgreSQL connection string from step 1 |
BETTER_AUTH_SECRET | openssl rand -base64 32 |
BETTER_AUTH_URL | Your Railway public URL (e.g. https://locker-production.up.railway.app) |
NEXT_PUBLIC_APP_URL | Same as BETTER_AUTH_URL |
BLOB_STORAGE_PROVIDER | local (default) or s3 / r2 with matching credentials |
If using local storage, attach a volume mounted at /app/local-blobs.
Deploy. Railway runs migrations automatically via the migrate service in Docker Compose, or you can add a deploy command: pnpm db:migrate && node apps/web/server.js.
Fly provides persistent VMs with attached volumes.
Create a PostgreSQL cluster:
fly postgres create --name locker-db
Launch the app from the repo root:
fly launch --dockerfile Dockerfile
Attach the database:
fly postgres attach locker-db
Create a volume for local storage:
fly volumes create blob_data --size 10 --region your-region
Add to fly.toml:
[mounts]
source = "blob_data"
destination = "/app/local-blobs"
Set secrets:
fly secrets set \
BETTER_AUTH_SECRET=$(openssl rand -base64 32) \
BETTER_AUTH_URL=https://your-app.fly.dev \
NEXT_PUBLIC_APP_URL=https://your-app.fly.dev
Run migrations and deploy:
fly deploy
./Dockerfile./app/local-blobs for local file storage.DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL.Vercel runs Next.js on serverless functions. Locker auto-detects this and disables features that require a persistent runtime:
You must use a cloud storage provider (Vercel Blob, S3, or R2).
Import the repo into Vercel.
Set the framework preset to Next.js and the root directory to apps/web.
Add a PostgreSQL database (Vercel Postgres, Neon, Supabase, etc.) and set DATABASE_URL.
Set environment variables:
| Variable | Value |
|---|---|
BETTER_AUTH_SECRET | openssl rand -base64 32 |
BETTER_AUTH_URL | Your Vercel deployment URL |
NEXT_PUBLIC_APP_URL | Same as BETTER_AUTH_URL |
BLOB_STORAGE_PROVIDER | vercel (recommended) or s3 / r2 |
BLOB_READ_WRITE_TOKEN | From Vercel Blob (if using vercel provider) |
Deploy. Run migrations manually or via a build command: pnpm db:migrate && pnpm build.
Locker detects the hosting platform automatically from environment variables (VERCEL, FLY_REGION, RAILWAY_ENVIRONMENT, etc.). If detection is wrong or you want to test serverless behavior locally, set:
LOCKER_RUNTIME_ENV=vercel # or: docker, fly, railway, render, development
Set BLOB_STORAGE_PROVIDER in .env to configure the default storage backend for new workspaces:
| Provider | Value | Required Env Vars |
|---|---|---|
| Local filesystem | local | LOCAL_BLOB_DIR |
| AWS S3 | s3 | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET |
| Cloudflare R2 | r2 | R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET |
| Vercel Blob | vercel | BLOB_READ_WRITE_TOKEN |
Workspace admins can attach additional stores from Settings > Stores. Each store can be configured as:
Stores use their own credentials (BYOB), so different teams can bring different backends. A primary store is designated per workspace for new uploads; replicas receive copies automatically.
Locker ships with a built-in plugin system. Plugins are installed per-workspace and can add search, transcription, file actions, and more.
| Plugin | Description |
|---|---|
| QMD Search | Semantic document search powered by QMD embeddings |
| Full-Text Search | Lightweight SQLite FTS5 search — no external service required |
| Document Transcription | AI-powered OCR for images and PDFs, making non-text files searchable |
| Google Drive Sync | Import files from and export files to Google Drive |
| Knowledge Base | Build an AI-powered wiki from tagged documents with chat and graph view |
QMD and FTS run as standalone microservices. Enable them with the search Docker Compose profile:
docker compose --profile search up -d
| Command | Description |
|---|---|
pnpm dev | Start all packages in dev mode |
pnpm build | Production build |
pnpm typecheck | Type-check all packages |
pnpm lint | Lint all packages |
pnpm db:generate | Generate a new Drizzle migration |
pnpm db:migrate | Apply pending migrations |
pnpm db:seed | Seed the database |
pnpm format | Format code with Prettier |
Locker includes a read-only virtual filesystem over workspace files/folders, powered by just-bash.
The shell API is available on tRPC router vfsShell:
vfsShell.createSession({ cwd? }) → create a workspace-scoped shell sessionvfsShell.exec({ sessionId, command, timeoutMs? }) → run a bash commandvfsShell.session({ sessionId }) → get session cwd + expiryvfsShell.closeSession({ sessionId }) → close a sessionImplementation details:
folders + files and cached in memory.rm, mv, redirections, etc.) fail with EROFS (read-only filesystem).MIT
(top 24 of 27)
741 followers · starred Apr 2026
1,198 followers · starred Apr 2026
8 followers · starred Apr 2026
122 followers · starred Jun 2026