Skip to content

Shrpp/ovlt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

114 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OVLT logo

Self-hosted OIDC auth in a single Rust binary.
OAuth2 + OIDC Β· Multi-tenant via Postgres RLS Β· <50 MB RAM Β· MIT licensed.

MIT License hefesto on crates.io Docker image Alpha status Documentation Built with Rust

OVLT TUI demo


⚠ Alpha build. Not production ready. APIs and configuration may change. Stable beta target: Q3 2026. See Roadmap and Security for current state and known gaps.

OVLT is a self-hosted OIDC authorization server in Rust, designed for indie hackers and small teams who want OIDC without the operational overhead of Keycloak or the per-seat cost of hosted alternatives. Single binary, Postgres-only, no sidecars.

Built with Rust + Axum + PostgreSQL RLS. Powered by hefesto.


Quick Start

docker run -p 3000:3000 \
  -e OVLT_ADMIN_KEY=your-admin-key \
  -e OVLT_BOOTSTRAP_ADMIN_EMAIL=admin@example.com \
  -e OVLT_BOOTSTRAP_ADMIN_PASSWORD=Admin1234! \
  ghcr.io/shrpp/ovlt-core:latest

Secrets (JWT_SECRET, MASTER_ENCRYPTION_KEY, TENANT_WRAP_KEY) are auto-generated on first run and printed to logs. Save them somewhere safe before restarting the container.

Once running, see Getting Started to create your first tenant and integrate a client application.


Features

πŸ” OIDC Authorization Server Authorization Code + PKCE, client_credentials (M2M), RS256 id_tokens, JWKS endpoint, OpenID discovery
🏒 Multi-tenant isolation PostgreSQL Row-Level Security β€” tenant boundaries enforced at the database layer, not the application layer
πŸ”’ Encryption at rest AES-256-GCM envelope encryption for sensitive fields (TOTP secrets, SMTP credentials, IdP secrets) via hefesto
πŸ“± MFA TOTP (RFC 6238) + WebAuthn/Passkeys (FIDO2 Level 2) β€” manage via TUI or API
🌐 Social login Google and GitHub OAuth2 β€” per-tenant IdP config, stored encrypted, manageable via TUI
πŸ“§ Per-tenant SMTP Encrypted credentials at rest Β· Auto-send on register + password reset
πŸ“‹ Audit log Every auth event recorded β€” who, what, when, from where
πŸ–₯️ Admin TUI Terminal UI with guided wizard β€” manage tenants, users, clients, roles, SMTP, IdPs
πŸ” OpenAPI + Swagger UI Auto-generated spec at /openapi.json Β· Interactive docs at /docs
πŸ›‘οΈ Hardened defaults Argon2id passwords Β· Rotating refresh tokens Β· Account lockout Β· Per-IP rate limiting Β· HSTS Β· CSP

Planned for v0.5

  • OPAQUE password authentication β€” the server never sees the user's password, even during login. Real zero-knowledge for credentials. Tracking issue
  • Client-side encrypted tenant secrets β€” SMTP passwords and IdP secrets encrypted in the admin's browser before transmission. Server holds only ciphertext at rest. Tracking issue

Comparison

OVLT Kanidm Keycloak Authentik Zitadel
RAM at idle <50 MB ~90 MB ~512 MB ~735 MB ~512 MBΒΉ
Startup time <1 s <2 s 30–60 s ~10 s ~5 s
Language Rust Rust Java Python Go
Multi-tenant built-in βœ… βœ… βœ… βœ… βœ…
Field-level encryption βœ… ❌ ❌ ❌ ❌
External deps beyond DB None None None Redis None
PKCE required βœ… βœ… Optional Optional Optional
Argon2id hashing βœ… βœ… ❌ (bcrypt default) βœ… βœ…
OPAQUE auth 🚧 v0.5 ❌ ❌ ❌ ❌
Maturity Alpha Stable Stable Stable Stable
License MIT MPL-2.0 Apache 2.0 MIT Apache 2.0
Pricing Free Free Free Free FreeΒ²

ΒΉ Per the Zitadel maintainer's recommendation for small setups. Lower minimums are technically possible.
Β² Zitadel Cloud is paid; self-hosted is free.

Measurement methodology: RAM at idle measured with 1 tenant, 10 users, no active sessions, fresh container. Steady-state under load may differ.

This is not a "we beat them at everything" table. The alternatives above are all mature, production-tested projects with track records OVLT does not yet have. OVLT's bet is on a different operational profile (single Rust binary, no JVM/Redis, low footprint, modern cryptography roadmap), not on being feature-complete relative to Keycloak.


Install Admin TUI

Download the ovlt binary from GitHub Releases. Binaries are named ovlt-<platform>-<version>.

macOS

# Remove quarantine flag (required β€” binary is unsigned in alpha)
xattr -dr com.apple.quarantine ovlt-macos-arm64-*   # Apple Silicon
# or
xattr -dr com.apple.quarantine ovlt-macos-x64-*     # Intel

chmod +x ovlt-macos-*
sudo mv ovlt-macos-* /usr/local/bin/ovlt
ovlt connect http://localhost:3000

Linux (static musl, zero runtime dependencies)

chmod +x ovlt-linux-x64-*    # x86_64
# or
chmod +x ovlt-linux-arm64-*  # ARM64

sudo mv ovlt-linux-* /usr/local/bin/ovlt
ovlt connect http://localhost:3000

Windows

Move-Item ovlt-windows-x64-*.exe ovlt.exe
.\ovlt.exe connect http://localhost:3000

Windows SmartScreen will warn β€” the binary is not yet code-signed. Click More info β†’ Run anyway. Homebrew tap, WinGet/Scoop, and code-signed binaries are planned for the stable beta.

Once connected, run ovlt serve to launch the TUI. It guides you through tenant creation, user management, client registration, SMTP setup, and more β€” no web browser required.


Documentation

Doc Description
Getting Started Run OVLT, first login, create a tenant
Configuration All environment variables
API Reference All HTTP endpoints Β· Interactive Swagger UI at /docs
Admin TUI Using the ovlt terminal UI
M2M / Client Credentials Machine-to-machine auth flow
MFA TOTP setup and management
WebAuthn / Passkeys FIDO2 passkey registration and authentication
SMTP Per-tenant email delivery configuration
Social Login Google and GitHub OAuth setup
Architecture Multi-tenancy, RLS, encryption model
Security Security model, threat model, hardening checklist
Database Access Connect via DataGrip/DBeaver locally or over SSH tunnel

Technology Stack

Layer Technology Why
Runtime Rust Memory-safe, no garbage collector, predictable footprint
Web framework Axum Async, composable, built on Tokio
Database PostgreSQL + RLS Tenant isolation enforced at the database layer
ORM SeaORM Type-safe queries, automatic migrations on startup
Encryption hefesto AES-256-GCM envelope encryption (see Security for the key hierarchy)
Password hashing Argon2id Current OWASP recommendation (OPAQUE migration planned for v0.5)
Protocols OAuth2, OIDC, JWT RS256 id_tokens, HS256 access tokens, JWKS endpoint
Deployment Docker + Compose Single binary, no sidecars, no external dependencies except Postgres

Maturity

OVLT is alpha software. Where the project currently stands:

  • Implemented and exercised: OIDC core flows, multi-tenant isolation, MFA, social login, SMTP, audit log, TUI.
  • Implemented but lightly tested: Encryption at rest (hefesto), key rotation, advanced rate limiting.
  • In progress: Comprehensive integration test suite (Stage 5), distributed rate limiter, OPAQUE password auth (Stage 6).
  • Not yet started: External security audit, hardened production deployment guide, multi-region replication.

The Roadmap reflects this honestly. If you're evaluating OVLT for production use, the answer is "not yet" β€” wait for the stable beta in Q3 2026. If you're evaluating it for a side project, internal tool, or test deployment, the alpha works and feedback is welcome.


Roadmap

βœ“  Stage 1 Β· Auth Core                                               [ done ]
β”‚    OIDC compliance β€” authorization_code + PKCE, client_credentials
β”‚    RS256 id_token, JWKS, OpenID discovery
β”‚    Refresh token rotation, revocation, session management
β”‚    RBAC β€” roles, permissions, claims in tokens
β”‚
βœ“  Stage 2 Β· User Lifecycle                                          [ done ]
β”‚    Password reset + email verification (one-time tokens)
β”‚    Password policies, account lockout, login attempt tracking
β”‚    Per-tenant settings (TTL, lockout thresholds, registration toggle)
β”‚
βœ“  Stage 3 Β· Extended Auth                                           [ done ]
β”‚    TOTP MFA (RFC 6238) β€” setup, challenge, disable, admin override
β”‚    WebAuthn / Passkeys (FIDO2 Level 2) β€” register, authenticate, manage
β”‚    Social login β€” Google + GitHub, per-tenant IdP config via DB + TUI
β”‚    Per-tenant SMTP β€” encrypted credentials, auto-send on register + reset
β”‚
βœ“  Stage 4 Β· DX & Observability                                      [ done ]
β”‚    OpenAPI spec β€” GET /openapi.json + Swagger UI at GET /docs
β”‚    Universal login β€” server resolves tenant from email
β”‚    Structured errors β€” field-level validation, friendly messages
β”‚    TUI redesign β€” consistent keybindings, contextual hints, settings modals
β”‚    CLI β€” ovlt serve / ovlt connect, cross-platform static binaries
β”‚    Audit log, database access docs
β”‚
●  Stage 5 Β· Security Hardening                               [ in progress ]
β”‚    Cookie Secure flag in production
β”‚    Remove raw SQL string interpolation (defense-in-depth)
β”‚    Type-safe RLS extractor β€” impossible to bypass at compile time
β”‚    Distributed rate limiter (PostgreSQL-backed, multi-replica safe)
β”‚    Tenant key cache with TTL + zeroize-on-drop
β”‚    Key rotation with grace period (JWT + RSA)
β”‚    Docker image hardening (distroless, non-root)
β”‚    Password history enforcement
β”‚    Durable audit log (critical events synchronous, buffered otherwise)
β”‚    MFA backup codes β€” recovery without admin intervention
β”‚
●  Stage 6 Β· Test Suite Expansion                             [ in progress ]
β”‚    Integration test suite β€” full OIDC flow (authorize β†’ token β†’ introspect)
β”‚    Tenant isolation regression tests across every endpoint
β”‚    Security regression tests β€” enumeration, timing, tampering
β”‚    Cryptographic round-trip tests for hefesto envelope
β”‚    OAuth flow tests β€” PKCE enforcement, code replay, JWT tamper rejection
β”‚    Coverage gates in CI (block PRs that drop coverage > 2%)
β”‚    Target: β‰₯60% overall, β‰₯80% in auth/, β‰₯90% in crypto/
β”‚    Public coverage badge and per-module reporting
β”‚
β—‹  Stage 7 Β· Modern Authentication                             [ planned ]
β”‚    OPAQUE password authentication (via opaque-ke)
β”‚      β€” server never sees the password, even during login
β”‚      β€” migration path from Argon2id for existing users
β”‚    Client-side envelope encryption for tenant configuration secrets
β”‚      β€” admin browser encrypts SMTP password and IdP secrets before transmit
β”‚      β€” server holds only ciphertext at rest
β”‚    JS client SDK (@ovlt/sdk) implementing OPAQUE on the browser side
β”‚    Documented threat model in docs/security.md
β”‚
β—‹  Stage 8 Β· Observability & Developer Experience              [ planned ]
β”‚    Prometheus metrics β€” /metrics endpoint (login rates, token issuance,
β”‚      DB pool, JWKS cache hits)
β”‚    Structured tracing β€” request-id correlation end-to-end
β”‚    Auto-generated SDKs β€” Python + Go via OpenAPI Generator on release
β”‚    Framework integration guides β€” Next.js, Express, FastAPI, SvelteKit
β”‚    Single-tenant convenience mode (DEFAULT_TENANT_SLUG env var)
β”‚    Dev-mode rich errors β€” debug field with human-readable context
β”‚    Homebrew tap Β· WinGet/Scoop Β· Code-signed binaries
β”‚
β—‹  Stage 9 Β· Beta Features                                     [ planned ]
β”‚    Generic OIDC identity broker β€” Microsoft, Apple, Okta, any OIDC IdP
β”‚      via discovery, not just Google + GitHub
β”‚    User groups β€” hierarchical, role inheritance, JWT claims
│    Tenant export / import — disaster recovery, staging→prod migration
β”‚    Token introspection with bloom filter cache
β”‚    Bulk user import β€” NDJSON, supports Argon2id passthrough + re-hash
β”‚    Account self-service β€” sessions list/revoke, email change, password
β”‚      change with current-password verification
β”‚
β—‹  Stage 10 Β· Distribution & Auto-update                       [ planned ]
β”‚    Auto-update check on startup β€” pulls latest binary if newer available
β”‚    In-place binary replacement without reinstall or service interruption
β”‚    Configurable update channel (stable / beta) via env var or config file
β”‚    Opt-out flag for air-gapped / locked environments
β”‚
β—‰  Stable beta β€” Q3 2026

Have a feature in mind or found a bug? Open a Discussion. Found a security issue? See Security for the reporting process.


How to help

OVLT is a one-maintainer project. The highest-impact contributions right now:

  1. Security review. Read the code. File issues for anything that looks off. Especially: auth endpoints, token validation, RLS extractor, encryption boundaries. See the Security policy for how to report.
  2. Tests. Stage 6 is actively in progress. Integration tests, regression tests for fixed bugs, and tenant isolation tests are all open for contribution. See CONTRIBUTING.md.
  3. Production smoke-testing. Deploy OVLT in a staging environment. Report what breaks. Bugs found in real deployments are worth ten times bugs found in code review.
  4. Documentation. If something confused you during setup, that's a doc bug. Doc PRs are reviewed fast.
  5. Client SDKs. OPAQUE will need a JS client. Python and Go SDKs are planned. Early contributors welcome.

For larger work (new auth flow, encryption change, multi-tenancy logic), open an issue first to align.


License

MIT License β€” free to use, modify, and distribute.


How this project is built

AI tools (Claude, GitHub Copilot) accelerate boilerplate, docs, and iteration cycles. Every commit is reviewed by the author. Architecture and security decisions are the author's responsibility β€” and the gaps in tests, threat model, and external review are also the author's responsibility to close. The Roadmap reflects current state honestly. Code review, security reports, and contributions are welcome and credited.


ovlt.tech Β· me@shrpp.dev Β· powered by hefesto

About

Lightweight OIDC Authorization Server in Rust. Authorization Code + PKCE, RS256, multi-tenant RLS, AES-256-GCM zero-knowledge encryption. ~20 MB RAM.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages