TSG deployment guide
This guide covers deploying the TNO Security Gateway to Kubernetes with the TSG CLI. For a first managed deployment, start with Getting started. The configuration reference documents every input field.
Prerequisites
Client tools
Helm is not used.
npm install -g @tsg-dsp/cli@latest
Cluster
- A Kubernetes version supported by the selected CloudNativePG release. CloudNativePG 1.30 supports Kubernetes 1.34–1.36; check its support matrix before choosing versions. Size capacity for the actual stacks and workers you deploy.
- CloudNativePG 1.30 or newer, for the
DatabaseRoleCRD each component's database login depends on. - An Ingress controller, or the Gateway API CRDs plus a controller.
- cert-manager, if the TLS Secrets the rendered routes reference should be issued automatically.
tsg deploy checks the CRDs required by the rendered bundle and checks operator
versions when it can read them. It rejects missing CRDs and known unsupported
operator versions. It does not verify the Kubernetes version, cert-manager,
ingress controller availability, DNS or TLS issuance. Check these separately.
These are cluster-admin concerns; TSG never installs or removes them.
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm upgrade --install cnpg cnpg/cloudnative-pg \
--namespace cnpg-system --create-namespace
Public HTTPS endpoints are required for DID document resolution, even for a single-cluster deployment.
Managed services and organizations
Start from participant.yaml. The file now describes the managed SSO Bridge, Wallet, Control Plane and Tenant Management services. ecosystem.yaml is the same supported starting topology. Neither file creates organizations from participant seeds. Create or import organizations through the manager after the services are reachable.
Set the namespace, public host, authority details and stable administrator UUID.
Declare managedTenancy, components.controlPlane.enabled: true and
components.tenantManagement: {} explicitly. Wallet and SSO Bridge remain the
established mandatory stack components. The CLI does not add a manager to an
old deployment automatically.
Point DNS at the chosen ingress or gateway address. Provision the referenced Secrets through your normal secret delivery process. For a demo:
tsg secrets generate participant.yaml --context <context> --apply
tsg diff participant.yaml --context <context>
tsg deploy participant.yaml --context <context>
tsg status participant.yaml --context <context>
Secret generation leaves existing Secrets untouched. Preserve the runtime
SESSION_SECRET and TENANCY_SECRET values across deployments. With
private_key_jwt, generate the manager's key pair before rendering:
tsg keys generate hosted tenant-management
Commit its public JWK and deliver the private JWK through the referenced Secret.
The generated URLs for the example's path routing are SSO at
https://hosted.example.com/, Wallet at /wallet/, Control Plane at
/control-plane/ and Tenant Management at /tenant-management/. These are
configuration examples; verify DNS, TLS and real endpoint responses after deployment.
Use the manager to create or import an organization and inspect its canonical ID, service bindings and lifecycle status. See manager operations for existing data. No database reset or tenant import happens during CLI render, migrate or deploy.
Workers require pre-provisioned canonical owners, scoped OAuth credentials and Control Plane registrations. The CLI will reject missing identities and will never invent a tenant UUID or signaling credential. Follow the explicit HTTP multi-tenant or analytics provisioning procedure before adding a worker. Starter can be added as a managed browser client with explicitly configured canonical tenant choices. An empty choice list is valid and creates no tenants.
For old seeded files, first run tsg migrate, then complete the
managed runtime migration. Frozen v1alpha1 schema acceptance
does not preserve removed seed execution semantics.
Continuous deployment
tsg render does not contact a cluster or the network. The same inputs and CLI
version produce the same bytes, so you can commit and review the manifests:
tsg render participant.yaml -o gitops/tsg
Argo CD or Flux then owns apply and prune. Do not use tsg deploy against the
same resources. Pin spec.images.<component>.digest for a committed bundle so
its image references do not change with the CLI version.
The continuous deployment guide has working Flux and Argo CD examples. It also explains ordering, Secret delivery, controller tracking, and the prune settings needed to protect database resources.
Outside a controller-managed deployment, you can apply a bundle rendered earlier without reinterpreting the configuration:
tsg apply gitops/tsg
Ongoing operations
Updating
Change the configuration and rerun tsg diff, then tsg deploy. A full
deployment also reconciles removed stacks and retains their data.
Deploying part of a file
tsg deploy ecosystem.yaml -s hosted
A stack-selected run never reconciles, because the stacks it did not render are
unselected rather than absent. Add --include-infra when the shared
infrastructure set also needs to be applied.
Uninstalling
tsg uninstall participant.yaml # retains databases and volumes
tsg uninstall participant.yaml --delete-data # destroys them
Uninstall works from the inventory recorded in the cluster, not from the configuration file, so it removes what was actually deployed.
Gateway API (Envoy Gateway)
The CLI can expose the applications through the Gateway API instead of an
Ingress. This is opt-in. You can enable both while moving traffic one host at
a time.
routing:
ingress:
enabled: false
gateway:
enabled: true
className: eg
clusterIssuer: letsencrypt
Prerequisites:
- The Gateway API CRDs and a controller. The default class is Envoy Gateway
(
eg). - cert-manager started with
--enable-gateway-api, so it issues certificates forGatewaylisteners as it does for ingresses. - The
egGatewayClasscreated withmergeGateways: true.
The mergeGateways setting is easy to miss. TSG renders one Gateway per
distinct host, so without it every host gets its own Envoy proxy fleet and its
own cloud load balancer. An Ingress controller typically serves every host
through one. In a live cluster test, four Gateway objects produced four
separate external IPs before mergeGateways was applied.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: merged-proxy-config
namespace: envoy-gateway-system
spec:
mergeGateways: true
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: merged-proxy-config
namespace: envoy-gateway-system
With mergeGateways: true every Gateway under the eg class shares one Envoy
fleet and one external IP, routed by TLS SNI. See
Deployment Mode
for the constraint this relies on: the (port, protocol, hostname) tuple must
be unique across merged listeners, which holds here because each Gateway uses
a distinct host.
If you point DNS at the merged IP, reserve it as a static cloud address first.
Envoy Gateway creates a Service with a dynamic address, which may change if
Kubernetes recreates the Service.
You do not have to choose an owner within a stack. TSG renders the Gateway on
the first component of each host and attaches the rest as HTTPRoutes.
Changing what is rendered
The typed configuration covers replicas, resources, nodeSelector, ingress
class, and annotations. For other Kubernetes fields, add a patch. The CLI
applies it after rendering and before apply:
patches:
- target:
kind: Deployment
allowMultiple: true
merge:
spec:
template:
spec:
imagePullSecrets:
- name: registry-credentials
See Patches for targets, operations and ordering.
Related documentation
- Dataset configuration describes how to advertise an offer.
- CLI reference lists every command.
- Configuration reference documents every field.
- Architecture explains how the components fit together.
For the previous Helm-generating CLI format, follow the manual CLI migration guide. tsg migrate does not convert that format.