Client-side encryption
Argon2id, HKDF and XChaCha20-Poly1305 protect data before it reaches the API.
A self-hosted password manager with browser-side end-to-end encryption, YubiKey/FIDO2 and no server access to plaintext secrets.
N3X Vault is an independent password manager with its own protocol and browser-side end-to-end encryption. The server never receives the master password or an unwrapped account key.
Release status: the security alpha is suitable for protocol review, development and controlled testing. Do not store production secrets yet.
Application interface
A real product interface — open any preview to inspect it at full size.
Logins, secure notes and TOTP secrets are encrypted in the browser before reaching your own server.
Managed hosting by N3X
N3X can deploy and maintain this application, from initial setup and SSL to updates, monitoring and backups.
Argon2id, HKDF and XChaCha20-Poly1305 protect data before it reaches the API.
WebAuthn PRF unlock, hardware-key inventory and a two-device readiness policy.
Encrypted export and resumable restore into an empty installation without a hidden universal key.
The Rust API and PostgreSQL store ciphertext, protocol parameters and minimal operational metadata.
Fifteen-minute browser sessions remain memory-only and are revocable server-side.
A private database network, dropped capabilities, read-only filesystems and volume-backed runtime secrets.
DOCKER CONFIGURATOR
Set the final hostname before enrolling a YubiKey. Changing the RP ID later invalidates existing hardware credentials.
Use the final reverse-proxy domain, for example vault.company.com.
name: n3xvault
x-api-security: &api-security
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
tmpfs:
- /tmp:size=32m,mode=1777
x-web-security: &web-security
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
tmpfs:
- /tmp:size=32m,mode=1777
- /app/.next/cache:size=64m,mode=0700,uid=1001,gid=1001
services:
bootstrap:
image: alpine:3.22
restart: "no"
command:
- /bin/sh
- -ec
- |
umask 077
if [ ! -s /run/n3xvault/database_password ]; then
od -An -N32 -tx1 /dev/urandom | tr -d ' \n' > /run/n3xvault/database_password
fi
if [ ! -s /run/n3xvault/bootstrap_token ]; then
od -An -N32 -tx1 /dev/urandom | tr -d ' \n' > /run/n3xvault/bootstrap_token
fi
chmod 0444 /run/n3xvault/database_password /run/n3xvault/bootstrap_token
volumes:
- runtime_secrets:/run/n3xvault
networks:
- backend
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
postgres:
image: postgres:17-alpine
restart: unless-stopped
depends_on:
bootstrap:
condition: service_completed_successfully
environment:
POSTGRES_DB: n3xvault
POSTGRES_USER: n3xvault
POSTGRES_PASSWORD_FILE: /run/n3xvault/database_password
volumes:
- postgres_data:/var/lib/postgresql/data
- runtime_secrets:/run/n3xvault:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n3xvault -d n3xvault"]
interval: 5s
timeout: 5s
retries: 12
networks:
- backend
api:
image: ghcr.io/nexitpl/n3xvault-api:alpha
restart: unless-stopped
depends_on:
bootstrap:
condition: service_completed_successfully
postgres:
condition: service_healthy
environment:
N3XVAULT_BIND: 0.0.0.0:8080
N3XVAULT_DATABASE_HOST: postgres
N3XVAULT_DATABASE_NAME: n3xvault
N3XVAULT_DATABASE_USER: n3xvault
N3XVAULT_DATABASE_PASSWORD_FILE: /run/n3xvault/database_password
N3XVAULT_BOOTSTRAP_TOKEN_FILE: /run/n3xvault/bootstrap_token
N3XVAULT_PUBLIC_ORIGIN: https://vault.example.com
N3XVAULT_WEBAUTHN_RP_ID: vault.example.com
N3XVAULT_SESSION_TTL_SECONDS: ${N3XVAULT_SESSION_TTL_SECONDS:-900}
N3XVAULT_WEBAUTHN_FLOW_TTL_SECONDS: ${N3XVAULT_WEBAUTHN_FLOW_TTL_SECONDS:-300}
N3XVAULT_DEVICE_PAIRING_TTL_SECONDS: ${N3XVAULT_DEVICE_PAIRING_TTL_SECONDS:-300}
RUST_LOG: ${N3XVAULT_LOG_LEVEL:-n3xvault_api=info,tower_http=info}
volumes:
- runtime_secrets:/run/n3xvault:ro
healthcheck:
test: ["CMD", "curl", "--fail", "--silent", "http://127.0.0.1:8080/health/ready"]
interval: 15s
timeout: 3s
retries: 5
start_period: 15s
networks:
- backend
<<: *api-security
web:
image: ghcr.io/nexitpl/n3xvault-web:alpha
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
N3XVAULT_API_INTERNAL_URL: http://api:8080
ports:
- "127.0.0.1:8793:3000"
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/api/health"]
interval: 20s
timeout: 5s
retries: 5
start_period: 20s
networks:
- frontend
- backend
<<: *web-security
networks:
frontend:
backend:
internal: true
volumes:
postgres_data:
runtime_secrets:
mkdir -p n3xvault
cd n3xvault
# Save the configuration as docker-compose.yml
docker compose up -d
docker compose ps
docker compose run --rm api print-bootstrap-token
curl -fsS http://127.0.0.1:8793/api/health