ngrok alternative

The open source, self-hosted alternative to ngrok

Octelium is a free and open source, self-hosted zero trust access platform. A service running on your machine is served to the Cluster over an outbound tunnel and published at a stable URL on your own domain, either openly or behind your identity provider, with policy, rate limiting and auditing in front of it.

  • Free and open source
  • Your own domain
  • No inbound ports
service.yaml
A local service, publishedThe upstream address is resolved from the side of a connected host, so no port is opened.
A local service, published. The upstream address is resolved from the side of a connected host, so no port is opened.
kind: Service
metadata:
  name: dev
spec:
  mode: HTTP
  isPublic: true
  config:
    upstream:
      url: http://localhost:3000
      user: laptop
Open to the internet. Anonymous access removes authentication, which is what a webhook receiver usually needs.
kind: Service
metadata:
  name: hooks
spec:
  mode: HTTP
  isPublic: true
  isAnonymous: true
  config:
    upstream:
      url: http://localhost:3000
      user: laptop
Or behind your team. Without the anonymous flag, the same Service requires an identity and a Policy.
kind: Policy
metadata:
  name: team
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.user.spec.type == "HUMAN"
            - match: '"team" in ctx.user.spec.groups'
service-remote.yaml
From a laptop or a containerA connected client serves the upstream over its own outbound tunnel, with no inbound port.
From a laptop or a container. A connected client serves the upstream over its own outbound tunnel, with no inbound port.
kind: Service
metadata:
  name: dev
spec:
  mode: HTTP
  isPublic: true
  config:
    upstream:
      url: http://localhost:3000
      user: laptop
Not only HTTP. Generic TCP and UDP are covered, alongside SSH, databases, Kubernetes and DNS.
kind: Service
metadata:
  name: local-pg
spec:
  mode: POSTGRES
  port: 5432
  config:
    upstream:
      url: postgres://localhost:5432
      user: laptop
Hosted by the Cluster itself. There does not have to be a laptop involved. The Cluster can deploy and serve the app.
kind: Service
metadata:
  name: preview
spec:
  mode: WEB
  isPublic: true
  config:
    upstream:
      container:
        port: 3000
        image: ghcr.io/acme/web:pr-482
policy-http.yaml
The request itselfMethod, path, headers and serialized JSON body are all part of the request context.
The request itself. Method, path, headers and serialized JSON body are all part of the request context.
kind: Policy
metadata:
  name: webhook-only
spec:
  rules:
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.request.http.method == "POST"
            - match: ctx.request.http.path == "/hooks/github"
Public, but not unconditional. Anonymous authorization keeps a Service public while still filtering on the request.
kind: Service
metadata:
  name: hooks
spec:
  mode: HTTP
  isPublic: true
  isAnonymous: true
  config:
    upstream:
      url: http://localhost:3000
      user: laptop
  authorization:
    enableAnonymous: true
    inlinePolicies:
      - spec:
          rules:
            - effect: ALLOW
              condition:
                match: ctx.request.http.method == "POST"
Rate limiting. A sliding-window rate limit is a plugin on the Service, keyed per Session by default.
kind: Service
metadata:
  name: hooks
spec:
  mode: HTTP
  isPublic: true
  config:
    upstream:
      url: http://localhost:3000
      user: laptop
    http:
      plugins:
        - name: minute-limit
          condition:
            matchAny: true
          rateLimit:
            limit: 60
            window:
              minutes: 1
http-auth.yaml
An upstream API keyThe application behind the tunnel keeps its own credential, and nobody downstream receives it.
An upstream API key. The application behind the tunnel keeps its own credential, and nobody downstream receives it.
kind: Service
metadata:
  name: api
spec:
  mode: HTTP
  isPublic: true
  config:
    upstream:
      url: http://localhost:8080
      user: laptop
    http:
      auth:
        bearer:
          fromSecret: api-key
A local database. A database on your own machine is reached without its password leaving the Cluster.
kind: Service
metadata:
  name: local-pg
spec:
  mode: POSTGRES
  port: 5432
  config:
    upstream:
      url: postgres://localhost:5432
      user: laptop
    postgres:
      user: app
      database: app
      auth:
        password:
          fromSecret: pg-password
A private registry. Deployed containers pull from private registries using credentials held as Cluster Secrets.
kind: Service
metadata:
  name: preview
spec:
  mode: WEB
  isPublic: true
  config:
    upstream:
      container:
        port: 3000
        image: ghcr.io/acme/web:pr-482
        credentials:
          usernamePassword:
            username: ghcr-user
            password:
              fromSecret: ghcr-token
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. The machine serving a resource is itself a User, with its own Session and audit trail.
kind: User
metadata:
  name: laptop
spec:
  type: WORKLOAD
  groups:
    - serving
An MCP gateway. An MCP server on a laptop can be published the same way, with tool calls authorized individually.
kind: Service
metadata:
  name: tools-mcp
spec:
  mode: MCP
  isPublic: true
  config:
    upstream:
      url: http://localhost:8080
      user: laptop
    mcp:
      endpoint: /mcp
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
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: ghcr-token Updated
Secret: pg-password Updated
IdentityProvider: github Updated
Policy: team Created
Group: team Created
Group: serving Updated
Service: dev Created
Service: hooks Created
Service: preview Created
User: laptop Created
Cluster Core resources successfully applied
 7 resources created
 3 resources updated

 ClusterConfig updated
Comparison

Octelium and ngrok, capability by capability

Both products are described from the same structured capability dataset used across this site, with the same evidentiary standard applied to each. Emerging and experimental features are marked as partial regardless of vendor.

Capability comparison

Dataset reviewed August 2026

A curated view of the dataset, including the rows where Octelium is stronger, the rows where it is not, and the rows where the two are equivalent. The complete capability matrix, with search and filters, is one click away.

Architecture

Architecture

Octelium
Kubernetes-native identity-aware proxy/gateway architecture in which policy evaluation is separated from enforcement, with client-based WireGuard/QUIC access, clientless BeyondCorp access, declarative resources, and self-hosted control/data planes.
ngrok
Cloud-hosted reverse proxy/gateway with agents connecting private services to ngrok's edge. Endpoint and Traffic Policy model for routing, inspection, and traffic actions.

Authentication

OpenID Connect

Octelium
Yes
ngrok
Yes

SAML 2.0

Octelium
Yes
ngrok
Yes

Native FIDO2 / Passkey

Native means implemented by the platform itself, not merely delegated to an external IdP.

Octelium
NativeFIDO2/Passkey/WebAuthnN with attestation and hardware-resistant authenticator checks
ngrok
No

Workload Identity

Octelium
OIDC assertions / workload identity
ngrok
No

Anonymous / Public Access

Octelium
Yes
ngrok
Public endpoints supported

Authorization & Policy

Policy-as-Code

Octelium
CEL + OPA
ngrok
Traffic Policy

Per-Request Authz

For L7 products, this means each HTTP/gRPC/API/K8s request can be evaluated. For overlays, session/connection policy is not counted as per-request. This modeling choice structurally favors L7 gateways over network overlays.

Octelium
Yes
ngrok
HTTP/endpoint policy

L7-Aware Policies

Octelium
HTTP, gRPC, K8s, DB, SSH, mTLS-related context
ngrok
HTTP/API traffic policy

Device Posture

Octelium
TPM/FIDO2/device attributes
ngrok
No

L7 Protocol Awareness & Secretless Access

HTTP / HTTPS

Octelium
L7-aware + secretless credential injection
ngrok
L7 gateway

gRPC

Octelium
Native L7 mode
ngrok
Partial

SSH

Octelium
Secretless / embedded SSH patterns
ngrok
No

PostgreSQL

Octelium
Secretless + query-aware policy/logging
ngrok
No

MySQL

Octelium
Secretless + query-aware policy/logging
ngrok
No

Kubernetes

Octelium
Secretless + verb/resource/namespace policy
ngrok
K8s operator/exposure; not K8s semantic authz gateway

Raw TCP / UDP

Octelium
TCP and UDP
ngrok
TCP endpoints; UDP not a core general VPN capability

HTTP Manipulation

Octelium
With native plugins including Lua, Envoy ExtProc, JSON schema validation, cache, rate limits
ngrok
Traffic Policy actions

Transport & Networking

WireGuard Data Plane

Whether the product's own client/data plane is built on WireGuard, versus a proprietary or TLS-based transport.

Octelium
Kernel / userspaceWireGuard via kernel module, TUN, or unprivileged userspace (wireguard-go) implementations.
ngrok
No

NAT Traversal

Octelium
Via GatewaysReaches resources behind NAT through Cluster Gateways; client-to-Gateway path rather than a direct P2P mesh.
ngrok
PartialEdge-relayed through ngrok's network, not P2P.

Visibility, Auditing & Observability

OpenTelemetry-Native

Octelium
Yes
ngrok
No

L7-Aware Access Logs

Octelium
HTTP/gRPC/K8s/DB/SSH identity-aware logs
ngrok
Inspection/replay/logs

SSH Session Recording

Octelium
Yes
ngrok
No

Access Methods

Client-Based VPN / Overlay

Octelium
WireGuard / QUIC
ngrok
No

Clientless Browser Access

Octelium
Yes
ngrok
Public/protected web endpoints

Private DNS

Octelium
Yes
ngrok
No

Dynamic Configuration

GitOps / Declarative Config

Octelium
Kubernetes-like resources / YAML
ngrok
YAML/Terraform/K8s

AI / MCP / Agent Compatibility

AI / LLM Gateway

Octelium
Native LLM Service modeProtocol-aware OpenAI/Anthropic gateway: validated operations, per-request authorization on model, tools and token limits, CEL-based model selection, and token usage in access logs.
ngrok
AI gateway positioning

MCP Gateway / MCP Access

Octelium
Native MCP Service modeProtocol-aware MCP gateway: JSON-RPC method and tool-level authorization, protocol version pinning, origin validation, and managed-container MCP upstreams.
ngrok
Partial

Deploy Containers / PaaS

Octelium
Yes
ngrok
No

Gateway Capabilities

API Gateway

Octelium
Rate limit, cache, schema validation, Lua, ExtProc
ngrok
Native gateway / traffic policy

Kubernetes Ingress / Gateway

Octelium
Yes
ngrok
K8s operator / gateway patterns

Reverse Proxy / Tunneling

Octelium
Yes
ngrok
Yes

Scalability & Cloud-Nativeness

Auto Horizontal Scaling

Octelium
PEP/PDP can scale independently
ngrok
SaaS edge

High Availability

Octelium
K8s-native HA model
ngrok
SaaS edge

Openness & Self-Hosting

Fully Self-Hosted

Octelium
Yes
ngrok
No

Server Code Open Source

Octelium
Yes
ngrok
No

No Mandatory Proprietary Cloud

Octelium
Yes
ngrok
No

Data Sovereignty

Octelium
Yes
ngrok
No
Questions

Frequently asked

How does a local service get published without opening a port?
A Service upstream can be an address that is only reachable from the side of a connected client. That client, running octelium connect with the --serve or --serve-all flag, announces that it is willing to serve the Service, and the Cluster forwards requests to it over the client's own outbound tunnel. Nothing inbound is opened on the machine or its network.
Do I get my own domain and a stable URL?
Yes. A published Service is reached at its own public FQDN under the domain your Cluster was installed with, and the public DNS record and TLS certificate for it are managed by the Cluster. The URL is part of the Service definition rather than something assigned per session, so it does not change when a tunnel is restarted.
Can something be published without any authentication?
Yes. Anonymous public access switches off authentication and authorization for a Service, which is what a webhook receiver or a public demo usually needs. Anonymous authorization can then still be enabled, so the Service filters on path, method, headers, query parameters and body content while remaining publicly reachable, and rate limiting is available as a plugin.
Is it only for HTTP?
No. Alongside HTTP, WEB and gRPC, a Service can run in SSH, PostgreSQL, MySQL, Kubernetes, DNS, SOCKS5, browser-based RDP, MCP and LLM modes, or in generic TCP and UDP mode for anything else. The application-layer modes add per-request authorization, secretless upstream credentials and protocol-aware auditing on top of the tunnel.
What does it take to run the Cluster?
The quick installer provisions a complete single-node Cluster, including Kubernetes itself, on one fresh Linux VM with 2 vCPUs, 2 GB of RAM and a domain you own. That is enough for development and personal use. Larger deployments run on scalable managed or on-premise Kubernetes installations.
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.