Identity-aware access to your infrastructure. Short-lived, audited, self-hosted.
Try it · How it works · What it connects to · What is not verified yet · Docs
Limen decides who can reach your servers, databases and clusters, and keeps a record of what they did there.
Engineers sign in through your company's identity provider. Limen checks a policy you keep in Git, then gives them a certificate that expires in an hour (or sooner: you choose per role). They connect with the tools they already use (ssh, psql, kubectl, redis-cli), and every session is recorded or audited into a signed trail you can verify yourself. CI jobs sign in the same way, with their own short-lived token, so your pipelines hold no long-lived secret either.
It is open source (Apache-2.0), written in Rust, and you run it on your own infrastructure. It is not production-ready yet: there is no release, and nothing has been tried against real cloud services. What is not verified yet has the details.
Keys, passwords and tokens tend to outlive the reason they were handed out. Limen is built so that no person or pipeline holds one for long, and so that you can always answer two questions: who can get in right now, and what did they do?
| Without it | With Limen | |
|---|---|---|
| Getting onto a server | An SSH key that stays valid until someone removes it | A certificate that expires in an hour, or sooner if you choose |
| Getting into a database | A password that people copy and share | limen db connect orders-prod. Only Limen's worker holds the database credential; no person sees it |
| Someone leaves the team | Find and remove every key and password they had | Disable them in your identity provider and they can't start new sessions. limen admin lock also ends their open ones within seconds |
| A CI job deploys | A long-lived secret stored in the CI settings | The job's own OIDC token becomes a short, scoped login |
| The network | Targets reachable from a bastion or a VPN | Limen's worker dials out from your network, so targets need no inbound port |
"Who ran that DELETE?" |
Depends on what the database logs, and for how long | Every statement, tied to the person or CI job that ran it, in a hash-chained trail |
$ limen login --proxy limen.example.com:443 # a browser opens on your identity provider
$ limen ls # what am I allowed to reach?
NAME KIND ACCESS AS LABELS
bastion-staging ● ssh ec2-user, ubuntu env=staging tier=bastion
orders-staging ● postgres limen_read, limen_write env=staging team=payments
web-staging-1 ● ssh ec2-user, ubuntu env=staging
3 resources · `limen show <name>` tells you how to connect to one
$ limen ssh web-staging-1 # a recorded SSH session
$ limen db connect orders-staging # a local address for psql, no password needed
$ limen explain orders-prod # why can't I reach this one?
$ limen request orders-prod --for 30m --reason "INC-123: orders table is locked"If a resource isn't in your list, limen explain tells you which rule stopped you, and limen request asks an approver for time-limited access.
There is no release to download yet, so this builds Limen from source and runs the whole system on your machine, with a test identity provider and test users. You need Docker (on macOS, OrbStack or Docker Desktop) and the tools pinned in mise.toml (run mise install). The first build takes several minutes.
git clone https://github.com/limen-dev/limen && cd limen
# 1. Start everything. The script checks your tools, asks what to enable (an SSH host,
# databases, Redis, Kubernetes, observability...), applies an example policy, and
# prints a ready-to-run command for each resource.
deploy/compose/setup.sh
# 2. Install the CLI (re-run after pulling to upgrade)
scripts/install-cli.sh
# 3. Sign in. A browser opens; use admin@example.com with the password "password".
limen --proxy localhost:3443 login --ca-file deploy/compose/.state/internal-ca.pem
# 4. Connect
limen ls
limen ssh web-staging-1
# 5. Open the web console, sign in as the same user, and replay the session you just had
open https://localhost:3443/console/ # on Linux, paste the address into a browserNote
Your browser will warn about the console's certificate. That is expected: it comes from a development CA the script just created. Click through the warning on localhost. Don't add that CA to your system's trust store. The other test users, and what each one is allowed to see, are listed in deploy/compose/README.md.
The quickstart walks through the same steps with more explanation.
Limen is three programs:
- The control plane signs people and bots in through your identity provider, issues their short-lived certificates, keeps the policy, and writes the audit trail. The only database it needs is PostgreSQL.
- The proxy is the one public entry point. It checks each connection against the policy and passes it to the right worker.
- The worker runs inside your network, next to the things you want to reach. It dials out to the proxy, so nothing on your side needs an open inbound port. It speaks each target's protocol, records or audits the session, and signs in to the target with credentials only it holds.
All three are static binaries. If Limen can't write the audit trail, it refuses new sessions rather than let them run unrecorded.
The diagrams page follows one connection step by step, and shows where credentials and audit events go when parts of the system fail.
Each target works with ordinary self-hosted servers and with the managed services listed under it. ✅ means built and tested against a local copy of that software.
Any OIDC provider Okta, Entra ID, Keycloak, Auth0, Dex your groups map to Limen roles ✅ tested with Dex |
GitHub Actions the job's OIDC token becomes a bot login ✅ tested with a stand-in issuer |
GitLab CI the job's ID token becomes a bot login ✅ tested with a stand-in issuer |
Other automation any OIDC token, including Kubernetes service accounts ✅ tested with a stand-in issuer ⏳ AWS IAM: Phase 15 |
A bot is matched on exact claims of its token (for example the repository and the branch), gets a short-lived certificate (15 minutes by default, at most an hour), and is bound by the same policy. The CI run that made each request is written into every audit event.
Audit events are written to S3 in signed batches, and each batch records the hash of the one before it, like links in a chain. If a batch goes missing, is reordered, or is edited, one command finds it:
limen-audit-verify --bucket <your-audit-bucket> --ca-file internal-ca.pemTraces carry only ids and outcomes, never user names, SQL statements or tokens. To see one locally, start the dev stack with Jaeger: deploy/compose/setup.sh --yes --stacks ssh,tracing.
|
|
| Status | |
|---|---|
| Docker Compose, the full stack on one machine | ✅ works; this is the local dev stack |
| Kubernetes, several copies of each program | ✅ example manifests; |
| Terraform for the audit store (S3, Glue, Athena) and the Datadog monitors | ✅ works |
| Amazon ECS and EC2, and a Helm chart | ⏳ planned, Phase 15 |
Limen is tested thoroughly, but only against local stand-ins: Dex in place of a real identity provider, databases and brokers in containers, a local S3 and KMS, and a fake Datadog intake. Nothing has been verified against real AWS, Okta or Datadog yet. The
Production hardening (a Helm chart, cloud deployment modules, a penetration test) comes after the next phase, and there is no tagged release yet. Until both are done, treat Limen as something to evaluate, not something to put in front of production systems.
Phases 0 to 13 are done: login and tunnels, SSH with recording, the audit pipeline, the console, bots, scale-out, the database, cache, Kubernetes, search and messaging protocols, internal web apps, and access workflows (requests and break-glass, audit search, discovery, policy tooling, access reviews, and watching a live session).
Next:
- Phase 14, one management API (in progress): manage roles, resources, and bots from the CLI, the console, or Terraform, with one owner per document and scoped writers for automation (ADR-0042, milestone)
- Phase 15, production readiness: a Helm chart, ECS and EC2 modules, and a penetration test (milestone)
- Verification against real services (milestone)
- The documentation site, already built in
website/, is published when the repository goes public (milestone)
Every phase is a GitHub milestone with its checklist in an epic issue. What "done" means for each one is in docs/design.md §13.
Start here
- Quickstart and concepts: run it, then understand what happened
- What is built and what is verified, item by item
Connect
Control access
- Policy reference · testing and questioning policy · access requests and break-glass · access reviews · bots for CI · the management API (Terraform) · resource discovery
Audit and operate
- The console · audit search · watching a live session · metrics and alerts · tracing · scale-out · runbooks
How it is built
- The three programs · design · diagrams · decision records (ADRs) · threat model · penetration test plan
Limen is Latin for "threshold", the root of the English word liminal. A threshold is where you stop until you're allowed in. That is the job: you prove who you are, Limen lets you across for a short, recorded visit, and the door closes behind you.
It's also short enough to type all day (limen login, limen ssh). Say it "LIE-men" or "LEE-men"; both are common.
Found a vulnerability? Please report it privately through GitHub, not in a public issue. SECURITY.md explains how, and what is in scope.
CONTRIBUTING.md covers the repository layout, how to build and test, and the conventions. Coding agents should read AGENTS.md.
Apache-2.0. Icons are from Simple Icons (CC0) and Lucide (ISC). Product names and logos belong to their owners and appear here only to say what Limen works with.