Back to Projects
Zero Locker cover image

Zero Locker

A self-hosted, open-source password manager built with Next.js 15, TypeScript, Prisma, and Neon Postgres — encrypting credentials, payment cards, and secrets with AES-256-GCM behind a type-safe oRPC API and BetterAuth authentication.

🔐 Zero Locker — A Self-Hosted, Open-Source Password Manager

Zero Locker is a self-hosted, open-source password management solution I built to give people full control over their credentials, payment cards, and secrets without trusting a third-party vault. The entire codebase — server, database schema, and encryption logic — is public on GitHub, so anyone can audit exactly how their data is handled instead of taking a vendor's word for it.


🌟 The Problem

Most password managers ask you to trust a closed-source, cloud-hosted vault with your most sensitive data. I wanted an option that was:

  • Auditable — open-source, so the encryption and storage logic can be inspected line by line
  • Self-hostable — runs on your own infrastructure instead of a vendor's servers
  • Not just passwords — credentials, payment cards, and arbitrary secrets (API keys, SSH keys, tokens) in one place
  • Modern to use — a fast, well-designed dashboard rather than a dated enterprise UI

✨ Core Features

Straight from the project's own feature set:

  • End-to-end encryption — AES-256-GCM for all sensitive fields
  • Credential storage — usernames, passwords, and per-credential metadata (recovery email, phone number, whether 2FA is enabled)
  • Payment card management — card number and CVV stored encrypted, alongside card metadata like credit limit, rewards program, and contactless/international payment flags
  • Secret storage — typed secrets (API keys, database URLs, SSH keys, JWT secrets, OAuth tokens, webhook secrets, general tokens) with expiry tracking
  • Containers — group credentials, cards, and secrets into folders; a container can be restricted to a single entity type, including a secrets-only mode built for exporting environment variables
  • Platforms — credentials are linked to a platform (e.g. a specific service), with a review workflow (approved/pending/rejected) for platforms submitted by users
  • Password history — automatic tracking of credential changes over time
  • Tagging — custom tags across credentials, cards, and secrets
  • Authentication — session and account management via BetterAuth
  • Dark/light theme, responsive UI — built with Tailwind CSS and shadcn/ui
  • Self-hosted deployment — Docker Compose for a local PostgreSQL instance, with the app itself deployable to Vercel or any Node host

🏗️ Technical Architecture

Data Model

The schema is split into focused Prisma files rather than one monolith — credential.prisma, cards.prisma, secrets.prisma, encryption.prisma, auth.prisma — and centers on a few real design decisions:

  • Credential, Card, and Secret are separate models, each with their own metadata model (CredentialMetadata, CardMetadata, SecretMetadata) rather than one generic "item" table — so a card can carry a credit limit and rewards program while a secret carries a type and expiry date, without either model being forced into a shape it doesn't need.
  • EncryptedData is a shared table (iv, encryptedValue, encryptionKey) referenced by every sensitive field — a credential's password, a card's number and CVV, and a secret's value all point to their own EncryptedData row, so encryption is handled uniformly across entity types instead of being reimplemented per field.
  • Container groups items into folders, with a ContainerType (MIXED, SECRETS_ONLY, CREDENTIALS_ONLY, CARDS_ONLY) — a secrets-only container is what backs environment-variable-style operations.
  • Platform ties a credential to the service it belongs to, with its own approval workflow (APPROVED / PENDING / REJECTED) for platforms added by users rather than pre-seeded.
  • UserPlan distinguishes NORMAL accounts (limited to 3 default containers) from PRO accounts (unlimited containers).

Tech Stack

  • Next.js 15 (App Router, Turbopack dev server) and React 19
  • TypeScript throughout, validated at the boundaries with Zod
  • Prisma ORM 6 over Neon serverless Postgres (@prisma/adapter-neon)
  • oRPC for a type-safe, contract-first API layer between client and server (@orpc/server, @orpc/client, @orpc/react-query)
  • BetterAuth for session and account authentication
  • TanStack Query for client-side data fetching and caching
  • Tailwind CSS and shadcn/ui (Radix primitives) for the interface
  • Resend for transactional email, Vercel Analytics for usage metrics

Security

  • AES-256-GCM encryption applied to every sensitive field before it's written to the database — credential passwords, card numbers and CVVs, and secret values
  • Each encrypted value gets its own record in the shared EncryptedData table with a unique initialization vector, so encryption isn't reused across fields or users
  • Credential password changes are tracked in a separate CredentialHistory model, itself encrypted the same way as the live value

🚀 Self-Hosting

Zero Locker is designed to be run on your own infrastructure:

git clone https://github.com/FindMalek/zero-locker.git
cd zero-locker
pnpm install
cp .env.example .env   # set DATABASE_URL, BETTER_AUTH_SECRET, etc.

pnpm docker:up          # starts a local PostgreSQL 15 container
pnpm db:migrate          # applies the Prisma schema
pnpm dev                 # starts the Next.js dev server on :3000

The included docker-compose.yml handles local Postgres, and the same Prisma schema runs against Neon in production. Project scripts also cover day-to-day operations — docker:status, docker:logs, docker:reset, db:reset-and-seed — for resetting or inspecting the local database during development.


📌 Where It Stands

Zero Locker is open-source, MIT-licensed, and live at zero-locker.com. The codebase is primarily TypeScript, with the full schema, oRPC routers, and UI available for anyone to read, run, or contribute to on GitHub — issues and pull requests are open.

👉 Try Zero Locker 👉 Star on GitHub

zero-locker