A zero trust remote access VPN over WireGuard
Octelium is a free and open source, self-hosted zero trust access platform. Client-based access runs over WireGuard tunnels and behaves as a zero-config VPN: a single stable route, stable private dual-stack addresses and automatic private DNS. What makes it zero trust is what sits above the tunnel, where every request is authorized on its own.
- Free and open source
- Designed for self-hosting
- Kernel WireGuard where available
kind: Service
metadata:
name: grafana
spec:
mode: HTTP
config:
upstream:
url: http://10.0.6.12:3000kind: Policy
metadata:
name: sre
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.user.spec.type == "HUMAN"
- match: '"sre" in ctx.user.spec.groups'
- match: ctx.session.status.type == "CLIENT"kind: Service
metadata:
name: workstation
spec:
mode: SSH
port: 22
config:
upstream:
url: ssh://192.168.1.24
user: aliceA unified secure access platform
The tunnel is one of them. Each capability is described in detail below, in the same order.
- Unified access platform
One architecture for client-based zero-config VPN-like access over WireGuard and QUIC tunnels and clientless access over browsers for humans and OAuth2 access for workloads.
Read more - L7-aware access control
Identity-based, application-layer aware ABAC access control with policy-as-code via CEL and OPA, applied on a per-request basis.
Read more - Secretless access
Dynamic secretless access where teams and AI agents access protected infrastructure without ever holding a credential.
Read more - Unified identity management
Teams, workloads and AI agents share the same model for identity management, access control, and auditing.
Read more - Real-time visibility and auditing
OpenTelemetry-native, real-time, application-layer-aware visibility and structured logging.
Read more - GitOps-friendly management
Octelium is administered like Kubernetes. Define your resources in YAML files, store them in a Git repository.
Read more
A tunnel that carries traffic, not permissions
Each resource is protected by an identity-aware proxy that provides application-layer-aware access control, secretless access, and visibility. Connecting to the Cluster establishes a path, and grants nothing by itself.
- The client connects over WireGuard to every Gateway, and each Service is reached through a single stable route with a stable private dual-stack address and an automatically managed private DNS name.
- A Service upstream can also be an address that is only reachable from the side of a connected host, which covers laptops, private clouds and equipment behind NAT with no inbound port anywhere.
- The very same Services can also be published clientlessly over HTTPS, for people in a browser and for workloads over standard OAuth2 and bearer authentication, with no client at all.
kind: Service
metadata:
name: grafana
spec:
mode: HTTP
config:
upstream:
url: http://10.0.6.12:3000kind: Namespace
metadata:
name: prod
spec:
authorization:
policies:
- srekind: Service
metadata:
name: grafana
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: http://10.0.6.12:3000Layer-7 aware access control with policy-as-code
Access is authorized on a per-request basis, using CEL or Open Policy Agent, against the identity behind the request and the content of the request itself rather than the network path it arrived on.
- Dynamic, fine-grained attribute-based access control ABAC with policy-as-code via CEL and OPA.
- Application-layer-aware access control that includes HTTP methods, paths, headers and serialized JSON body content, SSH users, Kubernetes verbs, resources and namespaces, and PostgreSQL and MySQL users and databases.
- Zero standing privileges. No permanent admins or superuser Users. All access is explicitly allowed by a Policy that can be tied by time and context.
kind: Policy
metadata:
name: sensitive
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'kind: Policy
metadata:
name: api-read-only
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.http.method == "GET"
- match: ctx.request.http.path.startsWith("/v1/")
- match: '"analysts" in ctx.user.spec.groups'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'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. A tunnel on its own does nothing about the API keys, database passwords and private keys that reach a resource once the tunnel is up.
- Covers HTTP API keys and access tokens, SSH passwords and private keys, PostgreSQL and MySQL passwords, kubeconfigs, and mTLS client certificates.
- The upstream account, user and credential can be selected dynamically per request from identity and context, so different Users reach the same upstream with different privileges.
- Revoking access is a Policy change rather than a credential rotation across every system a person or workload could reach.
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-keykind: Service
metadata:
name: pg-prod
spec:
mode: POSTGRES
port: 5432
config:
upstream:
url: postgres://10.0.4.21:5432
postgres:
user: analytics_ro
database: analytics
auth:
password:
fromSecret: pg-password
sslMode: REQUIREkind: Service
metadata:
name: stripe
spec:
mode: HTTP
config:
upstream:
url: https://api.stripe.com
http:
auth:
bearer:
fromSecret: stripe-api-keyA unified identity model for humans and workloads
Human and workload Users share the same identity management, authentication, access control and visibility model. A container in CI connects the same way an engineer does, and is authorized by the same Policies.
- Workloads authenticate with authentication tokens, with the OAuth2 client credentials flow, or secretlessly with federated OIDC assertions from GitHub Actions, cloud providers and Kubernetes clusters.
- People authenticate through any OpenID Connect or SAML 2.0 identity provider, with native FIDO2 and WebAuthn passkeys, TOTP and TPM 2.0 authenticators available on top of it.
- The MCP and LLM gateway modes extend the same identity, policy and audit model to the tools and model providers that AI agents reach.
- Cordium, built on Octelium, provides isolated sandboxes for agents and developers, where processes reach authorized Services through the Workspace identity with no secrets inside the sandbox.
kind: IdentityProvider
metadata:
name: github-actions
spec:
oidcIdentityToken:
issuerURL: https://token.actions.githubusercontent.com
audience: https://example.comkind: User
metadata:
name: ci-runner
spec:
type: WORKLOAD
groups:
- cikind: Service
metadata:
name: tools-mcp
spec:
mode: MCP
isPublic: true
config:
upstream:
url: http://mcp.internal:8080
mcp:
endpoint: /mcpReal-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.
- Application-layer-aware visibility with logs that include HTTP requests and responses, database queries, SSH session recordings, DNS question names, MCP methods and tool names, and LLM operations and token usage.
- That is a different kind of record from a connection log. A layer-4 tunnel can show that an address reached a port, not which query was run or which path was requested.
- Logs are exported over OpenTelemetry OTLP in real-time to SIEM providers you already operate.
A scalable platform that also deploys your workloads
A Cluster runs on Kubernetes and uses it to scale its own data plane, place Service proxies across Gateways, and run containerized applications that the Cluster itself deploys.
- Gateways scale horizontally rather than each one imposing a fixed ceiling on the traffic and the number of connections it can carry.
- The Cluster is managed declaratively. Resources are defined in YAML, kept in a Git repository, and applied with a single octeliumctl apply that reproduces the entire Cluster state.
- Management is centralized over the Cluster's gRPC APIs, so the Cluster is fully programmable and no configuration change requires SSH access to a server.
$ octeliumctl apply ./cluster
Secret: pg-password Updated
Secret: bastion-key Updated
IdentityProvider: okta Updated
Policy: sre Created
Group: sre Created
Group: analysts Updated
Service: grafana.prod Created
Service: bastion Created
Service: pg-prod.prod Created
Namespace: prod Created
Cluster Core resources successfully applied
7 resources created
3 resources updated
ClusterConfig updatedWhat the client does on the host, mode by mode
WireGuard is the transport, and the client adapts to whatever privileges it has. These are the parts that matter in practice, next to what each one actually does.
- 01
Kernel WireGuard where it exists
On Linux 5.6 and later, or any kernel with the WireGuard module loaded, the client uses the kernel implementation, which is by far the most performant mode. It needs root or the NET_ADMIN capability.
Read more - 02
A userspace TUN device otherwise
The wireguard-go TUN device implementation covers every platform, including macOS and Windows. It also needs permission to create a TUN device, and can be selected explicitly over the kernel mode.
Read more - 03
No privileges at all, if necessary
Without permission to create a TUN device, the client runs its own userspace network stack on gVisor Netstack as an ordinary non-root process. Services are then reached by mapping them to the host, which is what makes the client usable inside containers, CI runners and confined environments.
Read more - 04
One route, not a routing table
Services are addressed through the Cluster rather than through the networks their upstreams sit on, so the client keeps a single stable route however many environments, clouds and clusters are behind it. There are no remote subnets to advertise and no overlapping ranges to reconcile.
Read more - 05
Dual-stack without translation
The client uses a private IPv6 address by default and can be forced to IPv4-only or dual-stack, independently of what each upstream speaks, so there is no NAT64 or DNS64 to operate between them.
Read more - 06
Private DNS that configures itself
Every Service has a stable private FQDN assigned by the Cluster, resolved through a split DNS server the client sets up automatically using resolvectl on Linux and networksetup on macOS. Nothing has to be memorized or kept in sync as upstream addresses change.
Read more - 07
Serving, as well as consuming
The same client can serve resources to the Cluster with the --serve and --serve-all flags, so a laptop, a container or a pod in another cluster becomes a reachable upstream with no inbound port opened beside it.
Read more - 08
Authorization above the tunnel
Bringing the tunnel up grants nothing on its own. Every request is authorized against identity, device, session and the application-layer request itself, which is the part a WireGuard configuration cannot express.
Read more
A WireGuard configuration describes peers, keys and allowed addresses. None of those are identities, and none of them can express that a particular person may run one query on one database at one time of day.
The same platform capabilities ship with every deployment, whichever way you use it.
Frequently asked
- Is this real WireGuard?
- Yes. Client-based access runs over WireGuard, using the kernel implementation where it is available and an unprivileged userspace implementation elsewhere. A QUIC-based tunneling mode is supported alongside it. Everything above the transport, including identity, Policies, secretless access and auditing, is identical either way.
- Do clients need root privileges?
- Not necessarily. On Linux the client first tries the WireGuard kernel implementation, which needs root or the NET_ADMIN capability. Without those it falls back to a wireguard-go TUN device, and without permission to create a TUN device it runs an unprivileged userspace network stack over gVisor Netstack. In that last mode Services are reached by mapping them to the host, which is what makes the client work inside containers, CI runners and IoT devices.
- Do I have to manage peers and keys?
- No. There is no peer list to maintain, no key to distribute and no configuration file to hand out. A person runs octelium connect, authenticates through your identity provider, and the Cluster establishes the tunnel and assigns addressing and DNS. A Session can be revoked centrally, which ends access immediately.
- What about routes and split tunneling?
- Each Service is reached through a single stable route, so there are no remote subnets to advertise into a user's routing table and no overlapping ranges to reconcile. Because only Cluster traffic uses the tunnel, ordinary internet traffic is never pulled through a gateway to keep a connection usable, which is the usual reason full tunneling gets switched on.
- Can resources behind NAT be reached without opening a port?
- Yes. A Service upstream can be an address that is only reachable from the side of a connected client, which serves it to the Cluster over its own outbound tunnel using the --serve or --serve-all flags. That covers a laptop behind NAT, containers, Kubernetes pods in other clusters, private clouds and IoT devices, with no inbound port and no firewall change on that side.
- 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.
Related solutions
QUIC remote access VPN
The same zero-config tunnel over a QUIC transport, with the same identity, policy and auditing model above it.
Read moreBusiness VPN
A remote access platform for a whole team, with SSO, device posture, secretless access and application-layer auditing.
Read moreZero Trust Network Access
Octelium as a complete ZTNA and BeyondCorp platform for humans, workloads and AI agents on a single architecture.
Read moreDeploy Octelium on your own infrastructure in minutes
Free and open source. Self-hosted. No vendor lock-in.