
Ephemera is a lightweight, self-hosted SSH Certificate Authority designed to enforce Zero-Trust access for infrastructure. It replaces static SSH keys with short-lived certificates, integrates hardware-backed WebAuthn MFA, and maintains cryptographically verifiable audit trails.
[!NOTE] Canonical Source: Codeberg
GitHub Mirror: GitHub (for availability and hosting)
graph LR
subgraph Client["User (Operator)"]
SSH["SSH Client"]
HW["Hardware Key<br/>WebAuthn / YubiKey"]
end
subgraph Auth["Authentication Boundary"]
MFA["WebAuthn MFA<br/><i>Human presence required</i>"]
OIDC["OIDC<br/><i>Optional</i>"]
end
subgraph CA["Ephemera SSH Certificate Authority"]
CORE["Self-hosted CA<br/>Air-gap capable"]
POLICY["Policy Engine<br/><i>Governance at issuance</i>"]
BUDGET["Trust Budgeting<br/><i>Optional</i>"]
end
subgraph Targets["Target Servers"]
NATIVE["Native OpenSSH<br/>TrustedUserCAKeys"]
NOAGENT["No agents<br/>No SSH proxy"]
end
subgraph Audit["Audit & Recovery"]
LOG["Tamper-Evident<br/>Audit Log"]
BACKUP["Encrypted Backups<br/>Shamir Recovery"]
end
Client --> Auth
Auth -->|"Short-lived cert"| CA
CA -->|"Certificate expires<br/>automatically"| Targets
CA -.->|"Post-fact integrity"| Audit
style Auth fill:#e8f5e9,stroke:#2e7d32
style CA fill:#e3f2fd,stroke:#1565c0
style Audit fill:#fff3e0,stroke:#ef6c00
What Ephemera does: Governs who may receive access and for how long.
What Ephemera does NOT do: Runtime monitoring, MITM proxying, command inspection.
Enforcement: Entirely within native OpenSSH — no Ephemera agent on target servers.
Key rotation: Not needed — certificates expire automatically.
Ephemera is a self-hosted SSH Certificate Authority built on native OpenSSH features. It replaces long-lived SSH keys with short-lived certificates issued just-in-time, with explicit physical presence and auditable privilege escalation.
It is designed for teams that want centralized SSH governance without MITM proxies, custom protocols, or cloud dependencies.
Core SSH CA functionality: Production-ready
Trust Budgeting: Experimental (opt-in, subject to change)
The experimental features are clearly isolated and disabled by default.
Traditional SSH relies on long-lived private keys spread across laptops and servers. Once a key leaks, access persists until you discover it and rotate keys everywhere. Ephemera replaces static keys with short-lived certificates that expire automatically, shrinking the window of misuse from months to minutes.
Just-in-Time Access : Certificates expire in minutes (default 5m), reducing the window of opportunity for stolen credentials.
WebAuthn Enforcement : Certificate issuance requires physical MFA (FIDO2) interaction via YubiKey or TouchID.
Sovereign Recovery : Encrypted backups are protected via Shamir's Secret Sharing, requiring a quorum to restore.
Verifiable Audit : All CA actions are logged to a Merkle-chained ledger for tamper-evident history.
Granular RBAC : A YAML-based policy engine defines access based on roles, resources, and conditions.

Ephemera includes an experimental, opt-in governance primitive called Trust Budgeting.
Trust Budgeting limits cumulative privileged authority at certificate issuance time by treating access as a finite, visible resource. Each certificate issuance consumes an explicit budget. When the budget is exhausted, normal issuance stops until the budget resets or a separate emergency (break-glass) path is used.
This mechanism:
Trust Budgeting is experimental and may change or be removed.
Documentation: docs/trust_budgeting.md
Ephemera includes GateBridge, a shadow evaluation system that validates policy decisions against an alternate engine (Gate0) without affecting production behavior.
policy-shadow.log)Each entry contains:
GET /api/admin/gate0/status
Returns:
{
"bridge_version": "1.0.0",
"gate0_version": "v0.2.1",
"policy_hash": "sha256:8f4b...",
"status": "healthy",
"last_mismatch": null,
"telemetry": {
"latency_p50_ms": 2.3,
"latency_p95_ms": 5.1,
"latency_p99_ms": 8.7
}
}
GateBridge can be disabled via configuration flag. Shadow mode is fail-open and does not affect authorization decisions.
No breaking changes to Gate0 CLI interface. Shadow logs gain new fields but remain backward parseable.
Goal: Issue your first SSH certificate in under 5 minutes.
# Clone and start
git clone https://github.com/Qarait/ephemera.git
cd ephemera
docker compose up -d
Note: CA master password is auto-generated and persisted on first run.
For production, setCA_MASTER_PASSWORDin a.envfile before starting.
[!IMPORTANT] Production Deployments: Use the SoftHSM backend for hardware-backed key isolation. The CA private key never touches disk. See PKCS#11 Setup Guide.
Open http://localhost:3000 in your browser.
Default credentials:
admindocker compose logs ephemera | grep "Password:"
Alternative Compose Files:
docker-compose.dev.yml — Development with local builds and syslogdocker-compose.test.yml — Includes SSH target for end-to-end testing# Install the CLI from source
git clone https://github.com/Qarait/ephemera.git
cd ephemera
pip install .
# Initialize your SSH config
ephemera init
# Login to the CA
ephemera login
# Issue your first certificate
ephemera renew
# Check your status
ephemera status
# Connect securely!
ssh user@your-server
Ephemera provides a secure backup mechanism that encrypts your critical data (CA keys, database) with a random password, and then splits that password into Shamir shards. This ensures that no single person can restore the backup, but a quorum can.
# Create encrypted backup and split password into 5 shards (threshold 3)
ephemera backup-create --k 3 --n 5 --out-dir ./backup
This produces:
ephemera_backup.enc (The encrypted archive)backup_shard_1_of_5.json, etc. (The password shards)Note: Store the shards in separate, secure locations. Store the encrypted backup file safely (it is useless without the shards).
# Restore using the encrypted file and any 3 shards
ephemera backup-restore --backup ./backup/ephemera_backup.enc --shards ./backup/backup_shard_1_of_5.json ./backup/backup_shard_2_of_5.json ./backup/backup_shard_4_of_5.json --out-dir ./restored
policy.yaml)Ephemera uses a powerful YAML-based policy engine for Role-Based Access Control (RBAC).
# Define Roles
roles:
developer:
can_request_cert: true
max_cert_duration: 300 # 5 minutes
allowed_principals: ["dev-user"]
admin:
can_request_cert: true
max_cert_duration: 3600 # 1 hour
allowed_principals: ["root", "admin"]
can_approve_sudo: true
# Define Rules
rules:
# Developers can only access dev servers
- role: developer
resource: "dev-*"
action: "ssh"
effect: allow
# Admins can access everything with MFA
- role: admin
resource: "*"
action: "ssh"
effect: allow
conditions:
mfa_required: true
Please see SECURITY.md for responsible disclosure information.
Looking to contribute? Check out our Small Tasks for New Contributors.
[!TIP] Threat model and security assumptions are documented here. Feedback and critique are welcome.
| Field | Description |
|---|
timestamp | ISO 8601 UTC timestamp |
match | Boolean — did both engines agree? |
versions.bridge | GateBridge Python version |
versions.gate0 | Gate0 CLI version |
versions.policy_hash | SHA256 hash of policy.yaml |
context_hash | SHA256 hash of canonicalized input |
yaml_decision | YAML engine result |
gate0_decision | Gate0 engine result |
snapshot | Full context (only on mismatch, size-capped) |