How to Implement Password Protection Using the ACCESS_KEYS Environment Variable in MiniSearch
MiniSearch enables instant password protection when you define the ACCESS_KEYS environment variable, activating Argon2-based validation that secures all API endpoints while the UI prompts users for authentication and persists valid sessions in localStorage.
The felladrin/minisearch repository ships with a built-in access control system that requires zero code changes to deploy. By setting a single environment variable, you activate server-side key validation using Argon2 hashing and client-side session management. This implementation protects search, inference, and custom endpoints behind a password-style access key system.
How the ACCESS_KEYS Protection System Works
MiniSearch uses a multi-layered approach to access control that spans both server and client codebases. When ACCESS_KEYS is populated, the system automatically activates validation hooks and UI prompts.
Server-Side Validation Architecture
The server intercepts all requests through the validateAccessKeyServerHook middleware defined in server/validateAccessKeyServerHook.ts. This hook listens for POST requests to /api/validate-access-key and compares submitted hashes against the environment variable using Argon2 verification.
The validation logic loops through each key in the comma-separated list:
const accessKeys = process.env.ACCESS_KEYS?.split(",") ?? [];
for (const key of accessKeys) {
if (await argon2Verify({ password: key, hash: accessKeyHash })) {
isValid = true;
break;
}
}
If any key matches the submitted Argon2 hash, the server returns { valid: true }, granting access to the requesting client.
Client-Side Authentication Flow
The client application checks for protection status through the VITE_ACCESS_KEYS_ENABLED flag exposed in vite.config.ts. When enabled, the App component in client/components/App/App.tsx forces a modal prompt before rendering the main interface.
User input flows through client/modules/accessKey.ts, which handles three critical operations:
- Local Hashing: Plain-text keys are hashed locally using
hashAccessKey()before transmission - Server Validation: The hash is sent to
/api/validate-access-keyfor verification - Session Persistence: Valid hashes are stored in
localStorageunderaccessKeyHashwith timestamps to prevent re-prompting during the timeout period defined byVITE_ACCESS_KEY_TIMEOUT_HOURS
Configuring Password Protection
Activating access control requires only environment configuration and a service restart. No source code modifications are necessary.
1. Define Access Keys in the Environment
Create or edit the .env file at the project root using the format shown in .env.example. Set ACCESS_KEYS to a comma-separated list of plain-text passwords:
# .env
ACCESS_KEYS="alpha-2024,beta-2024,gamma-2024"
Each comma-separated value represents a valid access credential. The server stores these as plain text in memory but validates them against Argon2 hashes submitted by clients.
2. Enable the Vite Build Flag
The build system automatically detects the environment variable and exposes it to the client bundle. In vite.config.ts, the define block sets VITE_ACCESS_KEYS_ENABLED:
define: {
VITE_ACCESS_KEYS_ENABLED: JSON.stringify(
Boolean(process.env.ACCESS_KEYS)
),
},
This boolean flag determines whether the UI renders the access key prompt or bypasses authentication entirely.
3. Rebuild and Deploy
For Docker deployments, rebuild the image to capture the new environment variables:
docker compose up --build -d
The server hook activates automatically on startup when process.env.ACCESS_KEYS is detected.
4. Client Authentication Implementation
When integrating the access key flow into custom client code, import the validation module from client/modules/accessKey.ts:
import { validateAccessKey } from "./accessKey";
async function onKeySubmit(input: string) {
const ok = await validateAccessKey(input);
if (ok) {
// Proceed to protected resources
console.log("Access granted");
} else {
// Display authentication error
console.error("Invalid access key");
}
}
The validateAccessKey function handles local hashing, server verification, and automatic localStorage persistence upon success.
Key Source Files Reference
Understanding the codebase structure helps with customization and debugging:
server/validateAccessKeyServerHook.ts: Implements the POST/api/validate-access-keyendpoint and performs Argon2 verification againstACCESS_KEYSclient/modules/accessKey.ts: ContainshashAccessKey(),validateAccessKey(), andverifyStoredAccessKey()for client-side operationsclient/components/App/App.tsx: UI entry point that conditionally renders the access key modal based onVITE_ACCESS_KEYS_ENABLEDvite.config.ts: Build configuration that exposes the access key feature flag to the clientdocs/configuration.md: Official documentation for environment variables.env.example: Template showing expected variable format
Summary
- Set the
ACCESS_KEYSenvironment variable to a comma-separated list of authorized passwords to activate protection - The server automatically validates keys using Argon2 through
server/validateAccessKeyServerHook.ts - The client UI switches to protected mode via
VITE_ACCESS_KEYS_ENABLEDdefined invite.config.ts - Valid sessions persist in
localStoragewith configurable timeouts viaVITE_ACCESS_KEY_TIMEOUT_HOURS - All API endpoints, including search and inference, require valid access keys when protection is enabled
Frequently Asked Questions
What hashing algorithm does MiniSearch use for access key validation?
MiniSearch uses Argon2 for all access key operations. When a user enters a key, the client hashes it locally using hashAccessKey() from client/modules/accessKey.ts before transmission. The server then uses argon2Verify() in server/validateAccessKeyServerHook.ts to compare the submitted hash against the plain-text keys defined in ACCESS_KEYS without transmitting passwords over the network.
Can I use ACCESS_KEYS with Docker Compose?
Yes. Pass the environment variable through your docker-compose.yml file or an .env file in the project root. The container must be rebuilt or restarted to pick up changes to ACCESS_KEYS. You can reference the variable in your compose file using ${ACCESS_KEYS:-} to provide a default empty value if the variable is unset.
How long do access key sessions last?
Session duration is controlled by the VITE_ACCESS_KEY_TIMEOUT_HOURS environment variable. After successful validation, the client stores the hash and timestamp in localStorage. The verifyStoredAccessKey() function in client/modules/accessKey.ts checks this timeout on page load and prompts for re-authentication when the period expires.
Does enabling ACCESS_KEYS affect API endpoints only, or the UI as well?
Both. When ACCESS_KEYS is defined, vite.config.ts sets VITE_ACCESS_KEYS_ENABLED to true, causing client/components/App/App.tsx to render the access key modal before the main interface. Simultaneously, the server hook validates keys for all requests. The system protects both the user interface and underlying API resources.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →