The open source, self-hosted API gateway
Octelium is a free and open source, self-hosted zero trust access platform. Its HTTP and gRPC modes put an identity-aware proxy in front of your APIs: each request is authorized on its own method, path and body, the upstream credential stays in the Cluster, and plugins handle rate limiting, validation and manipulation.
- Free and open source
- Designed for self-hosting
- REST and gRPC
kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://api.internal:8443
http:
auth:
bearer:
fromSecret: api-keykind: Policy
metadata:
name: partners
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.http.method == "GET"
- match: ctx.request.http.path.startsWith("/v1/")
- match: '"partners" in ctx.user.spec.groups'kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://api.internal:8443
http:
plugins:
- name: minute-limit
condition:
matchAny: true
rateLimit:
limit: 120
window:
minutes: 1A unified secure access platform
An API gateway is one use of the same platform. 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
One architecture, wherever the upstream runs
Each API is represented by a Service, which is served by an identity-aware proxy that abstracts away the network details of the upstream behind it. Where that upstream runs is a detail of the Service definition.
- Published clientlessly, the Service is reached over HTTPS at its own public FQDN, by people in a browser and by applications over standard OAuth2 and bearer authentication.
- Upstreams can be private services behind NAT in any environment, protected public APIs, containers the Cluster deploys itself, or several endpoints load balanced together.
- The gRPC mode listens over HTTP/2 as the protocol requires and decodes requests, so gRPC APIs get the same authorization and auditing treatment as REST ones.
kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: http://10.0.6.40:8080kind: Service
metadata:
name: grpc-api
spec:
mode: GRPC
port: 8080
isPublic: true
config:
upstream:
url: https://grpc.internal:8443kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
container:
port: 8080
image: ghcr.io/acme/api:3.1.0
replicas: 4Layer-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 a token that either works or does not.
- HTTP context covers the method, path, headers, query parameters and the serialized JSON body, so a rule can bound a field in a request rather than allow an endpoint outright.
- gRPC context covers the package, service, method and full service name, alongside the underlying HTTP request that carried it.
- Validation runs alongside authorization. A JSON schema plugin rejects malformed bodies with a configurable status code and body before they reach the upstream.
kind: Policy
metadata:
name: bounded-writes
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.http.method in ["POST", "PUT"]
- match: ctx.request.http.path.startsWith("/v1/orders")
- match: ctx.request.http.bodyMap.amount < 5000kind: Policy
metadata:
name: grpc-read-only
spec:
rules:
- effect: ALLOW
condition:
all:
of:
- match: ctx.request.grpc.service == "MainService"
- match: ctx.request.grpc.method == "GetUser"
- match: '"partners" in ctx.user.spec.groups'kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://api.internal:8443
http:
plugins:
- name: validate-orders
condition:
match: ctx.request.http.path.startsWith("/v1/orders")
jsonSchema:
inline: <ORDER_JSON_SCHEMA>
statusCode: 400Upstream credentials that are never distributed
The credential a caller presents to the Cluster and the credential the Cluster presents upstream are entirely separate. Upstream credentials are stored as Secrets and injected once a request is authorized.
- Bearer tokens, API key headers, basic authentication, OAuth2 client credentials, AWS Signature Version 4 signing and mTLS client certificates are all supported for the upstream.
- Protected public APIs are covered as well as internal ones, so a third-party API can be exposed to your own applications without the key being copied into each of them.
- Which upstream and which credential are used can be selected per request, which is how API versions, tenants and staged rollouts sit behind a single URL.
kind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://api.internal:8443
http:
auth:
bearer:
fromSecret: api-keykind: Service
metadata:
name: partner-api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://partner.example.com
tls:
clientCertificate:
fromSecret: partner-client-certkind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://v1.internal:8443
http:
auth:
bearer:
fromSecret: v1-api-key
dynamicConfig:
configs:
- name: v2
upstream:
url: https://v2.internal:8443
http:
auth:
bearer:
fromSecret: v2-api-key
rules:
- condition:
match: '"beta" in ctx.user.spec.groups'
configName: v2A unified identity model for humans and workloads
Human and workload Users share the same identity management, authentication, access control and visibility model. The applications calling an API are first-class identities rather than holders of a shared key.
- Applications authenticate with the standard OAuth2 client credentials flow or access tokens, in any language and with no proprietary SDK, sent as Authorization: Bearer or X-Octelium-Auth.
- They can also authenticate secretlessly with federated OIDC assertions from GitHub Actions, cloud providers and Kubernetes clusters, so no long-lived credential has to be stored beside them.
- Lua and Envoy ExtProc plugins run before or after authorization, and a request body a plugin changes is parsed again so later stages act on the updated request.
- The MCP and LLM gateway modes apply the same architecture to the tools and model providers AI agents reach, with tool calls and inference requests authorized individually.
octeliumctl create cred \
--type oauth2 \
--user microservice1 \
api-cred
# The application then authenticates at
# https://<DOMAIN>/oauth2/token
# and sends the issued bearer access token.kind: IdentityProvider
metadata:
name: github-actions
spec:
oidcIdentityToken:
issuerURL: https://token.actions.githubusercontent.com
audience: https://example.comkind: Service
metadata:
name: api
spec:
mode: HTTP
isPublic: true
config:
upstream:
url: https://api.internal:8443
http:
plugins:
- name: enrich
condition:
matchAny: true
lua:
inline: |
function onRequest(ctx)
local b = octelium.req.getRequestBody()
octelium.req.setRequestBody(b)
endReal-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.
- Entries record the request path, method and response code, and for gRPC the package, service and method, attributed to the identity that made the call rather than to a shared key.
- 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.
- Managed containers deploy, scale and serve the API itself as the Service upstream, from public or private registries, with resource limits, volumes and health probes.
- The Cluster is managed declaratively. Services, Policies, Groups and Secrets are YAML in a Git repository, applied with a single octeliumctl apply that reproduces the entire Cluster state.
- Management is centralized over the Cluster's gRPC APIs, so publishing a new API or rotating an upstream credential can itself be automated.
$ octeliumctl apply ./cluster
Secret: api-key Updated
Secret: partner-client-cert Updated
IdentityProvider: github-actions Created
Policy: partners Created
Group: partners Created
Group: beta Updated
Service: api.apis Created
Service: grpc-api.apis Created
Service: partner-api.apis Created
Namespace: apis Created
Cluster Core resources successfully applied
7 resources created
3 resources updated
ClusterConfig updatedWhat an API gateway has to do, and what does each part
An API gateway is usually adopted for one reason and then asked to carry several others. These are the responsibilities that accumulate, next to the mechanism in an Octelium Cluster that handles each one.
- 01
Knowing who is calling
Every request carries an Octelium identity rather than a shared API key. Applications authenticate with the standard OAuth2 client credentials flow, access tokens or federated OIDC assertions, in any language and with no proprietary SDK.
Read more - 02
Deciding per request
Authorization runs on every request with CEL or Open Policy Agent, over the method, path, headers, query parameters and serialized JSON body, combined with identity, group membership and device attributes in the same expression.
Read more - 03
Holding the upstream credential
API keys, bearer tokens, basic authentication, OAuth2 client credentials, AWS SigV4 signing and mTLS client certificates are stored as Secrets and injected after a request is authorized, so callers never hold them.
Read more - 04
Routing to the right backend
Dynamic configuration selects the upstream, credential, headers, paths and plugins per request from identity and request context, which covers API versioning, tenant separation and staged rollouts on one URL.
Read more - 05
Reshaping the request
Request and response headers can be added, overridden, appended or removed, and path prefixes can be added, removed or replaced, without changing the upstream service.
Read more - 06
Protecting the upstream
Plugins provide sliding-window rate limiting backed by the Cluster's own store, JSON schema validation with a configurable failure response, response caching with a custom key, and direct responses that never reach the upstream at all.
Read more - 07
Running your own logic
Lua scripts and Envoy ExtProc servers run in the request path, before or after authorization, for enrichment, redaction, guardrails and intentional mutation of request and response bodies.
Read more - 08
Recording what happened
Each request produces an identity-aware AccessLog with the method, path, response code, gRPC package, service and method where applicable, streamed in real time over OpenTelemetry to your own log management and SIEM providers.
Read more
Proxying a request is the easy part. What makes a gateway worth operating is that the identity, the decision, the credential and the record all live in one declarative configuration rather than in four systems.
The same platform capabilities ship with every deployment, whichever way you use it.
Frequently asked
- How do applications authenticate?
- Through the standard OAuth2 client credentials flow against the Cluster's own token endpoint, or with an access token Credential used directly as a bearer token, sent in an Authorization: Bearer header or an X-Octelium-Auth header. Ordinary OAuth2 libraries in any language work without a proprietary SDK. Workloads can also authenticate secretlessly with federated OIDC assertions from the platform hosting them.
- What can a policy actually see?
- For HTTP, the method, path, headers, query parameters and the serialized JSON body through ctx.request.http.bodyMap. For gRPC, the package, service, method and full service name, alongside the underlying HTTP request. Those combine with identity, group membership, device posture, session type and time in the same CEL or Open Policy Agent expression, evaluated per request.
- Does it do rate limiting and caching?
- Yes, as plugins on the Service. Rate limiting is a global sliding window backed by the Cluster's Redis store, applied per Session by default with a custom key available through a CEL expression, and several limits can run together. Response caching takes a TTL and its own key expression. JSON schema validation and direct responses are plugins as well.
- Can one URL serve several API versions or accounts?
- Yes. Dynamic configuration selects the upstream, upstream credential, headers, paths and plugins per request from identity and request context, so a beta group can be routed to a newer backend with its own key while everyone else stays on the current one, under one Service and one set of Policies.
- Does it handle gRPC?
- Yes. The gRPC mode automatically listens over HTTP/2 as the protocol requires, and decodes requests so that the package, service and method are available for authorization and appear in the access logs alongside the underlying HTTP information.
- Can it host the API as well as front it?
- Yes. Managed containers deploy, scale and serve a container image as the Service upstream, on the Cluster's own data-plane nodes, with environment variables from Secrets, replica counts, resource limits, volumes and health probes. A Service can also load balance across several upstream endpoints.
Related solutions
AI gateway
An identity-aware gateway for OpenAI and Anthropic APIs, with per-request control over models, tools and token limits.
Read moreSelf-hosted PaaS
Deploy, scale and serve containerized applications that the Cluster itself runs, with or without public access.
Read moreZero trust SaaS and API access
Secretless access to protected public resources, so a team reaches a SaaS API without holding its key.
Read moreDeploy Octelium on your own infrastructure in minutes
Free and open source. Self-hosted. No vendor lock-in.