โจ Your Credentials. Your Security. Your Rules. โจ
A secure, self-hosted credential management application for storing and organizing your digital credentials with complete privacy and control.
๐ Quick Start โข ๐ผ๏ธ Screenshots โข ๐ฆ Installation โข ๐๏ธ Setup โข ๐ฑ PWA โข ๐ง Troubleshooting
1.3.0 needs a one-time database update if you use Supabase. Please read MIGRATION.md before you update. It takes five minutes and covers every step with expected output and troubleshooting.
SQLite and Neon users, and anyone installing fresh, can skip it.
Desktop installers are available on the Keyper website or on the GitHub releases page.
Scroll down to see other installation options.
- ๐ API Keys - Store and organize your API credentials
- ๐ Login Credentials - Username/password combinations
- ๐คซ Secrets - Sensitive configuration values
- ๐ซ Tokens - Authentication and access tokens
- ๐ Certificates - SSL certificates and keys
- ๐ Documents - Secure file uploads for
.pdf,.doc,.docx,.odt,.txt,.md - ๐งฉ Miscellaneous - Large multiline secure notes/commands/scripts that donโt fit fixed types
- ๐ Categories - Group credentials by service or type
- ๐ Tags - Flexible labeling system
- โก Priority Levels - Low, Medium, High, Critical
- ๐ Expiration Tracking - Never miss renewal dates
- ๐ Real-time Search - Find credentials instantly
- ๐๏ธ Quick Reveal & Copy - Reveal and copy sensitive values directly from the credential detail view
- ๐๏ธ Inline Text Document Preview - Text-like document credentials (
.txt,.md,text/*) can be previewed inline in credential detail view - โฌ๏ธ Secure Document Download - All document credentials can be downloaded from detail view
- ๐ฅ๏ธ Theme Choices - Light, Dark, System, Charcoal, Medium Gray, Light Gray, Warm Light, Blue, Midnight Blue, and Deep Purple appearance modes
- ๐๏ธ Persistent Preferences - Theme and font choices are saved locally and restored across sessions
- ๐งญ Adaptive UI Accents - Core dashboard controls, tags, and backgrounds follow the selected palette
- ๐ Appearance Docs - The website docs include an Appearance Settings guide covering all built-in themes and fonts
- ๐ Row Level Security (RLS) - Every policy is scoped to
TO authenticatedandowner_id = auth.uid(), so the anon key on its own reads nothing - ๐ End-to-End Encryption - AES-256-GCM under a key that only your master passphrase can unwrap
- ๐ค Multi-User Support - Real accounts via Supabase Auth, with per-account vault isolation enforced by the database
- ๐ Secure Connections - HTTPS/TLS encryption
- ๐ Self-Hosted - Complete control over your data
Good to know: encryption covers the secret values themselves. Titles, usernames, URLs, notes, tags and categories are stored as regular text so Keyper can search and sort them. See Security model for what each layer covers.
- Passphrase-Wrapped Vault Key - The key that decrypts your secrets is stored only encrypted under your master passphrase, so a full database dump does not decrypt anything
- AES-256-GCM Encryption - Industry-standard authenticated encryption
- Argon2id Key Derivation - Memory-hard, ASIC-resistant (with PBKDF2 fallback)
- Auto-Lock Protection - 15-minute inactivity timeout with activity detection
- Authenticated Row Access - Supabase Auth session required before the database returns any row
- Legacy Vault Migration - Vaults created before v1.3.0 are re-wrapped automatically on first unlock
- No Passphrase Recovery - There is no stored value that can reset your passphrase, by design
Get Keyper running on your own infrastructure in under 5 minutes!
- Node.js 18+ installed on your system
- Database (choose one):
- ๐๏ธ SQLite (local mode) โ no account or server required, zero configuration, works in browser and Electron desktop
- โ๏ธ Supabase โ free tier works perfectly for hosted/remote/multi-device usage
- ๐ Neon Postgres โ Neon Cloud or Neon Local Docker using a Postgres connection string
- Modern web browser (Chrome, Firefox, Safari, Edge)
# Install Keyper globally
npm install -g @pinkpixel/keyper
# Start the server (default port 4173)
keyper
# Or start with custom port
keyper --port 3000
# Open in your browser
# ๐ http://localhost:4173 (or your custom port)That's it! ๐ Follow the in-app setup wizard to configure your database (choose SQLite for zero-config local storage, Supabase for hosted cloud storage, or Neon for cloud/local Postgres).
Want to try Keyper before installing? Visit our hosted demo:
๐ app.keyper.icu
Just enter your own Supabase credentials and start managing your encrypted credentials instantly! Your data stays completely private since all encryption happens in your browser.
Demo Usage:
- โ Your Keys Stay Yours - Your master passphrase never leaves your browser, and the vault key is stored only in wrapped form
- โ Real Functionality - Full Keyper experience with your own Supabase instance
- โ No External Signup Required - Just bring your Supabase URL and anon/publishable key
- โ In-App User Registration Available - Create multiple isolated user vaults directly inside Keyper
โ ๏ธ Demo Limitations - Recommended for testing and light usage only- ๐ Self-Host for Production - Install locally for best performance and full control
Note: The demo uses the same secure architecture as self-hosted Keyper. Your Supabase credentials are stored only in your browser's localStorage and never transmitted to our servers.
npm install -g @pinkpixel/keyperAvailable Commands:
keyper- Start Keyper serverkeyper --port 3000- Start on custom portkeyper --help- Show help and usagecredential-manager- Alternative commandkeyper-dashboard- Another alternative
npx @pinkpixel/keypergit clone https://github.com/pinkpixel-dev/keyper.git
cd keyper
npm install
npm run build
npm startRun Keyper as a containerised web app โ no Node.js required on the host!
Quick Start (Docker Hub)
docker run -d -p 8080:80 --name keyper --restart unless-stopped pinkpixeldev/keyper:latestBuild Locally (Docker Compose)
# Clone the repo
git clone https://github.com/pinkpixel-dev/keyper.git
cd keyper
# Build & start (serves on http://localhost:8080)
docker compose up -d
# Or on a custom port
HOST_PORT=3030 docker compose up -d
# Force rebuild after source changes
docker compose up -d --build
# Stop
docker compose down
# Follow logs
docker compose logs -fNote: Keyper stores all configuration (Supabase credentials, Neon connection strings, or SQLite provider selection) in browser
localStorageโ no environment variables or volumes are required.
Run Keyper as a native desktop app on Windows or Linux!
| Platform | Package | Download |
|---|---|---|
| Windows | NSIS installer | Keyper.Setup.v1.2.2-win-x64.exe |
| Linux | AppImage (ARM64) | Keyper-1.2.2-arm64.AppImage |
| Linux | AppImage (AMD64) | Keyper-1.2.2-x86_64.AppImage |
| Linux (Debian/Ubuntu) | .deb (x86_64) |
keyper_1.2.2_amd64.deb |
| Linux (Debian/Ubuntu) | .deb (ARM64) |
keyper_1.2.2_arm64.deb |
git clone https://github.com/pinkpixel-dev/keyper.git
cd keyper
npm install
npm run electron:preview# desktop packaging from source
npm run electron:build:linux # AppImage + deb
npm run electron:build:win # NSIS installerInstallers are output to dist-electron/.
If you already use Keyper with Supabase, please read MIGRATION.md in full before you start. It is a five-minute read and it walks through every step with expected output and troubleshooting. Keyper also guides you through the same steps in the app.
1.3.0 needs a one-time database update before it will open an existing vault.
- Run the five scripts one at a time, in order. Do not paste them all in together.
- Back up first. Supabase โ Database โ Backups.
- Do not run
sql/supabase-setup.sql. That is for new installs only.
Every script checks itself before changing anything, so running one out of order stops safely and tells you where to go back to. Nothing half-applies.
Keyper now signs you in to an account before opening your vault, and stores your vault key in a stronger form.
- You sign in with an email and password. Previously Keyper identified you by a username you typed. Now it uses a real account, and the database checks it.
- Each account only sees its own data, enforced by the database rather than by the app filtering results.
- Your vault key is now stored encrypted under your master passphrase. It used to be stored in a form the server could read directly. This means a copy of the database is no longer enough to decrypt anything.
Your credentials are not changed and not re-encrypted.
| # | Where | What |
|---|---|---|
| 1 | Supabase | Back up your database |
| 2 | Supabase | Authentication โ Providers โ enable Email |
| 3 | Supabase | Authentication โ Users โ Add user |
| 4 | SQL Editor | Run migration/01-check.sql, copy your account UUID |
| 5 | SQL Editor | Run migration/02-claim-your-data.sql โ paste your UUID into the one marked line |
| 6 | SQL Editor | Run migration/03-apply-security.sql |
| 7 | Keyper | Sign in, then unlock with your existing master passphrase |
| 8 | SQL Editor | Run migration/04-check-key.sql to confirm |
| 9 | SQL Editor | Run migration/05-remove-old-key.sql |
Only step 5 needs an edit. Everything else is paste-and-run.
You will have two secrets, not one. The account password you create in step 3 gets you your rows. Your existing master passphrase decrypts them. They are different, and you need both.
Your master passphrase can no longer be reset. You can change it whenever you know the current one, but nothing stored can recover it. Older versions allowed a reset only because the vault key sat separately in usable form, which is the thing being fixed. Write your passphrase down somewhere safe before you start.
Full detail, expected output at each step, and troubleshooting: MIGRATION.md
Keyper supports three database backends โ choose the one that fits your workflow:
| Feature | SQLite (Local) | Supabase (Cloud) | Neon Postgres (Cloud/Local) |
|---|---|---|---|
| Setup required | None โ auto-configured | Project creation + SQL script | Connection string + Neon setup script |
| Internet connection | โ Not required | โ Required | โ Cloud / local proxy for Neon Local |
| Multi-device sync | โ Not supported | โ Supported | โ Supported |
| Works in browser/PWA | โ Yes | โ Yes | โ Yes |
| Works in Electron desktop | โ Yes | โ Yes | โ Yes |
| Data location | Your device (IndexedDB in browser/PWA, optional file path in Electron) | Your Supabase project | Neon Cloud or Neon Local branch |
- Start Keyper and open the app in your browser, PWA, or Electron desktop build
- In the setup wizard, select "SQLite (Local)" as your database provider
- Master Passphrase: Create your encryption passphrase
- Start Managing: Add your first encrypted credential! ๐
SQLite mode stores your encrypted vault locally with no external service required. In browser/PWA mode it uses IndexedDB automatically; in Electron you can also point Keyper at a SQLite file on disk.
-
Visit supabase.com and sign up/login
-
Click "New Project"
-
Configure your project:
- Name:
keyper-db(or your preference) - Database Password: Generate a strong password
- Region: Choose closest to your location
- Name:
-
Wait 1-2 minutes for setup completion
- In Supabase dashboard: Settings โ API
- Copy these values:
- Project URL:
https://your-project.supabase.co - anon/public key:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
- Project URL:
-
Start Keyper:
keyper -
Database Setup: Configure your Supabase connection
- Enter your Supabase URL and anon/publishable key
- Copy and run the complete SQL setup script in Supabase SQL Editor
- If you already have an existing Keyper database, run the update script too (
migration-add-document-misc-types.sql) sodocumentandmisccredential types work - The script creates tables with the latest security features:
raw_dekandbcrypt_hashcolumns for the new simplified security model- Backwards compatibility for existing users with legacy
wrapped_deksystem - Latest credential type support (
api_key,login,secret,token,certificate,document,misc)
- Test the connection
-
Master Passphrase: Create your encryption passphrase
- Choose a strong passphrase (8+ characters recommended)
- New users get the simplified bcrypt-only authentication system
- This encrypts all your credentials client-side with secure emergency reset capabilities
-
Start Managing: Add your first encrypted credential! ๐
- Neon Cloud: Create or open a project at neon.tech, then copy a pooled or direct Postgres connection string from the Neon dashboard.
- Neon Local: Start the official Neon Local Docker container, then use its local Postgres connection string, for example
postgres://neon:npg@localhost:5432/neondb.
- Start Keyper and open the setup wizard.
- Select Neon Postgres as the database provider.
- Choose Neon Cloud or Neon Local Docker.
- Paste the connection string.
- Copy and run
sql/neon-setup.sqlin the Neon SQL Editor or any Postgres client connected to Neon. - Test the connection, save, and continue into the vault.
Keyper works as a Progressive Web App for a native app experience!
- Open Keyper in Chrome/Edge/Firefox
- Look for the install icon in the address bar
- Click to install as a desktop app
- Access from your applications menu
- Open Keyper in your mobile browser
- Tap the browser menu (โฎ)
- Select "Add to Home Screen" or "Install App"
- Access from your home screen
- ๐ฑ Native app experience
- ๐ Faster loading times
- ๐ Offline functionality
- ๐ Background updates
- ๐ฒ Push notifications (coming soon)
โ "Connection failed: Database connection failed"
- Verify URL format - now supports any valid HTTP/HTTPS URL (v1.0.6+)
- โ
Cloud:
https://your-project.supabase.co - โ
Local:
http://localhost:54321,http://192.168.1.100:8000 - โ
Custom:
https://supabase.mydomain.com
- โ
Cloud:
- Use anon/public key, not service_role
- Check that your Supabase project is active
- For Neon, verify the connection string is copied exactly and that
sql/neon-setup.sqlhas completed successfully - For Neon Local, make sure the Docker container is running and reachable from the browser or Electron app
โ "relation 'credentials' does not exist"
- Run the complete SQL setup script in Supabase SQL Editor or the Neon setup script in Neon SQL Editor
- Ensure the script completed without errors
โ New document or misc credentials fail to save
- Run the existing-database update script:
migration-add-document-misc-types.sql - Confirm
credentials_credential_type_checkincludesdocumentandmisc
โ Dashboard shows "No credentials found"
- Click "Refresh App" button
- Clear browser cache and reload
- For PWA: Uninstall and reinstall the app
โ Can't enter new credentials after clearing configuration
- Refresh the page after clearing configuration
- Ensure you're using a valid HTTP/HTTPS URL (any format supported in v1.0.6+)
- Try clearing browser cache if form inputs appear stuck
โ Categories dropdown is empty when using custom username
- This issue has been resolved in the latest version
- Categories should now appear for all usernames (both default and custom)
- If still experiencing issues, try refreshing the page after setting your username
โ App doesn't show setup wizard after clearing database
- Clear browser cache and cookies for the site
- For Chrome/Edge: Settings โ Privacy โ Clear browsing data โ Cookies and cached files
- For Firefox: Settings โ Privacy โ Clear Data โ Cookies and Site Data + Cached Web Content
- Refresh the page to see the initial setup screen
โ Stuck in configuration loops or can't access settings
- Clear browser cache and localStorage completely
- Refresh the page and reconfigure your database connection
- Ensure your Supabase credentials are correct
- Use the built-in database health checks to verify table integrity
โ Multi-user vault conflicts
- Each user has their own isolated encrypted vault
- Use Dashboard Settings โ User Management to switch users
- Use Create New User from the lock screen or Add New User in user management
- Refresh after user-switch actions if prompted for the cleanest vault context handoff
- Each user's data is completely separate and encrypted individually
You can change your master passphrase from Settings if you know the current one. You cannot reset it if you have forgotten it. Nobody can, including us, and that is the point.
Changing it re-wraps the same vault key under a key derived from your new passphrase. Nothing gets re-encrypted, so it is quick and every existing credential keeps working.
If you forget it, the vault is gone. There is no recovery path and no support request that helps. Your only option is to delete the vault and start over. Write your passphrase down and put it somewhere safe.
This changed in v1.3.0, and the change was deliberate. Older versions let you regain access by overwriting the
bcrypt_hashcolumn in the database. That worked because the vault key was stored separately, in usable form, inraw_dek. Which also meant anyone who could write to your database could reset the hash, read the key and decrypt everything. The reset was not a feature sitting next to the encryption; it was a hole straight through it.The vault key is now stored only wrapped under your passphrase, so there is no value in the database that a reset could unlock. Losing the passphrase genuinely loses the data. That is the trade, and it is the right one for a credential manager.
Account password vs master passphrase โ two different secrets:
| Account password | Master passphrase | |
|---|---|---|
| What it does | Proves who you are so the database returns your rows | Decrypts those rows |
| Where it lives | Supabase Auth | Only in your head |
| Can it be reset? | Yes, by email | No, never |
| If leaked | Attacker gets ciphertext and metadata | Attacker needs your rows too |
- Upgrading to 1.3.0? Start with MIGRATION.md
- Check the documentation or the Self-Hosting Guide
- Review the browser console for errors (F12 โ Console)
- Check your database provider logs (Supabase dashboard โ Logs, or DevTools โ Console for SQLite)
- Report bugs and request features on GitHub
- For anything else, email support@keyper.icu
When asking for help, never include your master passphrase, your database connection string, or the contents of your
vault_configtable.
- โ Self-Hosted - Run on your own infrastructure
- โ Private Database - Your Supabase instance, Neon database, or local SQLite storage
- โ No Tracking in App - Zero telemetry or analytics inside the Keyper application. (The public documentation website uses basic analytics to track downloads and pages view counts)
- โ Open Source - Fully auditable code
- ๐ Row Level Security - Owner-scoped policies that require an authenticated session
- ๐ Encryption - Secret values encrypted client-side; metadata stored in plaintext
- ๐ค User Isolation - Enforced by the database, not by client-side filtering
- ๐ก๏ธ Offline-First Option - SQLite mode requires no internet and stores data entirely on-device
- Registration: Users self-register with an email and password through Supabase Auth. No admin account is required. Enable the Email provider in your Supabase project first.
- Isolation: Every account has its own
vault_config, wrapped vault key, credentials and categories, and the database enforces the separation through owner-scoped RLS policies. It is not client-side filtering that you could bypass by editing a query. - Switching accounts: Sign out and sign in as the other account. There is no in-app account switcher any more, because listing other users required a database read that is now correctly refused.
- No Backdoors: There is no admin override and no recovery path. Signing in gets you your own encrypted rows; the master passphrase is still required to read them.
Keyper protects your data in layers. They are easy to mix up, so here is what each one actually does:
| Layer | What it covers |
|---|---|
| Supabase Auth session | Decides whether the database returns your rows at all |
| Owner-scoped RLS policies | Keeps each account to its own rows, checked by the database |
| Passphrase-wrapped vault key | Means a copy of the database cannot decrypt anything on its own |
AES-256-GCM on secret_blob |
Encrypts the secret values themselves |
Scope, so you know what you are working with:
- Encryption covers the secret values.
title,username,url,notes,tags,categoryandpriorityare stored as regular text, which is what makes search and sorting work. Encrypting them is on the roadmap. - Your master passphrase is the only thing that unlocks the vault key, and it is never sent anywhere. That also means nobody can recover it for you, so keep a copy somewhere safe.
- The anon/publishable key is designed to be public and is safe to expose. On its own it does not open anything.
- Neon mode works differently. It connects to Postgres directly from the browser using a connection string, which carries full database access, so database-side rules cannot narrow it down. It suits a single operator who keeps that string private. For separate accounts use Supabase; for a private local vault use SQLite.
- Frontend: React 19.1 + TypeScript
- Build Tool: Vite 7.0
- Styling: Tailwind CSS + shadcn/ui
- Database: Supabase (PostgreSQL + Auth), Neon Postgres, or SQLite (sql.js / IndexedDB)
- State Management: TanStack Query
- Forms: React Hook Form + Zod
- PWA: Vite PWA Plugin + Workbox
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
We welcome contributions! Please see our Contributing Guide for details.
Created by Pink Pixel โจ Dream it, Pixel it
- ๐ Website: pinkpixel.dev
- ๐ง Email: admin@pinkpixel.dev
- ๐ฌ Discord: @sizzlebop
- โ Support: Buy me a coffee
โญ Star this repo if Keyper helps secure your digital life! โญ