Edge standalone / container
Run the edge directly with systemd, or as a container / Kubernetes sidecar — the setup where it's easiest to make the edge the connection-terminating hop.
Running the edge close to where browser traffic lands keeps the connection-level timing signal strongest, because there are fewer hops between the browser and the edge.
Serve HTTPS at the edge
In this setup the edge is the front door for the Octet path, so let it terminate the browser's TLS directly — that keeps it the connection-terminating hop with no proxy in between. Point it at a certificate for your Octet hostname (e.g. octet.yourapp.com) and listen on 443:
| Variable | Value |
|---|---|
EDGE_TLS_CERT_FILE | Path to the certificate chain (e.g. Let's Encrypt fullchain.pem). |
EDGE_TLS_KEY_FILE | Path to the matching private key (e.g. privkey.pem). |
PORT | 443 |
Provision the certificate however you already do (Let's Encrypt / certbot, your platform's cert manager, or a cert your ops team issues), and make sure the service user can read both files. With both set the edge serves HTTPS; with them unset it serves plain HTTP — only safe behind a front you've confirmed preserves the browser connection. The examples below use this direct-TLS setup.
systemd
Keep secrets in an environment file (mode 600), not in the unit:
PORT=443
OCTET_URL=https://<your-octet-api-url>
LICENSE=<your-license-key>
# Terminate the browser's TLS at the edge (keeps it the connection-terminating hop):
EDGE_TLS_CERT_FILE=/etc/letsencrypt/live/octet.yourapp.com/fullchain.pem
EDGE_TLS_KEY_FILE=/etc/letsencrypt/live/octet.yourapp.com/privkey.pem
# Mutual TLS to Octet is planned hardening — optional and inert until Octet provisions certs:
# OCTET_CA_FILE=/etc/octet/octet-ca.pem
# EDGE_CLIENT_CERT_FILE=/etc/octet/edge.crt
# EDGE_CLIENT_KEY_FILE=/etc/octet/edge.key
[Unit]
Description=Octet edge (harvester + connector)
After=network.target
[Service]
ExecStart=/usr/local/bin/octet-edge-linux-amd64
EnvironmentFile=/etc/octet/edge.env
Restart=on-failure
User=octet
DynamicUser=no
# Let the non-root service user bind the privileged port 443:
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
The octet user must also be able to read the certificate and key — Let's Encrypt files under /etc/letsencrypt/live are root-only by default, so grant read access (e.g. an ACL or a group) or copy them somewhere the user can read.
sudo systemctl enable --now octet-edge
curl -s https://octet.yourapp.com/health # {"ok":true,...}
Docker
The binary is static, so a minimal base image is enough:
FROM gcr.io/distroless/static-debian12
COPY octet-edge-linux-amd64 /octet-edge
ENTRYPOINT ["/octet-edge"]
docker run -d --name octet-edge -p 443:443 \
-e PORT=443 \
-e OCTET_URL=https://<your-octet-api-url> \
-e LICENSE=<your-license-key> \
-e EDGE_TLS_CERT_FILE=/certs/fullchain.pem \
-e EDGE_TLS_KEY_FILE=/certs/privkey.pem \
-v /etc/letsencrypt/live/octet.yourapp.com:/certs:ro \
octet-edge:latest
# To serve plain HTTP behind a connection-preserving front instead, drop the two
# EDGE_TLS_* vars and the cert mount, and map -p 8080:8080 with PORT=8080.
# Mutual TLS to Octet is planned hardening; when Octet provisions certs, also add:
# -e OCTET_CA_FILE=/etc/octet/octet-ca.pem \
# -e EDGE_CLIENT_CERT_FILE=/etc/octet/edge.crt \
# -e EDGE_CLIENT_KEY_FILE=/etc/octet/edge.key \
# -v /etc/octet:/etc/octet:ro
Kubernetes sidecar
Run the edge as a sidecar container in the pod that fronts browser traffic, mounting the credentials from a Secret:
containers:
- name: octet-edge
image: your-registry/octet-edge:latest
ports:
- containerPort: 8080
env:
- name: OCTET_URL
value: https://<your-octet-api-url>
envFrom:
- secretRef:
name: octet-edge-secrets # LICENSE (and the planned mutual-TLS cert paths, when enabled)
# Mount the mutual-TLS certs only once Octet provisions them (planned hardening):
volumeMounts:
- name: octet-certs
mountPath: /etc/octet
readOnly: true
Route the Octet path prefix (or a dedicated hostname) to the sidecar's port 8080, and make sure the source IP reaches it.
If your cluster's Ingress terminates TLS and forwards a fresh connection to the sidecar, the Ingress becomes the connection-terminating hop and the timing signal reflects it, not the browser. To keep the edge the terminating hop, either use TLS passthrough at the Ingress (route the raw connection to the sidecar) or have the sidecar serve TLS itself (mount the cert/key, set EDGE_TLS_CERT_FILE / EDGE_TLS_KEY_FILE, and expose 443). See Cloud LB / CDN.
Where to go next
- Deploy the Edge. Env vars and the termination rule.
- Edge Configuration. Full reference.