Install on Kubernetes (Helm)
The controller is a single HTTPS service. Everything — the REST API, the web console, and the SSH / Kubernetes / database / RDP proxies — travels over that one port as WebSocket traffic, so the ingress only has to forward HTTPS with WebSocket support. The official Helm chart wraps all of this and is secure by default.
Requirements
Section titled “Requirements”- Kubernetes 1.25+.
- An external PostgreSQL 16+ database (managed service or operator — the chart does not run one).
- An ingress controller: ingress-nginx, Traefik v3, or a Gateway API implementation
(with the
v1alpha3BackendTLSPolicyCRD). - cert-manager (recommended) to issue the public TLS certificate.
- Paid plans only: your per-organization license token from the
Tessera portal. Community needs no license — omit the
TESSERA_LICENSEkey from the secret below.
The controller image is pulled from Tessera’s public registry, so no image pull secret is needed.
1. Create the secrets
Section titled “1. Create the secrets”The chart never creates secrets — you provide them. Create the main secret and a stable SSH host key.
kubectl create namespace tessera
# Encryption/JWT keys, database URL, and your licensekubectl create secret generic tessera-controller-secrets -n tessera \ --from-literal=TESSERA_ENC_KEY="$(openssl rand -hex 32)" \ --from-literal=TESSERA_JWT_SECRET="$(openssl rand -hex 32)" \ --from-literal=TESSERA_DATABASE_URL="postgres://tessera:PASSWORD@pg-host:5432/tessera?sslmode=require" \ --from-literal=TESSERA_LICENSE="<license token>"
# Stable SSH proxy host key — generate ONCE and keep itssh-keygen -t ed25519 -N '' -f ssh_host_ed25519_keykubectl create secret generic tessera-hostkey -n tessera \ --from-file=ssh_host_ed25519_keyThe SSH host key must stay the same across upgrades — clients pin it (trust-on-first-use). Generate it once and keep the secret.
2. TLS
Section titled “2. TLS”The controller always serves HTTPS. The recommended setup terminates the public certificate at the ingress (from cert-manager) and re-encrypts to the controller — traffic is never plaintext inside the cluster.
By default the controller uses a self-signed backend certificate and the ingress skips backend
verification. For fully verified re-encrypt (and required for Gateway API), issue a stable
backend certificate and pass it as backendTLS.existingSecret (tls.crt / tls.key /
ca.crt).
3. Install
Section titled “3. Install”Pull the chart from the registry (OCI) and install with a values file for your ingress. CI stamps
the published chart version to the release at package time, and the chart defaults to the matching
controller image (tagged v<version>) for that release.
helm install tessera \oci://registry.tessera.company/charts/tessera-controller \--version 1.0.0 \-n tessera -f values.yamlA minimal values.yaml for ingress-nginx:
secret: existingSecret: tessera-controller-secretshostKey: existingSecret: tessera-hostkey
config: publicUrl: https://controller.example.com
ingress: type: nginx # nginx | traefik | gateway host: controller.example.com className: nginx tls: secretName: tessera-edge-tls # cert-manager-managed certManager: clusterIssuer: letsencrypt-prod
networkPolicy: enabled: true ingressControllerNamespace: ingress-nginx ingressControllerPodLabels: app.kubernetes.io/name: ingress-nginx postgres: cidr: 10.0.0.5/32 egress: targetCIDRs: - 10.0.0.0/16 # networks of the servers you connect to (never 0.0.0.0/0)For Traefik, set ingress.type: traefik (renders an IngressRoute + ServersTransport);
for Gateway API, set ingress.type: gateway and point ingress.gateway.name at your
Gateway (renders an HTTPRoute + BackendTLSPolicy, which requires backendTLS). The chart
ships example overlays (values-nginx.yaml, values-traefik.yaml, values-gateway.yaml).
4. Verify
Section titled “4. Verify”kubectl -n tessera rollout status deploy/tessera-tessera-controllerhelm test tessera -n tessera # curls /healthz through the serviceThen open https://controller.example.com. On a fresh database the controller bootstraps a
default administrator — sign in as admin / admin and change the password immediately.
Then follow the initial setup walkthrough.
Security defaults
Section titled “Security defaults”The chart is hardened out of the box — it passes the Kubernetes restricted Pod Security Standard:
- Runs non-root (uid 65532), read-only root filesystem, all Linux capabilities dropped,
seccomp: RuntimeDefault, no privilege escalation. - No ServiceAccount token is mounted and the ServiceAccount has zero RBAC — a compromised pod cannot reach the Kubernetes API.
- A deny-by-default NetworkPolicy is on: only the ingress controller can reach the port, and egress is an allowlist (DNS, PostgreSQL, your target networks, and 443 for OIDC/portal).
- The Service is ClusterIP — reachable only through the ingress — and traffic is TLS end to end.
The published chart is cosign-signed with the same key as the image; verify it with
cosign verify --key <tessera pubkey> registry.tessera.company/charts/tessera-controller:<version>.
Upgrading
Section titled “Upgrading”helm upgrade tessera \ oci://registry.tessera.company/charts/tessera-controller \ --version <new-version> -n tessera -f values.yamlBecause it is a single replica with a Recreate rollout, the pod restarts and active sessions
drop — schedule upgrades in a maintenance window (see
Backups & upgrades). The database schema migrates automatically
on startup.
See Configuration for the full list of settings and Licensing & activation for how the license is applied.
We would like to count visits with Google Analytics, which needs a cookie. Nothing is loaded and nothing is stored unless you accept. What this sets.