Zero trust network access

The open source, self-hosted ZTNA platform

Octelium is a free and open source, self-hosted zero trust access platform. It provides identity-based, layer-7 aware access control on a per-request basis, dynamic secretless access, and a unified architecture for both client-based and clientless access, for humans, workloads and AI agents alike.

  • Free and open source
  • Designed for self-hosting
service.yaml
A ServiceEvery protected resource is a Service, whatever protocol it speaks and wherever it runs.
A Service. Every protected resource is a Service, whatever protocol it speaks and wherever it runs.
kind: Service
metadata:
  name: hr-app
spec:
  mode: HTTP
  config:
    upstream:
      url: http://10.0.3.18:8080
A Policy. Access is authorized per request, from identity, context and the request itself.
kind: Policy
metadata:
  name: hr-team
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: '"hr" in ctx.user.spec.groups'
            - match: ctx.session.status.type == "CLIENT"
            - match: ctx.device.status.osType in ["MAC"]
A workload User. Non-human subjects are Users too, with the same Groups, Policies and audit trail.
kind: User
metadata:
  name: ci-runner
spec:
  type: WORKLOAD
  groups: ["automation"]
  authentication:
    identities:
      - identityProvider: github-actions
        identifier: repo:acme/api
Client-based and clientless

One architecture for both ways of reaching a resource

Each resource is protected by an identity-aware proxy that provides application-layer-aware access control, secretless access, and visibility. Users reach Services through two equivalent modes.

Read how Octelium works
service-private.yaml
Client-based accessA private resource reached over the tunnel through a single stable route and private DNS.
Client-based access. A private resource reached over the tunnel through a single stable route and private DNS.
kind: Service
metadata:
  name: metrics
spec:
  mode: HTTP
  config:
    upstream:
      url: http://10.0.3.44:9090
Clientless access. The same Service published over HTTPS for browsers and for workloads, with no client.
kind: Service
metadata:
  name: metrics
spec:
  mode: HTTP
  isPublic: true
  config:
    upstream:
      url: http://10.0.3.44:9090
Grouped and governed together. Services are grouped into Namespaces, and a Policy can be attached to the whole Namespace.
kind: Namespace
metadata:
  name: internal
spec:
  authorization:
    policies:
      - hr-team
      - deny-contractors
policy-identity.yaml
Identity and deviceGroup membership, Session type and Device attributes sit in one expression.
Identity and device. Group membership, Session type and Device attributes sit in one expression.
kind: Policy
metadata:
  name: hr-team
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: '"hr" in ctx.user.spec.groups'
            - match: ctx.session.status.type == "CLIENT"
            - match: ctx.device.status.osType in ["MAC"]
Authentication strength. Who has to re-authenticate with a FIDO2, TPM 2.0 or TOTP authenticator is itself a rule.
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  authenticator:
    authenticationEnforcementRules:
      - condition:
          match: ctx.session.status.isBrowser
        effect: ENFORCE
      - condition:
          match: '"security" in ctx.user.spec.groups'
        effect: ENFORCE
Explicit denial. A deny rule wins over an allow rule, and both are recorded in the access logs.
kind: Policy
metadata:
  name: deny-contractors
spec:
  rules:
    - effect: DENY
      condition:
        match: '"contractors" in ctx.user.spec.groups'
Secretless access

Credentials that are never distributed

Application-layer credentials are stored in the Cluster as Secrets and injected into the upstream connection once a request is authorized. This removes credential sprawl for teams and, increasingly, for workloads and AI agents.

Read the secretless access guide
service-postgres.yaml
PostgreSQLThe upstream password stays in the Cluster. Users connect without ever receiving it.
PostgreSQL. The upstream password stays in the Cluster. Users connect without ever receiving it.
kind: Service
metadata:
  name: reporting
spec:
  mode: POSTGRES
  port: 5432
  config:
    upstream:
      url: postgres://10.0.5.9:5432
    postgres:
      user: reporting_ro
      database: reporting
      auth:
        password:
          fromSecret: reporting-password
An internal API. An API key is injected upstream after authorization instead of being handed to a team.
kind: Service
metadata:
  name: payroll
spec:
  mode: HTTP
  config:
    upstream:
      url: https://payroll.internal
    http:
      auth:
        bearer:
          fromSecret: payroll-token
The credential itself. Credentials are ordinary Cluster resources, created out of band and referenced by name.
# Nothing about the value is ever written to Git
octeliumctl create secret payroll-token

# Or from a file, or from a value
octeliumctl create secret \
  --file ./token payroll-token
identity-provider.yaml
Secretless workload identityWorkloads authenticate with OIDC assertions issued by the platform running them.
Secretless workload identity. Workloads 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
Tool-level authorization. MCP JSON-RPC methods and tool names are normalized into the request context.
kind: Policy
metadata:
  name: mcp-tools
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.request.mcp.method == "tools/call"
            - match: ctx.request.mcp.name == "search_docs"
            - match: '"agents" in ctx.user.spec.groups'
An LLM gateway. The inference request is validated and the provider credential is injected upstream.
kind: Service
metadata:
  name: openai
spec:
  mode: LLM
  config:
    upstream:
      url: https://api.openai.com
    llm:
      protocol: OPENAI
      auth:
        bearer:
          fromSecret: openai-api-key
      limits:
        maxOutputTokens: 8192
Visibility and auditing

Real-time visibility at the application layer

OpenTelemetry-ready, application-layer aware, structured auditing and visibility emitted to your OpenTelemetry OTLP receivers, where they can be exported to your log management and SIEM tools.

Read about visibility and auditing
AccessLogOTLP
ALLOWjane@acme.comhr-appHTTPGET /reviews/2026 200, device=MAC
DENYcontractor-3payrollHTTPGET /v1/salaries policy=deny-contractors
ALLOWci-runnerreporting.dbPOSTGRESquery: select id, total from invoices
ALLOWlinus@acme.combastionSSHsession recorded, upstream user=deploy
ALLOWagent-07openaiLLMCHAT_COMPLETIONS model=gpt-5-mini tokens=1284
octeliumctl
octeliumctl apply ./cluster
$ octeliumctl apply ./cluster
Secret: payroll-token Updated
Secret: reporting-password Updated
IdentityProvider: github-actions Created
Policy: hr-team Created
Policy: deny-contractors Created
Group: hr Updated
User: ci-runner Created
Service: hr-app Created
Service: reporting.db Created
Namespace: internal Created
Cluster Core resources successfully applied
 8 resources created
 2 resources updated

 ClusterConfig updated
NIST SP 800-207

The zero trust tenets, and what implements each one

Zero trust is a security model rather than a product category. These are the principles NIST SP 800-207 sets out, next to the concrete mechanism in an Octelium Cluster that carries each one, so the architecture can be examined rather than taken on faith.

  1. 01

    Every resource is protected individually

    Applications, APIs, SSH servers, databases, Kubernetes clusters, DNS and generic TCP and UDP resources are each represented by a Service. Access is authorized against the Service and the request itself, not inferred from reaching the network the upstream sits on.

    Read more
  2. 02

    Network location grants nothing on its own

    Connecting to a Cluster does not by itself grant access to anything. Humans authenticate through your OpenID Connect or SAML 2.0 identity provider and built-in authenticators, and workloads through OAuth2 client credentials, bearer tokens, authentication tokens or OIDC assertions.

    Read more
  3. 03

    Communication is secured wherever it comes from

    Client-based access is carried over encrypted WireGuard or QUIC tunnels and clientless access over HTTPS. The same Service, identity, Policy and audit model applies to both, so there is no privileged path.

    Read more
  4. 04

    Access is authorized per request

    Every request is authorized explicitly against Policies written in CEL or Open Policy Agent, evaluated separately from the proxy that serves the resource. A session, a tunnel or a prior decision does not stand in for the next one.

    Read more
  5. 05

    Decisions use dynamic context

    Policies can evaluate the User, Group memberships, Session, Device, authentication strength, Service, Namespace, geolocation, the application-layer request, and arbitrary attributes supplied by external systems such as SIEM, threat intelligence and on-call tools.

    Read more
  6. 06

    Zero standing privileges

    No permanent admins or superuser Users. All access is explicitly granted through Policies which can be tid to time and context.

    Read more
  7. 07

    Authorization is continuously reevaluated

    Access tokens are not treated as stateless proof of authorization. Current Session, User, Group, Device and Policy state is resolved at authorization time, so deleting a Session, disabling a User or changing a Policy takes effect without waiting for a token to expire.

    Read more
  8. 08

    Everything is logged and exported

    Allowed and denied access both produce structured AccessLogs identifying the User, Session, Device, Service, the result, the matching Policy and rule, and the protocol-specific detail, streamed in real time to OpenTelemetry OTLP receivers.

    Read more

Network segmentation on its own is not zero trust, multi-factor authentication on its own does not create a zero trust architecture, and establishing a tunnel is not an authorization decision. Each can be a mechanism inside one.

Questions

Frequently asked

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.
Is a VPN tunnel compatible with zero trust?
A tunnel is a transport, not an authorization decision. Octelium uses encrypted WireGuard and QUIC tunnels for client-based access, but establishing one grants access to nothing on its own: every request through it is still authorized against a Service and its Policies, with the same evaluation and the same audit trail as a clientless request over HTTPS.
Do I have to replace my identity provider?
No. Any OpenID Connect or SAML 2.0 identity provider is supported, as well as GitHub OAuth2. Octelium additionally provides native FIDO2 and WebAuthn passkeys, TOTP and TPM 2.0 authenticators that can be required through Policy on sensitive Services, independently of what the identity provider itself enforces.
What does layer-7 aware access control mean in practice?
Authorization sees the request, not just the connection. A Policy can allow a specific HTTP method and path but not others, a Kubernetes verb on a resource in one namespace, a particular database and database user, a named MCP tool, or an LLM model and token ceiling, all in the same expression as identity, device and session attributes.
How are workloads and AI agents covered?
Workload Users share the same identity model as human Users. They authenticate with authentication tokens, with the standard OAuth2 client credentials flow, or secretlessly with federated OIDC assertions issued by the platform hosting them, such as GitHub Actions, a cloud provider or a Kubernetes cluster. No special SDK or client is required.
Do I need to know Kubernetes to run it?
An Octelium Cluster runs on top of Kubernetes, but you do not need Kubernetes experience to install, operate or use it. The quick installer provisions a complete single-node Cluster, including Kubernetes itself, on one fresh Linux VM/server and a domain you own. Production Clusters run on scalable managed or on-premise Kubernetes installations.
Get started

Deploy Octelium on your own infrastructure in minutes

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