Keyorix
Lightweight secrets management for teams that can't use SaaS.
On-premise. Air-gapped ready. Single binary. No Vault admin required.
Why Keyorix?
¹ The core product needs no internet access. Optional integrations that delegate to an external identity provider — OIDC machine-identity federation, SSO login — need network reachability to that provider (which can itself live entirely inside a private network with no internet egress). See Configuration for what's required.
Vault is powerful but requires a dedicated admin. Doppler is simple but SaaS-only. Keyorix is both simple and runs entirely in your infrastructure.
Install
curl -L https://raw.githubusercontent.com/keyorixhq/keyorix/main/install.sh | sh
That installs the keyorix CLI only (Linux and macOS, amd64 and arm64). The server
(keyorix-server) is a separate release asset (keyorix-server_<os>_<arch> for
linux/darwin on amd64/arm64, plus a Linux-only -airgap variant, with
checksums.txt) — see QUICK_START.md — or a
container image (ghcr.io/keyorixhq/keyorix-server).
Or build from source (Go only; no C toolchain, the SQLite driver is pure Go):
git clone https://github.com/keyorixhq/keyorix
cd keyorix && make install
Quick Start
Self-host the full stack (web UI + API + PostgreSQL) with Docker Compose:
git clone --branch v0.96.3 https://github.com/keyorixhq/keyorix.git && cd keyorix # the compose file, .env.example and scripts/selfhost/ live in the repo; use a release tag, main can be ahead of the published images
cp .env.example .env
./scripts/selfhost/init-secrets.sh # generates ./secrets/* (Docker secrets files); admin password is in ./secrets/admin_password
docker compose up -d # open http://localhost:8088
See docs/SELF_HOSTING.md for production setup (TLS,
backups, upgrades, and the all-important encryption-key handling), and
docs/CONFIGURATION.md for the full keyorix.yaml
reference (encryption/KEK providers, MFA, WebAuthn, dynamic secrets, OIDC, …).
Running on edge or industrial devices, unattended or air-gapped sites:
docs/edge-deployment.md.
Or run just the server binary (the server needs a config, encryption keys and a
migrated database first, written by admin init; the passphrase comes from a file
or a prompt, not a command line):
keyorix-server admin generate-secrets # master passphrase, bootstrap token, admin password: 0600 files in ./secrets
export KEYORIX_MASTER_PASSWORD_FILE=secrets/master_password KEYORIX_BOOTSTRAP_TOKEN_FILE=secrets/bootstrap_token
keyorix-server admin init
keyorix-server admin encryption init
keyorix-server admin migrate
keyorix-server
QUICK_START.md has the full sequence, including creating the first admin.
Log in with the CLI:
keyorix login --server https://localhost:8080 --ca-file certs/server.crt --username admin
# Password: (typed at the no-echo prompt)
(certs/server.crt is the self-signed certificate keyorix-server admin init
generated; login remembers the CA file for later commands.)
With an authenticator app enrolled, login prompts for a code after the
password (an unused recovery code works too).
Create and use secrets (passwords and values are prompted or read from a file, not passed as flags, because command-line arguments are visible via ps and saved in shell history):
keyorix secret create --name db-password --interactive # value typed at a hidden prompt
keyorix run --env production --var DATABASE_URL=db-password -- node app.js
keyorix run --env production --var DATABASE_URL=db-password -- flask run
keyorix run --env production --var DATABASE_URL=db-password -- ./myapp
Secrets are injected as environment variables under the name YOU choose with
--var NAME=secret-ref (repeatable). The old behavior — auto-deriving the env
var name from the secret's own name (db-password becoming DB_PASSWORD) — is
still available via the deprecated --derive-names flag, but is no longer the
default: it let whoever names a secret also choose the env var it becomes.
Migrate from Vault
# From Vault (Medusa YAML export)
keyorix secret import --file vault-export.yaml --format vault --project 1 --env 1
# From .env files
keyorix secret import --file .env --format dotenv --project 1 --env 1
# Preview before importing
keyorix secret import --file vault-export.yaml --format vault --project 1 --env 1 --dry-run
For a live Vault/OpenBao instance (rather than a static export file) —
including AWS/Azure/GCP secret managers — use keyorix-migrate, a separate
release binary (keyorix-migrate_<os>_<arch>) that connects directly and
imports over the Keyorix REST API. See
docs/migrate-from-vault.md and
docs/migrate-from-cloud.md.
SDKs
Fetch secrets directly from your application at startup. Zero hardcoded credentials.
Go, Python, Node.js, and Java SDKs live together in
keyorixhq/keyorix-sdks
(github.com/keyorixhq/keyorix-go is archived — superseded by the go/
directory there). Recommended for an app running unattended: authenticate
with a machine identity token (keyorix machine token issue <name|id>),
not a user's password — see docs/sdks.md for the full
picture, including PATs, error handling, and TLS with a private CA.
Go
go get github.com/keyorixhq/keyorix-sdks/go
client, _ := keyorix.New("https://your-server:8443", os.Getenv("KEYORIX_TOKEN"))
dbPassword, _ := client.GetSecretScoped(ctx, "db-password",
keyorix.ProjectByName("my-project"), keyorix.EnvironmentByName("production"))
Python (from source: not verified yet, see the note below)
client = keyorix.Client("https://your-server:8443", os.environ["KEYORIX_TOKEN"])
db_password = client.get_secret_scoped("db-password", "my-project", "production")
Node.js (from source)
git clone https://github.com/keyorixhq/keyorix-sdks.git
npm pack ./keyorix-sdks/node
npm install ./keyorixhq-sdk-0.3.0.tgz
const client = new keyorix.Client("https://your-server:8443", process.env.KEYORIX_TOKEN);
const dbPassword = await client.getSecretScoped("db-password", "my-project", "production");
Java (from source: not verified yet, see the note below)
KeyorixClient client = Keyorix.newClient("https://your-server:8443", System.getenv("KEYORIX_TOKEN"));
String dbPassword = client.getSecretScoped("db-password", "my-project", "production");
Packages are not published yet. pip install keyorix,
npm install @keyorixhq/sdk and the com.keyorix:keyorix-sdk Maven
dependency do not work today: nothing is on PyPI, npm or Maven Central. Only
the Go module resolves from a registry. The Node.js steps above (clone, pack,
install the tarball) were run and the package loads. A from-source install of
the Python and Java SDKs has not been verified yet; use the python/ and
java/ directories of the keyorix-sdks clone and their READMEs.
Each language's examples/petstore/ directory in
keyorix-sdks has a full
working demo with Docker Compose. No release has been tagged for
keyorix-sdks yet — see that repo's own COMPATIBILITY.md for the
current verified-compatible state.
Core Features
Secrets management
- Create, read, update, delete secrets with full versioning
- Environment separation: development, staging, production
- Secret sharing between users and groups
Access control
- Role-based access control (RBAC)
- Group-based permissions
- Service tokens for CI/CD and automation
- Dynamic secrets — on-demand credential generation with TTL
Audit and compliance
- Every access logged: who, what, when, from where
- Two audit layers:
audit_eventsandsecret_access_logs - NIS2 / DORA alignment for European compliance requirements
- Dashboard expiry alerts for secrets approaching rotation deadlines
- ML-based access anomaly detection and alerting
Developer experience
keyorix run— inject secrets into any processkeyorix secret import— migrate from Vault, .env files, JSONkeyorix login— single command server authentication- MCP server for AI-assistant integration — read-only (
keyorix_get_secret,keyorix_list_secrets), no write/rotate/delete tools (ADR-061) - Web dashboard for teams who prefer a UI
Architecture
Two binaries: a thin keyorix CLI that only ever talks REST to a server, and the
keyorix-server binary itself (HTTP REST on port 8080 by default; a partial gRPC
surface on port 9090, off unless server.grpc.enabled). A server built with make build-ui serves the web UI on the HTTP port;
the Docker Compose stack publishes it on 8088. The CLI has no local database mode and cannot bypass the server's own
authorization/audit — see docs/ARCHITECTURE.md for the full
picture, including keyorix-server admin's offline, host-side operations (recover a
locked-out admin, offline backup/restore, independent audit-chain verification).
SQLite for development and small teams. PostgreSQL for production.
Air-gapped deployment: copy the keyorix-server binary and run — no internet required,
and an air-gapped build profile excludes every cloud-SDK dependency entirely (see
docs/ARCHITECTURE.md).
(Optional features that delegate to an external identity provider — OIDC federation, SSO
login — need network reachability to that provider; see
Configuration.)
Security
- AES-256-GCM encryption for all secret values
- Envelope encryption: passphrase → PBKDF2 → KEK (memory only) → wrapped DEK
- Constant-time token comparison (timing attack prevention)
- Secrets never logged or exposed in error messages
Security issues: [email protected]
Roadmap
- Kubernetes service account authentication
License
AGPL-3.0. Commercial licensing available for enterprise deployments.
Contact: [email protected]
About
Built by Andrei Beshkov, ex-Microsoft Security PM, Valencia, Spain.
Keyorix SL — your data stays in your infrastructure.