ManagementGuideService ExamplesHTTP-based Applications
Octelium as a Self-Hosted ngrok Alternative

Octelium can very easily operate as a scalable self-hosted, free and open source alternative to ngrok, Cloudflare Tunnel and similar tunneling-based remote access commercial products. When used as a gateway to your HTTP-based applications, Octelium provides the following:

  • A scalable infrastructure to provide clientless access to any HTTP-based resource behind NAT from anywhere (e.g. private clouds, your own laptop, IoT, etc...).
  • Secure clientless BeyondCorp access for human Users via Octelium's OpenID Connect and SAML 2.0 IdentityProviders (read more here) as well as for your workload Users via OAuth2 client credentials (read more here) and bearer access tokens (read more here)..
  • Anonymous public access to your websites, APIs and webhooks (read more here).
  • Deploy and scale your containerized applications as Octelium Services (read more about managed containers here)
  • Dynamic identity-based, context-aware, L7 aware, on a per-request basis, centralized access control via policy-as-code with CEL and OPA (read more about Policies and access control here).
  • Dynamic L7-aware routing to upstreams and advanced request/response header and body manipulation.
  • OpenTelemetry-native, identity-based, L7 aware visibility and auditing.
  • Zero-config private client-based access from anywhere by humans as well as workloads via the octelium clients and containers (read more about connecting to Clusters here).
  • GitOps-friendly declarative, programmable management (read more here).

Let's assume in this guide that the User, john, wants to share some HTTP-based resource (e.g. web app, API, etc...) running on his laptop. Let's first create the User john in a YAML file as follows:

1
kind: User
2
metadata:
3
name: john
4
spec:
5
type: HUMAN

Now we assume the the resource to be served from john's machine is listening to the address localhost:8080. We simply create the Service for our internal resource with the name svc1 in separate services.yaml file as follows:

1
kind: Service
2
metadata:
3
name: svc1
4
spec:
5
mode: HTTP
6
isPublic: true
7
isAnonymous: true
8
config:
9
upstream:
10
url: http://localhost:8080
11
user: john

You can now apply the creation of both the User and Service as follows (read more about using octeliumctl apply here):

export OCTELIUM_DOMAIN=<DOMAIN>
octeliumctl apply /PATH/TO/YAML_FILE_OR_PARENT_DIRECTORY

Now for john to actually serve the Service svc1 from his side, john needs to connect to the Cluster via the octelium connect CLI command and adds the --serve flag as follows:

export OCTELIUM_DOMAIN=<DOMAIN>
octelium connect --serve svc1

You can also serve multiple Services simultaneously as follows:

octelium connect --serve svc1 --serve svc2

Also you can also serve all Services assigned to be served by the User via the --serve-all flag as follows:

octelium connect --serve-all
NOTE

You can have several octelium clients serving the same Service upstream. In such case, the Service will load balance among all the upstreams served by all the available connected octelium clients. For example, you might use this to serve an upstream from a deployment in remote Kubernetes cluster that runs multiple replicas octelium containers or when you want to have a Service whose upstreams can be running in several clouds/servers. In fact you can even have a single Service that has multiple upstreams served by multiple User (read more here).

You are not restricted to serving upstreams from just remote private networks, you can also deploy your containers and serve them as Octelium Services (read more about managed containers here). Here is an example:

1
kind: Service
2
metadata:
3
name: anonymous-nginx
4
spec:
5
mode: WEB
6
isPublic: true
7
isAnonymous: true
8
config:
9
upstream:
10
container:
11
image: nginx
12
port: 80

You can also deploy your Docker images stored in private container registries (see a more detailed example here). Here is an example:

1
kind: Service
2
metadata:
3
name: my-webapp
4
spec:
5
mode: WEB
6
isPublic: true
7
isAnonymous: true
8
config:
9
upstream:
10
container:
11
port: 3000
12
image: ghcr.io/<ORG>/<IMAGE>:<TAG>
13
command:
14
- npm
15
args:
16
- run
17
- start
18
replicas: 3
19
credentials:
20
usernamePassword:
21
username: <USERNAME>
22
password:
23
fromSecret: registry-password

Back to our initial example, the above Service configuration, namely the isAnonymous field, allows access for anonymous access over the internet. This could be useful for hosting and testing public websites, APIs, webhooks, etc.... However, you might want to only restrict the Service access to the Cluster's Users. You can do so by removing the isAnonymous field and adding Policies for who is allowed to access the Service (read more about Policies and access control here). Here is an example:

1
kind: Service
2
metadata:
3
name: svc1
4
spec:
5
mode: HTTP
6
isPublic: true
7
config:
8
upstream:
9
url: http://localhost:8080
10
user: john
11
authorization:
12
policies: ["allow-all"]

The above configuration allows access only for any authenticated User. However, you might want to control access in a more fine-grained way and not just allow access to all Users. Octelium actually provides a rich layer-7 aware, identity-based, context-aware ABAC access control on a per-request basis where you can control access based on the HTTP request's path, method, and even serialized JSON body content using policy-as-code with CEL and Open Policy Agent (OPA) (You can read more in detail about Policies and access control here). Here is another more detailed example:

1
kind: Service
2
metadata:
3
name: svc1
4
spec:
5
mode: HTTP
6
isPublic: true
7
config:
8
upstream:
9
url: http://localhost:8080
10
user: john
11
authorization:
12
inlinePolicies:
13
- spec:
14
rules:
15
- effect: ALLOW
16
condition:
17
all:
18
of:
19
- match: ctx.user.spec.email.endsWith("@example.com")
20
- match: ctx.request.http.path.startsWith("/prefix1")
21
- match: ctx.request.http.method in ["GET", "POST"]

Now authorized Users, once authenticated for example by Github OAuth2, OpenID Connect or SAML IdentityProviders such as Okta or Azure AD/Microsoft Entra ID (read more here), can access the Service svc1 either via the client-based private mode via the octelium connect command (read more here) as follows:

export OCTELIUM_DOMAIN=<DOMAIN>
# Now connect to the Cluster via the detached mode
octelium connect -d
# OR
sudo -E octelium connect
curl http://svc1:8080

Authorized Users can also access the Service via the clientless (i.e. BeyondCorp) mode (read more here). For example, if the Service is a web app, HUMAN Users (read more about User management here) can simply access the Service via their browsers at the public URL https://svc1.<DOMAIN>. Authorized WORKLOAD Users can also access the Service in a clientless way via standard OAuth2 client credential flow (read more here) or even directly via bearer access tokens (read more here).

Octelium also provides OpenTelemetry-ready, application-layer L7 aware visibility and access logging in real time (see an example for HTTP here). You can read more about visibility here.

This was a very short guide to show you how to use Octelium to deploy, scale, route and provide secure access as well as anonymous public access to any webapp containers. Here are a few more related features that you might be interested in:

  • Routing not just by request paths, but also by header keys and values, request body content including JSON (read more here).
  • Request/response header manipulation (read more here).
  • Cross-Origin Resource Sharing (CORS) (read more here).
  • gRPC mode (read more here).
  • Secretless access to upstreams and injecting bearer, basic, or custom authentication header credentials (read more here).
  • Application layer-aware ABAC access control via policy-as-code using CEL and Open Policy Agent (read more here).
  • OpenTelemetry-ready, application-layer L7 aware auditing and visibility (read more here).
© 2025 octelium.comOctelium Labs, LLCAll rights reserved
Octelium and Octelium logo are trademarks of Octelium Labs, LLC.
WireGuard is a registered trademark of Jason A. Donenfeld