Skip to content

Zann Docs

Self-hosted password manager for individuals and small teams.

Pet Project Notice

This project:

  • Is a pet project for experiments
  • Has a codebase written with LLM assistance
  • Has not passed a security audit
  • Is not recommended for production

Use at your own risk for testing and learning.

  • Client-side encryption - personal vaults are encrypted on the client
  • Shared vaults - shared vaults for small teams
  • CI/CD CLI - service account tokens, server fingerprint pinning
  • Desktop app - offline-first, works without a server (macOS, Windows)
  • Hybrid auth - OIDC + built-in authentication

Current status: experimental. Until v0.Y (refactor milestone), the API, CLI, and config format may change without backward compatibility.

After the refactor milestone, we will publish a stability policy and follow it for:

  • API compatibility
  • Config format migrations
  • Client/server version support windows
  • May happen without migration steps
  • Will still be noted in CHANGELOG when possible

Desktop app

  1. Download the desktop app for your platform from Releases
  2. Launch the app - it works offline-first
  3. Create a personal vault and start using it

If your platform is not listed in Releases, build the desktop app from source (requires Rust toolchain, Bun, and Tauri system dependencies):

Terminal window
cd apps/desktop
bun install
bun run tauri build

See CONTRIBUTING.md for platform-specific Tauri prerequisites.

Full install guide: /install/.

Option 2: Self-hosted server (for small teams and CI/CD)

Section titled “Option 2: Self-hosted server (for small teams and CI/CD)”
Terminal window
# Clone the repo
git clone https://github.com/constXife/zann
cd zann
# Start the server via Docker Compose
docker compose up -d
# The server is available at http://localhost:8080
  • Minimum (dev / low-load): 1 vCPU, 128 MB RAM
  • Recommended (sustained load): 2 vCPU, 512 MB RAM
  • Actual requirements depend on RPS, vault size, and cache policy
flowchart TB
subgraph Clients["Clients"]
Desktop["Desktop App<br/>Offline-first"]
CLI["CLI Client<br/>CI/CD ready"]
end
Server["Zann Server<br/>(Axum + PostgreSQL)"]
Desktop -.->|optional| Server
CLI -->|required| Server
classDef clientBox fill:#3b82f6,stroke:#1d4ed8,stroke-width:2px,color:#fff
classDef serverBox fill:#8b5cf6,stroke:#6d28d9,stroke-width:2px,color:#fff
class Desktop,CLI clientBox
class Server serverBox

Components:

  • zann-server - HTTP API (Axum, PostgreSQL)
  • zann-cli - CLI client for Linux/macOS/CI
  • apps/desktop - Desktop app (Tauri, SQLite)
  • zann-core - shared business logic and cryptography

Server threat model: crates/zann-server/SECURITY.md (assumptions and trust boundaries).

  • Desktop is the primary client for people (personal vaults + shared vaults).
  • CLI is for automation and CI/CD; it is token-based and requires the server.
  • Server provides the API, shared vaults, and token issuance.
  • Offline-first for personal vaults; optional server connection for shared vaults.
  • Recommended for interactive use and day-to-day management.
  • Uses tokens issued by the server (service account tokens).
  • Provide tokens via --token, --token-file, or zann config set-context.
  • Print version info with zann version.

Example token creation and CLI setup:

Terminal window
# Create a service account token on the server
zann-server token create ci-prod infra:/
# Configure the CLI in your CI job
zann config set-context ci \
--addr https://zann.example.com \
--token "$ZANN_SERVICE_TOKEN" \
--vault infra
  • Runs as the shared backend (Docker Compose or prebuilt image).
  • Issues tokens and enforces access scope and IP restrictions.

Zann supports CI/CD integrations:

  • Service account tokens for automation
  • Prefix-based access control to limit access
  • Server fingerprint pinning to prevent MITM attacks
  • CLI commands like zann get my-secret for scripts

Service token + CLI example:

Terminal window
# 1) Create a service account token on the server
zann-server token create ci-prod infra:/
# Save the "token" output in your CI secret store as ZANN_SERVICE_TOKEN
# 2) Configure the CLI in your CI job
zann config set-context ci \
--addr https://zann.example.com \
--token "$ZANN_SERVICE_TOKEN" \
--vault infra
# 3) Fetch a secret
export DB_PASSWORD="$(zann get infra/db/creds password)"

From a local k6 “morning sync” run (~500 VUs, ~2.5k req/s):

  • RSS memory: ~100 MiB
  • Errors: no 5xx observed

CPU usage depends on workload and database performance. See loadtest/k6/scenarios/morning_sync.js for the scenario.

Backend: Rust, Axum, PostgreSQL, SQLx, Argon2id, ChaCha20Poly1305 Desktop: Tauri, Vue 3, TypeScript, TailwindCSS DevOps: Docker Compose, GitHub Actions, Prometheus, OpenTelemetry

See CONTRIBUTING.md for local development instructions.

MIT License - see LICENSE

Copyright 2025 constXife