Platform

Deployment

Trellaris ships as one Helm chart with three tiers, and a cloud environment is created by one script. This page covers what an environment is made of, how to bring one up, and how it grows. The shape is the same on any cloud with managed Kubernetes and managed data services; the repository's reference environment implements it with infrastructure as code under infra/iac/.

Deployment view

The components of a production environment, by role. Names, ids and hostnames are deliberately not listed here; they live in the environment's own outputs and in its secret store.

EDGE DNS (public zone) Managed nginx ingress · Let's Encrypt TLS Logs · metrics · traces (any OTLP backend) MANAGED KUBERNETES · system + sandbox pools · workload identity · KEDA Workloads (Helm release) api · worker · beat · web · docs migrations Job · demo-seed Job cert-manager · Secrets Store CSI driver Secrets synced from the secret store at pod start Sandbox: one hardened Pod per run (deny-all network policy) Add-ons and identity Ingress controller (nginx) writes DNS records Secrets Store CSI provider, rotation every 2 min Container logs and metrics → the logging backend Workload identity: pods read secrets + write objects Deployer identity: GitHub OIDC, main branch only PRIVATE ENDPOINTS · NO PUBLIC ACCESS Managed relational DB with vector search automated backups, point-in-time restore Managed distributed cache Celery broker, run event streams, buckets single endpoint, no eviction, TLS Object storage artifacts, bundles, uploads, recordings identity-only access, versioning, soft delete SUPPORTING SERVICES Secret store Container Registry Model provider (chat + embeddings) Google OAuth · GitHub OAuth (sign-in)
Every data-plane hop stays inside the private network; the only public surfaces are the ingress and DNS.
RoleComponentSize in the reference environmentScale path (in place)
ComputeManaged KubernetesA system pool of 2 to 4 memory-optimised nodes (2 vCPU / 16 GB each, three zones) and a tainted sandbox pool of 1 to 2 nodes running Kata VM isolation, where only sandbox pods land; overlay networking with Cilium, workload identity, KEDARaise the node caps; add a user pool and taint the system pool
Ingress + TLSManaged nginx ingress controller, cert-manager, Let's EncryptOne public IP; certificates issued and renewed automaticallyA WAF-capable gateway in front; a global edge or CDN
DatabaseManaged relational DBBurstable 2 vCPU, 32 GB, 7-day point-in-time restore, vector-search extensionA general-purpose tier, zone-redundant standby, 35-day retention
Broker, streams, cachesManaged distributed cacheSmallest tier, single-endpoint clustering, no eviction, hourly snapshots, TLSNext tier; persistence unchanged
Object storageObject storageLocally redundant, versioning, 30-day soft delete, key-based access disabled (identity only)Zone- or geo-redundant replication
SecretsSecret store + Secrets Store CSI driverRBAC, purge protection, private endpoint; every platform secret and provider keyNone needed
ImagesContainer registryBasic tier, admin user off; api, web and docs images built in the registry on every deployPrivate link, geo-replication, content trust
ModelsModel provider (an existing account)A routed chat deployment and a large embedding model asked for 1536 dimensions, plus a second provider for failoverProvisioned throughput on the default tier
ObservabilityThe cloud's logs and metrics service30-day retentionOpenTelemetry collector for GenAI spans; managed Grafana
DNSPublic DNS zoneDelegated from the registrar; records written by the ingress controller—
IdentityTwo workload identitiesWorkload (pods: read secrets, write objects) and deployer (GitHub OIDC, main branch only)—
NetworkPrivate network, private endpoints, private DNS zonesThe database, the cache, object storage and the secret store reachable only inside the networkAn egress firewall for enumerable egress; a private API server
What is deliberately not there yet No WAF gateway or egress firewall, no Keycloak (social sign-in serves the demo; enterprise SSO is the first addition when an organisation needs an IdP alias), Each is an addition, not a rebuild.

Bring an environment up

One script does everything a person must do once. After it, every merge to main deploys on its own. The script in the repository targets one cloud; a port to another is the same seven steps with that cloud's template and CLI, and the chart does not change.

Once per environment, by someone who owns the cloud subscription or project

infra/iac/bootstrap.sh staging --location <region> --no-openai
  1. Preflight

    Checks the CLIs and sign-ins, enables every cloud service the template uses, compiles the template.
  2. Secrets

    Generates the platform secrets once into a gitignored file and reuses them on every later run. Collects the OAuth client for sign-in and the model provider keys from that same file.
  3. Infrastructure

    Creates the environment's resource container and runs the infrastructure template: network, cluster, database, cache, storage, secret store, registry, DNS zone, identities. Writes every secret into the secret store, assembling the connection strings from the servers it just created.
  4. Cluster

    Fetches credentials, installs cert-manager and the Let's Encrypt issuer.
  5. GitHub

    Creates the environment with its variables and secrets, restricted to the main branch.
  6. First deploy

    Starts the deploy workflow: images are built in the registry, the chart is installed, readiness is checked inside the cluster.
  7. DNS

    Prints the four nameservers to set at the registrar. Certificates issue as soon as the delegation propagates.

Your input is exactly: signing in, an OAuth client id and secret for Google or GitHub sign-in, a contact email for certificates, and the nameserver change at the registrar.

Every deploy after that

A merged pull request is a push to main, and that is the only trigger. The workflow signs in to the cloud with a short-lived OIDC token (no stored cloud credential), builds the three images in the registry, upgrades the Helm release with the environment's variables rendered into a values file, rolls the workloads once more if the synced secrets changed, and checks readiness from inside the cluster. A manual run from any other branch is skipped, and the environment's branch policy would withhold its secrets anyway.

Configuration that lives outside the chart

WhatWhere it livesHow it reaches the pods
Platform secrets (JWT signing, envelope-encryption root, BFF exchange), database and cache URLs, provider keys, sign-in client secrets, connector client secretsThe secret storeTwo SecretProviderClass objects sync them into two Kubernetes Secrets: one for the API side, one for the web tier, so the web pods never hold database credentials
Model routing (provider, tier ids, base URL, failover candidates, embedding model and dimensions), sign-in client ids, connector client idsGitHub environment variablesRendered by the workflow into a values file (JSON survives; --set would split it on commas)
Hostnames, replicas, resource requests, feature switches (demo org, landing org for new sign-ins)The chart's cloud values fileHelm

Other tiers

The same chart installs a starter tier with in-cluster an in-cluster database, cache and object store for kind or a small pilot, a team tier pointed at managed services with a TLS ingress, and an enterprise tier with autoscaling, split worker queues, OpenTelemetry export and secrets from an external manager. The compose stacks in infra/ remain the development loop.