Kubernetes
Run TheoWorks on your own Kubernetes cluster with Helm. Tested on k3s v1.34 with Traefik. One Helm chart, two editions -- Free/Pro (the public chart) and Enterprise (the offline bundle or the registry credential, both from the download page).
On Red Hat OpenShift? Use the OpenShift guide -- it uses an OpenShift Route and OpenShift's built-in security policy instead of an Ingress. Red Hat OpenShift cluster? Use the OpenShift guide. Any other Kubernetes cluster? Use the Kubernetes guide.
Choose your path
| Your situation | What you'll use | |---|---| | Free or Pro | The public chart | | Enterprise, connected cluster | The registry credential | | Enterprise, air-gapped cluster | The offline bundle |
Prerequisites
- Kubernetes 1.24 or later (tested on 1.34) --
kubectland Helm 3.8+. - An Ingress controller and IngressClass.
- A default StorageClass.
- A namespace that allows Pod Security
restricted. - A TLS certificate plan -- see TLS below.
- Your trusted proxy range -- see Find your forwardedAllowIps.
- Reachability to your GitLab, plus an OAuth application registered on it (client ID, client secret, and redirect URI). Sign-in is always through your own GitLab.
- Free or Pro only: outbound HTTPS to
lm.theoworks.io. The public chart connects to the TheoWorks License Server by default, the same way the single-machine launcher does -- your plan activates the same way. Enterprise clusters use the offline license instead and need no such access. - Enterprise only: sign in at theoworks.io/download
to get the chart and image, your offline Enterprise license file, and
jqon the air-gapped workstation (to read the image digest).
An Ingress controller
kubectl get ingressclassUse its NAME as ingress.className. If exactly one class is marked default,
className may be left empty. The chart creates a standard
networking.k8s.io/v1 Ingress. Gateway-API-only clusters aren't covered
yet.
Storage
kubectl get storageclassOne entry should show (default). If none does, set both
persistence.*.storageClassName. The pod needs two ReadWriteOnce volumes
(index 2Gi, state 256Mi). Its security context uses fsGroup to make them
writable, so the storage driver must apply fsGroup. Tested with k3s's
local-path storage.
Pod Security
The pod is proven admitted under the restricted Pod Security profile.
The guide recommends labelling the namespace
pod-security.kubernetes.io/enforce=restricted (the Install
steps below do this). A looser profile (baseline, privileged, or no
label) installs unchanged -- keep the security context as written, don't
remove it. Pod Security has no level above restricted; if your cluster
adds a policy engine (for example Kyverno or Gatekeeper), give the platform
team this table:
| What the pod asks for | Value |
|---|---|
| Runs as | non-root, UID 10001, GID 0, fsGroup 0 |
| Root filesystem | read-only |
| Privilege escalation | not allowed |
| Capabilities | all dropped |
| Seccomp profile | RuntimeDefault |
| Volumes | two RWO volume claims, plus an in-memory /tmp |
| Host access | no host paths, no host network |
Other user or group IDs aren't tested yet.
Find your forwardedAllowIps
The app only trusts forwarded client addresses from this range, and the chart refuses to install without it.
-
Find the controller's pods and their IPs, filtered to the controller's namespace as shown by
kubectl get ingressclass:kubectl get pods -A -o wide -
Find the pod network that contains them:
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'The per-node ranges sit inside the cluster pod network -- for example, on k3s
10.42.0.0/24and10.42.1.0/24sit inside10.42.0.0/16.
If podCIDR is empty (as with some network plugins), ask your platform team
for the cluster's pod network range. If the controller runs on the host
network (its pod IP equals a node IP), use the node network range instead.
A comma-separated list is allowed; * is never accepted -- TheoWorks then
trusts no forwarded addresses at all. Tested default: k3s 10.42.0.0/16
-- confirm it on your cluster.
Get the chart and image
Free or Pro
The public chart pulls the public TheoWorks image anonymously — no registry credential, no image pull secret, no sign-in. Its OCI reference (public ECR) is on the download page — the site has the current version; this page's commands install without pinning a version so they always install the current release.
Enterprise, air-gapped cluster
At theoworks.io/download, the Air-gapped cluster card gives you Get the offline bundle: the chart archive, the image as a portable archive, checksums, and the signing key:
theoworks-enterprise-X.Y.Z.tgz
theoworks-app-enterprise-X.Y.Z.oci.tar
checksums.txt
cosign.pubDownload all four before the link window closes — the window only has to cover the start of each download; a download already in progress finishes.
Enterprise, connected cluster
At theoworks.io/download, the Connected cluster card gives you Get a registry credential: a registry host, a username, and a temporary password, shown once and copyable without revealing it.
Write your values.yaml
The complete file below is byte-identical to the Kubernetes template on the download page -- if you started there, this is the same file you already copied.
route:
enabled: false # plain Kubernetes uses an Ingress, not an OpenShift Route
ingress:
enabled: true
className: traefik # your IngressClass -- kubectl get ingressclass
host: theoworks.example.com # your external hostname
tlsStrategy: own-cert # own-cert | acme | none -- see the guide's TLS section
tlsSecretName: theoworks-tls # the TLS Secret holding your hostname's certificate
forwardedAllowIps: "10.42.0.0/16" # your ingress controller's pod network -- required
podSecurityContext: # Kubernetes doesn't assign these the way OpenShift does
runAsUser: 10001
runAsGroup: 0
fsGroup: 0
config:
gitlabInstance: "https://gitlab.example.com" # your GitLab URL
oauthRedirectUri: "https://theoworks.example.com/oauth/callback" # must match the GitLab OAuth app
maintainerEmail: "you@example.com" # optional -- their first sign-in becomes the maintainer, skipping first-run setup
secrets:
oauthClientId: "<your-gitlab-oauth-client-id>"
oauthClientSecret: "<your-gitlab-oauth-client-secret>"
sessionKey: "<32 random bytes, base64 -- e.g. `openssl rand -base64 32`>"Kubernetes settings
route.enabled: false-- plain Kubernetes has no Route object; the chart'sroute.*keys are OpenShift-only.ingress.*--enabled: trueturns on the chart'snetworking.k8s.io/v1Ingress.classNamenames your IngressClass (see An Ingress controller).hostis the external hostname users reach.forwardedAllowIps(top-level) -- the platform-neutral alias for the trusted proxy range (see Find your forwardedAllowIps).route.forwardedAllowIpswins over this key if both are set -- a Route-less install should leave the Route-named key unset.podSecurityContext-- pins the pod's UID/GID/fsGroup explicitly, since Kubernetes (unlike OpenShift'srestricted-v2) does not assign these automatically.
TLS
| Your situation | Set in ingress | Also do |
|---|---|---|
| You have a certificate for the hostname (e.g. from your corporate CA) -- recommended | tlsStrategy: own-cert, tlsSecretName: theoworks-tls | create the Secret during Install (its step is shown there) |
| cert-manager with a ClusterIssuer (the usual Let's Encrypt setup) | tlsStrategy: own-cert, tlsSecretName: theoworks-tls, annotations: { cert-manager.io/cluster-issuer: letsencrypt } | nothing -- cert-manager creates the Secret |
| cert-manager with an Issuer in this namespace | tlsStrategy: acme, certManagerIssuer: <issuer name> in values | ingress.host must be set |
| TLS ends before the cluster (a load balancer terminates it) | tlsStrategy: none | use https:// in oauthRedirectUri only if users reach the site over HTTPS |
The ClusterIssuer row above uses own-cert plus an annotation, not acme,
because the acme option currently supports only an Issuer in the same
namespace. This flips to an acme row once the chart accepts a
ClusterIssuer.
tlsStrategy accepts exactly own-cert, acme or none. OpenShift's
internal isn't available on Kubernetes. A misspelt value is currently not
rejected: the Ingress then serves your controller's default certificate.
The acme row's "must be set" is a hard requirement today with no chart
guard. The guard text changes once the chart enforces it.
GitLab connection details are never optional: config.gitlabInstance and
config.oauthRedirectUri must match the OAuth application exactly, and
secrets.oauthClientId/oauthClientSecret/sessionKey must all be set (or
provided via secrets.existingSecret) — the app refuses to boot without
them.
Storage and resources apply to every path too:
persistence:
index:
size: 2Gi # rebuildable search index
storageClassName: "" # "" = cluster default
state:
size: 256Mi # small usage state
storageClassName: ""
resources:
limits: { cpu: "2", memory: 2Gi }
requests: { cpu: "500m", memory: 1Gi }The pod sizes its internal work pools to the CPU limit you set here, so it behaves the same on a small node and a large one.
Enterprise additions
On top of the common values above, Enterprise sets the license -- and, only for an air-gapped cluster, the image location:
license:
enabled: true # the chart default
existingSecret: "theoworks-license" # recommended: a secret you manage
existingSecretKey: "license.json"
# or, for a first install, inline the envelope instead:
# content: '{"...": "..."}'The license is mounted as a file, so rotating it is a secret update — no pod restart.
Connected cluster: keep the chart's image settings. The Enterprise chart already names the released image and pins it by digest — never a tag. Add only the pull secret you create during Install:
image:
pullSecrets: ["theoworks-pull"] # your dockerconfigjson secret(s)Don't set image.registry, image.repository, image.digest or
image.tag for a connected cluster.
Air-gapped cluster: nothing to add here for the image. Install sets the
image's registry and digest from your registry and the bundle. If your
registry needs credentials to pull, add your own secret under
image.pullSecrets.
Pin the image by digest so every rollout runs an exact, verified image —
this is the ONE enterprise pin style; nowhere on this page does an enterprise
command set image.tag.
If your GitLab or license server presents a certificate from an internal or
corporate authority, add a caBundle block (see the chart's bundled
values.yaml for its keys) — left at its defaults, nothing extra is mounted.
Install
-
Create the namespace.
kubectl create namespace theoworks kubectl label namespace theoworks pod-security.kubernetes.io/enforce=restricted -
Switch to it (this is what
oc projectdoes on OpenShift -- no command below needs a namespace flag):kubectl config set-context --current --namespace=theoworks -
Set these once:
export THEOWORKS_VERSION=X.Y.Z # Enterprise -- the version you're installing (the connected-cluster card, or the bundle filenames you downloaded) export REGISTRY=your-registry.example.internal # Enterprise, air-gapped cluster only -- where you load and pull the image from -
Only if you chose "You have a certificate": create the TLS Secret (after the namespace switch, so it lands in the right namespace):
kubectl create secret tls theoworks-tls --cert=tls.crt --key=tls.key
Free or Pro
helm install theoworks oci://public.ecr.aws/d9m2o0n8/chart/theoworks \
-f values.yamlEnterprise, air-gapped cluster
Verify and load the image into your own registry first, then install from the local chart file:
sha256sum -c checksums.txt
mkdir -p theoworks-app-enterprise-$THEOWORKS_VERSION-oci
tar -xf theoworks-app-enterprise-$THEOWORKS_VERSION.oci.tar -C theoworks-app-enterprise-$THEOWORKS_VERSION-oci
cosign load --dir theoworks-app-enterprise-$THEOWORKS_VERSION-oci $REGISTRY/theoworks-app-enterprise
DIGEST=$(jq -r '.manifests[] | select(.annotations.kind == "dev.cosignproject.cosign/imageIndex") | .digest' theoworks-app-enterprise-$THEOWORKS_VERSION-oci/index.json)
cosign verify --key cosign.pub --insecure-ignore-tlog \
$REGISTRY/theoworks-app-enterprise@$DIGESTcosign load takes the image reference positionally (there is no
--registry flag); the digest to verify -- and to pin image.digest below
-- comes from the extracted OCI layout's index.json, never from anything
cosign load prints.
Then install:
helm install theoworks ./theoworks-enterprise-$THEOWORKS_VERSION.tgz \
--set image.registry=$REGISTRY \
--set image.digest=$DIGEST \
-f values.yamlEnterprise, connected cluster
Sign in to the registry first (the credential's password is meant for
helm registry login's interactive prompt — never a command-line flag, never
a file):
helm registry login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWSPaste the password when prompted, then create the image pull secret (the
kubelet needs its own -- helm registry login above only covers the
chart pull). The sequence below never puts the password on the command
line, into shell history, or into a file:
printf 'Paste the registry password, then press Enter: '
IFS= read -rs TW_PW; echo
TW_AUTH=$(printf 'AWS:%s' "$TW_PW" | base64 | tr -d '\n')
TW_CFG=$(printf '{"auths":{"%s":{"username":"AWS","password":"%s","auth":"%s"}}}' \
366258937776.dkr.ecr.eu-central-1.amazonaws.com "$TW_PW" "$TW_AUTH" | base64 | tr -d '\n')
printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"theoworks-pull"},"type":"kubernetes.io/dockerconfigjson","data":{".dockerconfigjson":"%s"}}' "$TW_CFG" \
| kubectl apply --server-side -f -
unset TW_PW TW_AUTH TW_CFGName it in your values with image.pullSecrets: ["theoworks-pull"] (already
shown above), then install:
helm install theoworks oci://366258937776.dkr.ecr.eu-central-1.amazonaws.com/charts/theoworks-enterprise \
--version "$THEOWORKS_VERSION" \
-f values.yamlEnd the registry session:
helm registry logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comA registry credential expires (at most 12 hours). Recommended: mirror the image into your own registry once (see Day-2) rather than depending on it for every future pull, drain, or scale-out.
Verify
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/instance=theoworks --timeout=10m
kubectl get ingressThe HOSTS column shows your hostname and ADDRESS is filled in. Then confirm the instance is healthy and reachable: open your hostname, sign in through your GitLab, open a document, edit it, and save -- the commit lands in your GitLab repository.
Helm's post-install message currently shows an oc command -- on Kubernetes
use the kubectl wait command above instead.
If something's wrong
| Symptom | Fix |
|---|---|
| Install stops with "forwardedAllowIps is REQUIRED" | Set forwardedAllowIps -- see Find your forwardedAllowIps |
| Install stops with "no matches for kind Route" — Helm's exact message: no matches for kind "Route" in version "route.openshift.io/v1" | You're using the OpenShift values. Set route.enabled: false and use the Kubernetes values file above |
| Your hostname returns the controller's "404 page not found" | The request's hostname doesn't match ingress.host. Check DNS and ingress.host |
License and usage
-
Pro: sign in as the maintainer and open Settings ▸ Usage & License. Paste the code from your purchase email into Redemption code, then select Activate Pro. The same page shows current usage against your plan's seats.
-
Enterprise: your license file is stored in a Kubernetes Secret: the one named in
license.existingSecret(keylicense.jsonby default). To apply a renewed license, update that Secret in place. You don't needhelm upgradeor a restart:kubectl create secret generic theoworks-license \ --from-file=license.json=license.json \ --dry-run=client -o yaml | kubectl apply -f -TheoWorks reads the license file every time it checks your license. So the new license takes effect once Kubernetes updates the mounted file, which can take a short while. To confirm, open Settings ▸ Usage & License: it shows Licensed · Enterprise while a valid license is in effect.
If you put the license inline with
license.contentinstead, replace it in your values file and runhelm upgrade(see Day-2 operations).
Day-2 operations
Both the CA bundle and the license are mounted as files -- rotate either by updating the underlying secret in place; the mounted file refreshes without a restart.
Free or Pro: the public chart already bakes the current release's image
tag, so a plain upgrade picks up the latest release -- you don't need to set
image.tag yourself (doing so overrides the chart's baked tag):
helm upgrade theoworks oci://public.ecr.aws/d9m2o0n8/chart/theoworks \
-f values.yamlEnterprise, connected cluster: the chart bakes the released image's digest
itself, so an upgrade never sets image.digest -- it's the same install
command from Install, run again with the new version.
Already running from your own registry? Use Upgrade a mirrored install instead.
First, get a fresh registry credential. The one from your install has expired (registry credentials last at most 12 hours). At theoworks.io/download, in the Connected cluster card, select Get a registry credential (or Get a new credential). Keep that page open: you'll paste its password below. Finish these steps before the time shown on the card.
helm registry login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWSRefresh the image pull secret so your cluster can pull the new version's image, with the same password-safe sequence Install used:
printf 'Paste the registry password, then press Enter: '
IFS= read -rs TW_PW; echo
TW_AUTH=$(printf 'AWS:%s' "$TW_PW" | base64 | tr -d '\n')
TW_CFG=$(printf '{"auths":{"%s":{"username":"AWS","password":"%s","auth":"%s"}}}' \
366258937776.dkr.ecr.eu-central-1.amazonaws.com "$TW_PW" "$TW_AUTH" | base64 | tr -d '\n')
printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"theoworks-pull"},"type":"kubernetes.io/dockerconfigjson","data":{".dockerconfigjson":"%s"}}' "$TW_CFG" \
| kubectl apply --server-side -f -
unset TW_PW TW_AUTH TW_CFGexport THEOWORKS_VERSION=X.Y.Z # the new release
helm upgrade theoworks oci://366258937776.dkr.ecr.eu-central-1.amazonaws.com/charts/theoworks-enterprise \
--version "$THEOWORKS_VERSION" \
-f values.yamlhelm registry logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comThe pull secret now holds today's credential, which stops working within 12 hours. Pods that are already running aren't affected. But if Kubernetes later moves the pod to a node that doesn't have the image yet, pulling the image fails. To stop depending on this credential, mirror the image into your own registry. After that, an upgrade only needs a fresh credential to fetch the new chart and copy the new image; your running deployment never does.
Enterprise, air-gapped cluster: download and verify the new bundle first
-- re-run the air-gapped verify-and-load sequence against it
(which reads the new $DIGEST from its index.json) -- then upgrade from the
new chart file with the new registry and digest:
export THEOWORKS_VERSION=X.Y.Z # the new release
helm upgrade theoworks ./theoworks-enterprise-$THEOWORKS_VERSION.tgz \
--set image.registry=$REGISTRY \
--set image.digest=$DIGEST \
-f values.yamlOn shutdown the pod stops accepting new traffic first and finishes in-flight edits and saves within its shutdown grace period. Because this baseline runs a single pod, plan an upgrade for a quiet period -- multi-pod, continuously-available upgrades are on the roadmap.
Mirror the image for a connected cluster
A registry credential is short-lived. If your cluster's pod may reschedule after the credential expires (a redeploy, a node drain), pull secrets created from it will fail the next image pull. Mirror the image into your own internal registry so the running deployment no longer depends on the credential.
First, get a fresh registry credential. The one from your install has expired (registry credentials last at most 12 hours). At theoworks.io/download, in the Connected cluster card, select Get a registry credential (or Get a new credential). Keep that page open: you'll paste its password below. Finish these steps before the time shown on the card.
Set these once:
export INTERNAL_REGISTRY=your-internal-registry.example.internal
export THEOWORKS_VERSION=X.Y.Z # the version you run now: the number after "theoworks-enterprise-" in `helm list`Sign in to copy the image:
skopeo login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWSIf your own registry needs a sign-in to push, run
skopeo login "$INTERNAL_REGISTRY" too.
Copy the image you run now into your registry. It is tagged with its version, and its digest stays exactly the same:
IMAGE_DIGEST=$(kubectl get pod -l app.kubernetes.io/instance=theoworks -o jsonpath='{.items[0].spec.containers[0].image}' | sed 's/.*@//')
skopeo copy --all --preserve-digests \
docker://366258937776.dkr.ecr.eu-central-1.amazonaws.com/theoworks-app-enterprise@$IMAGE_DIGEST \
docker://$INTERNAL_REGISTRY/theoworks-app-enterprise:$THEOWORKS_VERSION
skopeo inspect --raw docker://$INTERNAL_REGISTRY/theoworks-app-enterprise@$IMAGE_DIGEST > /dev/null && echo "Your registry serves the image by digest."
skopeo logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comCopy to a version tag: some registries, OpenShift's own among them, don't keep an image pushed without a tag. TheoWorks still pulls it by digest, and the last check confirms your registry serves it that way. If the check prints nothing, stop: your registry isn't serving the image yet.
Let your cluster sign in to your registry. If your cluster can pull from your registry without a sign-in, skip this step. If your platform team already gave you a pull secret for it in this namespace, skip it too, and use that secret's name below. Otherwise create one (you'll be asked for your registry's username and password):
TW_AUTHDIR=$(mktemp -d)
skopeo login --authfile "$TW_AUTHDIR/auth.json" "${INTERNAL_REGISTRY%%/*}"
kubectl create secret generic internal-pull \
--type=kubernetes.io/dockerconfigjson \
--from-file=.dockerconfigjson="$TW_AUTHDIR/auth.json" \
--dry-run=client -o yaml | kubectl apply --server-side -f -
rm -rf "$TW_AUTHDIR"; unset TW_AUTHDIRThis path is safe for any password: skopeo writes the sign-in itself. The
sign-in sits for a moment in a private temporary folder (mktemp -d,
readable only by you), and the last line deletes it.
Point the chart at your registry. In your values.yaml, under image:,
add registry: with your registry's address (the same value as
$INTERNAL_REGISTRY), and add your registry's pull secret to
image.pullSecrets next to theoworks-pull, for example
pullSecrets: ["theoworks-pull", "internal-pull"]. Skip the pull secret if
the previous step didn't apply. Don't change the digest; the chart keeps it.
Apply it. Sign in again to fetch the chart: Helm keeps its own sign-in.
Paste the same password, or get a new credential first if the time shown on
the card has passed. Use helm upgrade, not helm install, which fails on
an existing release.
helm registry login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWS
helm upgrade theoworks oci://366258937776.dkr.ecr.eu-central-1.amazonaws.com/charts/theoworks-enterprise \
--version "$THEOWORKS_VERSION" \
-f values.yaml
helm registry logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comOnce the pod runs from your registry, theoworks-pull is no longer used,
and it holds a credential that expires. At your next upgrade you can remove
it from image.pullSecrets. From now on, upgrade with
Upgrade a mirrored install (below), not the
connected-cluster upgrade above.
Upgrade a mirrored install
Once your cluster runs from your own registry, copy each new version's image there first, then upgrade. Only these steps need a TheoWorks sign-in; your running deployment never does.
First, get a fresh registry credential. The one from your install has expired (registry credentials last at most 12 hours). At theoworks.io/download, in the Connected cluster card, select Get a registry credential (or Get a new credential). Keep that page open: you'll paste its password below. Finish these steps before the time shown on the card.
Set these once, and sign in to fetch the new chart:
export THEOWORKS_VERSION=X.Y.Z # the new release
export INTERNAL_REGISTRY=your-internal-registry.example.internal
helm registry login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWSPaste the password when prompted.
Find the new version's image, read from the new chart, never from the running pod:
NEW_DIGEST=$(helm template theoworks oci://366258937776.dkr.ecr.eu-central-1.amazonaws.com/charts/theoworks-enterprise \
--version "$THEOWORKS_VERSION" -f values.yaml \
| grep -o 'theoworks-app-enterprise@sha256:[0-9a-f]*' | head -n 1 | cut -d@ -f2)
echo "New image digest: $NEW_DIGEST"Helm may also print its own Pulled: and Digest: lines for the chart;
ignore them. The line that matters is the one starting New image digest:.
If it shows nothing after the colon, stop and check the version number.
Copy it into your registry:
skopeo login 366258937776.dkr.ecr.eu-central-1.amazonaws.com --username AWS
skopeo copy --all --preserve-digests \
docker://366258937776.dkr.ecr.eu-central-1.amazonaws.com/theoworks-app-enterprise@$NEW_DIGEST \
docker://$INTERNAL_REGISTRY/theoworks-app-enterprise:$THEOWORKS_VERSION
skopeo inspect --raw docker://$INTERNAL_REGISTRY/theoworks-app-enterprise@$NEW_DIGEST > /dev/null && echo "Your registry serves the new image by digest."
skopeo logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comThis uses the same password. If your own registry needs a sign-in to push,
run skopeo login "$INTERNAL_REGISTRY" too. If the check prints nothing,
stop before upgrading.
Upgrade:
helm upgrade theoworks oci://366258937776.dkr.ecr.eu-central-1.amazonaws.com/charts/theoworks-enterprise \
--version "$THEOWORKS_VERSION" \
-f values.yaml
helm registry logout 366258937776.dkr.ecr.eu-central-1.amazonaws.comYour values.yaml already points at your registry and its pull secret, so the new pod pulls the new image from there.
Reference
| Setting | What it does | Default |
|---|---|---|
| ingress.enabled | Turn on the plain-Kubernetes Ingress | false |
| ingress.className | Your cluster's IngressClass | "" |
| ingress.host | External hostname | "" |
| ingress.tlsStrategy | own-cert, acme, or none | none |
| ingress.tlsSecretName | The TLS Secret holding your certificate | "" |
| forwardedAllowIps | Ingress source CIDR (required); route.forwardedAllowIps wins if both are set | "" |
| podSecurityContext.runAsUser / .runAsGroup / .fsGroup | Pod identity Kubernetes doesn't assign automatically | 10001 / 0 / 0 |
| persistence.index.size / persistence.state.size | Volume sizes | 2Gi / 256Mi |
| image.registry / image.repository | Where the image comes from | (enterprise defaults; Free/Pro overrides) |
| image.tag | Override to pin an exact Free/Pro build | (chart default is the current release -- optional, not required) |
| image.digest | Exact image for Enterprise (pin by digest) | (required for Enterprise) |
| image.pullSecrets | Registry pull secret name(s); none needed for Free/Pro | [] |
| license.enabled | Mount an offline license (true Enterprise; false Free/Pro) | true |
| config.gitlabInstance / oauthRedirectUri | Your GitLab URL and OAuth redirect | (none) |
| config.maintainerEmail | Optional -- first sign-in from this address becomes the maintainer | "" |
| secrets.oauthClientId / oauthClientSecret / sessionKey | GitLab OAuth app credentials + session key | (none) |
| license.existingSecret / content | Your offline license (Enterprise) | (none) |
| resources.limits | CPU / memory ceiling | cpu: 2, memory: 2Gi |
See the chart's bundled values.yaml and values-kubernetes.yaml for every
setting and inline guidance.
Next steps
- OpenShift guide -- Red Hat OpenShift clusters.
- Self-hosting -- the single-machine launcher path.
- Install guide -- every way to run TheoWorks.