Zero trust SSH

Passwordless, keyless SSH at any scale

Octelium is a free and open source, self-hosted zero trust access platform. Its SSH mode authenticates to the upstream server on the User's behalf, so nobody receives a password or a private key, there is no SSH certificate authority to operate, and every session is authorized per connection and recorded.

  • Free and open source
  • No keys to distribute
  • No PKI to operate
ssh.yaml
An SSH ServiceThe private key stays in the Cluster and is used to authenticate to the upstream.
An SSH Service. The private key stays in the Cluster and is used to authenticate to the upstream.
kind: Service
metadata:
  name: bastion
spec:
  mode: SSH
  port: 22
  config:
    upstream:
      url: ssh://10.0.2.14
    ssh:
      user: deploy
      auth:
        privateKey:
          fromSecret: bastion-key
A Policy. Access is authorized per connection, from identity, context and the requested SSH user.
kind: Policy
metadata:
  name: ops
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.user.spec.type == "HUMAN"
            - match: '"ops" in ctx.user.spec.groups'
            - match: ctx.request.ssh.connect.user != "root"
Embedded SSH. A connected client can serve SSH itself, with no SSH server on the host and no root.
kind: Service
metadata:
  name: essh1
spec:
  mode: SSH
  config:
    ssh:
      eSSHMode: true
service-private.yaml
A server in a private networkA host in any environment, reached over the tunnel through a single stable route.
A server in a private network. A host in any environment, reached over the tunnel through a single stable route.
kind: Service
metadata:
  name: app-01
spec:
  mode: SSH
  port: 22
  config:
    upstream:
      url: ssh://10.0.2.20
    ssh:
      user: deploy
      auth:
        privateKey:
          fromSecret: deploy-key
A host behind NAT. The upstream address is resolved from the side of a connected client, so no port is opened.
kind: Service
metadata:
  name: workstation
spec:
  mode: SSH
  port: 22
  config:
    upstream:
      url: ssh://192.168.1.24
      user: alice
Hosts with no SSH server. The embedded mode serves SSH from inside the client, which suits fleets and containers.
kind: Service
metadata:
  name: fleet
spec:
  mode: SSH
  config:
    ssh:
      eSSHMode: true
policy-user.yaml
The requested SSH userThe SSH user asked for by the client is part of the request context.
The requested SSH user. The SSH user asked for by the client is part of the request context.
kind: Policy
metadata:
  name: no-root-ssh
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.request.ssh.connect.user != "root"
            - match: '"ops" in ctx.user.spec.groups'
Identity and context. Device posture, session type and group membership are attributes in the same expression.
kind: Policy
metadata:
  name: production-ssh
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.user.spec.type == "HUMAN"
            - match: ctx.session.status.type == "CLIENT"
            - match: ctx.device.status.osType in ["LINUX", "MAC"]
            - match: '"sre" in ctx.user.spec.groups'
Subsystems and forwarding. SFTP and local port forwarding are disabled by default and enabled explicitly.
kind: Service
metadata:
  name: bastion
spec:
  mode: SSH
  port: 22
  config:
    upstream:
      url: ssh://10.0.2.14
    ssh:
      user: deploy
      auth:
        privateKey:
          fromSecret: bastion-key
      enableSubsystem: true
      enableLocalPortForwarding: true
Secretless access

Keys and passwords that are never distributed

The upstream password or private key is stored in the Cluster as a Secret and used by the proxy to authenticate to the SSH server once a connection has been authorized. Nobody receives it, so there is nothing to rotate across laptops when someone leaves.

Read the secretless access guide
secret.sh
A private keyThe key is created as a Secret from a file and never leaves the Cluster.
A private key. The key is created as a Secret from a file and never leaves the Cluster.
octeliumctl create secret \
  --file ~/.ssh/id_ed25519 \
  bastion-key

# The Service then references it by name,
# and Users never receive the key itself.
The upstream host key. The upstream's public key is pinned, so the proxy verifies the host it connects to.
kind: Service
metadata:
  name: bastion
spec:
  mode: SSH
  port: 22
  config:
    upstream:
      url: ssh://10.0.2.14
    ssh:
      user: deploy
      auth:
        password:
          fromSecret: bastion-password
      upstreamHostKey:
        key: ssh-ed25519 AAAAC3NzaC1lZDI1...
A different user per identity. Group membership selects which upstream account and credential a connection uses.
kind: Service
metadata:
  name: ssh1
spec:
  mode: SSH
  dynamicConfig:
    configs:
      - name: root
        upstream:
          url: ssh://10.0.2.14
        ssh:
          user: root
          auth:
            password:
              fromSecret: root-password
      - name: usr
        upstream:
          url: ssh://10.0.2.14
        ssh:
          user: usr
          auth:
            password:
              fromSecret: usr-password
    rules:
      - condition:
          match: '"ops" in ctx.user.spec.groups'
        configName: root
      - condition:
          matchAny: true
        configName: usr
idp.yaml
Secretless workload identityCI jobs authenticate with OIDC assertions issued by the platform running them.
Secretless workload identity. CI jobs authenticate with OIDC assertions issued by the platform running them.
kind: IdentityProvider
metadata:
  name: github-actions
spec:
  oidcIdentityToken:
    issuerURL: https://token.actions.githubusercontent.com
    audience: https://example.com
A workload User. A deployment job that needs a shell is a User with its own groups and audit trail.
kind: User
metadata:
  name: deployer
spec:
  type: WORKLOAD
  groups:
    - ci
Recording options. Session recording is on by default, and stdin capture is opt-in for non-interactive runs.
kind: Service
metadata:
  name: bastion
spec:
  mode: SSH
  config:
    upstream:
      url: ssh://10.0.2.14
    ssh:
      visibility:
        enableSessionStdinRecording: true
Visibility and auditing

Session recordings, streamed as they happen

Every SSH session produces AccessLogs identifying the User, Session and Device alongside the SSH detail of the session itself, emitted in real time to your OpenTelemetry OTLP receivers.

Read about visibility and auditing
AccessLogOTLP
ALLOWlinus@acme.compg-prod.dbPOSTGRESquery: select id, email from users limit 50
ALLOWci-runnerprod-k8sKUBERNETESverb=list resource=pods namespace=production
DENYagent-07tools-mcpMCPtools/call name=transfer policy=mcp-tools
ALLOWjane@acme.combastionSSHsession recorded, upstream user=deploy
ALLOWagent-07openaiLLMCHAT_COMPLETIONS model=gpt-5-mini tokens=1284
octeliumctl
octeliumctl apply ./cluster
$ octeliumctl apply ./cluster
Secret: bastion-key Updated
Secret: root-password Updated
IdentityProvider: okta Updated
Policy: no-root-ssh Created
Group: ops Created
Group: sre Updated
Service: bastion Created
Service: app-01 Created
Service: fleet Created
User: deployer Created
Cluster Core resources successfully applied
 7 resources created
 3 resources updated

 ClusterConfig updated
SSH at scale

What SSH access has to solve, and what solves each part

SSH itself is not the difficult part. These are the problems that appear once more than a handful of people reach more than a handful of hosts, next to the mechanism in an Octelium Cluster that handles each one.

  1. 01

    Getting a key onto the right machines

    Nothing is distributed. The upstream password or private key is stored in the Cluster as a Secret and used by the identity-aware proxy to authenticate to the upstream, so no authorized_keys file has to be maintained across a fleet.

    Read more
  2. 02

    Taking it away again

    Revoking access is a Policy change or a Session revocation rather than a key removal on every host someone could reach, which is what makes offboarding reliable rather than a checklist.

    Read more
  3. 03

    Avoiding a certificate authority to run

    There is no SSH PKI to operate, no signing service to keep available and no certificate lifetime to tune. Authentication to the Cluster is your existing identity provider, and authentication to the upstream is the Cluster's own credential.

    Read more
  4. 04

    Deciding which account someone lands in

    The Service can force the upstream SSH user regardless of what the client asks for, and dynamic configuration can map different groups to different accounts and credentials on the same host.

    Read more
  5. 05

    Verifying the host being connected to

    The upstream's public key is pinned in the Service in OpenSSH format and verified by the proxy on connect, so host key checking is configuration rather than something each person confirms on first use.

    Read more
  6. 06

    Reaching hosts that cannot run a server

    The embedded SSH mode serves SSH from inside the octelium client itself, without a standalone SSH server on the host and without root privileges, which suits fleets of containers, IoT devices and confined environments.

    Read more
  7. 07

    Limiting what a session can do

    SSH subsystem requests such as SFTP and local port forwarding are both disabled by default and enabled explicitly per Service, so file transfer and tunnelling are decisions rather than side effects of shell access.

    Read more
  8. 08

    Being able to show what happened

    Sessions are recorded and streamed in real time over OpenTelemetry, alongside exec requests, subsystem requests and port forwarding events, each identified by the User, Session and Device behind it.

    Read more

Certificates shorten the life of a credential, which helps. They do not remove the credential from the person's machine, and they add a certificate authority to operate. Injecting the credential at the proxy removes both.

Questions

Frequently asked

How do people connect?
With their ordinary SSH client. The Service is reachable at a stable private name over the client-based tunnel, and the identity-aware proxy authenticates to the upstream on the User's behalf. Nothing about the local SSH workflow changes, and no key or password is entered.
Do I have to run a certificate authority?
No. There is no SSH PKI to operate. People authenticate to the Cluster through your existing OpenID Connect or SAML 2.0 identity provider, and the Cluster authenticates to the upstream with a password or private key held as a Secret. Which credential is used, and which upstream account it maps to, can be selected per request from identity and context.
Can it SSH into hosts that do not run an SSH server?
Yes. The embedded SSH mode lets a connected client serve SSH from inside the octelium client itself, without a standalone SSH server on the host and without root privileges. Authorized Users then SSH into a host by using that Session's name as the SSH user. A Cluster ships with a built-in Service for this, so nothing has to be defined to use it.
Are sessions recorded?
Yes. SSH Services emit full session recordings alongside exec requests, subsystem requests and port forwarding session events, streamed in real time over OpenTelemetry to your own log management and SIEM providers. Recording can be disabled per Service, and stdin recording can be enabled explicitly, which is useful for non-interactive sessions where stdin is not echoed.
Can SFTP and port forwarding be used?
Both are disabled by default and enabled explicitly per Service, with enableSubsystem for subsystem requests such as SFTP and enableLocalPortForwarding for local forwarding. Port forwarding sessions are recorded as their own event types in the access logs.
Is Octelium free and open source?
Yes. Octelium is free and open source and is designed for single-tenant self-hosting. There is no proprietary cloud-based control plane, and it is not a limited edition of a separate paid product. An enterprise package is available for organizations that need capabilities such as a web console, SCIM provisioning and secret encryption at rest, and it is free for personal, homelab and evaluation use.
Get started

Deploy Octelium on your own infrastructure in minutes

Free and open source. Self-hosted. No vendor lock-in.