ManagementGuideService ExamplesHTTP-based Applications
Deploy and Secure Access to Next.js/Vite App

Octelium enables you to seamlessly easily deploy, scale and secure access as well as public anonymous access to your Next.js/Vite.js/Astro web containerized/dockerized applications, effectively making Octelium operate as a PaaS-like deployment platform. Octelium simply provides the following:

  • A scalable infrastructure to provide clientless deployment and access to all your containerized/dockerized applications that can be hosted by public container registries or even private registries that require authentication (read more about managed containers here).
  • 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).
  • 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 (read more here).
  • 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).

In this guide, we're going to assume that your web app is built as a Docker image that is served by a private container registry (e.g. ghcr.io). We first need to obtain the user and password/token needed to authenticate to the private container registry. For example, the GitHub container registry (i.e. ghcr.io), you can read more here.

Now we store the obtained token as a Secret as follows:

octeliumctl create secret reg-password

Now we create the Service for our web application as follows:

1
kind: Service
2
metadata:
3
name: dashboard
4
spec:
5
mode: WEB
6
isPublic: true
7
config:
8
upstream:
9
container:
10
port: 3000
11
image: ghcr.io/<ORG>/<IMAGE>:<TAG>
12
command:
13
- npm
14
args:
15
- run
16
- start
17
replicas: 3
18
credentials:
19
usernamePassword:
20
username: <USERNAME>
21
password:
22
fromSecret: reg-password
23
resourceLimit:
24
cpu:
25
millicores: 2000
26
memory:
27
megabytes: 4000
28
env:
29
- name: KEY1
30
value: VALUE1
31
- name: KEY2
32
value: VALUE2
33
securityContext:
34
runAsUser: 1000

You can now apply the Service as follows (read more here):

octeliumctl apply /PATH/TO/SERVICE.YAML

Now you can access the Service publicly via the client-less/BeyondCorp using your browser at the address https://dashboard.<DOMAIN>. You can read more about publicly exposed BeyondCorp Services here.

And to provide public anonymous access, you only need to enable the isAnonymous field as follows:

1
kind: Service
2
metadata:
3
name: dashboard
4
spec:
5
mode: WEB
6
isPublic: true
7
isAnonymous: true
8
config:
9
# The rest of your config

You can also dynamically route to multiple containers (e.g. multiple container image versions) based on identity or/and context (read more about dynamic configuration here). Here is an example:

1
kind: Service
2
metadata:
3
name: my-web-app
4
spec:
5
mode: WEB
6
dynamicConfig:
7
configs:
8
- name: c1
9
upstream:
10
container:
11
port: 80
12
image: ghcr.io/org/image:v1
13
- name: c2
14
upstream:
15
container:
16
port: 80
17
image: ghcr.io/org/image:v2
18
rules:
19
- condition:
20
match: ctx.request.http.path.startsWith("/v1")
21
configName: c1
22
- condition:
23
match: ctx.request.http.path.startsWith("/v2")
24
configName: c2

When it comes to access control, Octelium 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 a generic example:

1
kind: Service
2
metadata:
3
name: my-nginx
4
spec:
5
mode: HTTP
6
config:
7
upstream:
8
container:
9
image: nginx
10
port: 80
11
replicas: 3
12
authorization:
13
inlinePolicies:
14
- spec:
15
rules:
16
- effect: ALLOW
17
condition:
18
all:
19
of:
20
- match: ctx.user.spec.groups.hasAll("dev", "ops")
21
- match: ctx.request.http.method in ["POST", "PUT"]
22
- match: ctx.request.http.path.startsWith("/users")
23
- match: ctx.request.http.headers["x-custom-header"] == "this-value"
24
# bodyMap contains the serialized JSON body content
25
- match: ctx.request.http.bodyMap.age > 18 && ctx.request.http.bodyMap.email.endsWith("@example.com")

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