From 248dffb17081dbd368938d1776e1274164dfc12a Mon Sep 17 00:00:00 2001 From: danc094codetogether Date: Tue, 28 Apr 2026 11:21:15 -0600 Subject: [PATCH 1/5] Bump Intel version to 1.3.5 (#209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: separate SSL certificates (#101) * fix: Set environment variables via .env file. (#99) * Set environment variables via .env file. * Missing change * Change how hostnames and secret are set. * changes for env template * add env variable resolver on sso redirect value * fix: add env_file to codetogether-intel (#105) * fix: missing CT_HQ_BASE_URL env var (#107) * feat: nginx auto config (#109) * fix: add step for sso provider (#110) * fix: add client_max_body_size to intel (#112) * fix: tweak name of dhparam.pem env var (#113) * tweak name of dhparam.pem env var * fix env var name in nginx template * fix pam to pem * fix: missing env file on collab (#114) * fix: handle nil ai.openai.api_key to prevent template er… (#116) * fix(intel-chart): handle nil ai.openai.api_key to prevent template errors Adjusted the Helm chart template for ai-secrets to avoid referencing ai.openai.api_key and ai.external.api_key when undefined. This fixes a fatal error during `helm template` when AI mode is set to `bundled` and no OpenAI config is present. Ensures compatibility with bundled-only deployments. * Changes to fix workflow issues * fix: cleanup for sso tenants (#117) * feat(intel): add option to disable AI integration entirely (#120) Previously, the Helm chart required either 'bundled' or 'external' AI mode to be configured, making it mandatory to include AI integration. This commit introduces a new flag `ai.enabled` to allow disabling AI features entirely, enabling Intel to be deployed without any AI-related containers or resources. * Change gen ai image name on values file (#122) * fix: bump up version number (#123) * docs: remove outdated metrics section from README (#130) - Removed the section referring to metrics(prometeus), etc from the README Co-authored-by: engineering * fix: add note to env-template file (#127) * fix: update LLM image URL to hub.edge (#132) * docs: add deprecation notice to old Live chart (#131) * 126 automatically configure ollama integration when llm is enabled (#128) * Make sidecar AI container resource block optional in deployment - Updated deployment.yaml to include the `resources` block for the `codetogether-llm` sidecar only if values are defined in values.yaml. - Ensures the bundled AI container can run without specifying resource limits/requests by default. - Improved overall Helm template flexibility for embedded AI mode. - Validated that runs with AI Container embeeded. * Enable support for external AI provider - Updated deployment.yaml to support both bundled and external AI modes, allowing selection via .Values.ai.mode. - Added manifests for external AI integration: - ai-config ConfigMap: defines external provider and URL. - ai-external-secret Secret: stores the external API key. - Verified that external AI mode works by routing requests through the configured external service. * feat: automate creation of external AI ConfigMap and Secret from values.yaml - Added Helm templates to generate ai-config ConfigMap and ai-external-secret Secret automatically when AI external mode is enabled. - ConfigMap values (ai_provider, ai_url) and Secret value (api-key) are now configurable via values.yaml. - Ensured resources are only created when ai.enabled=true and ai.mode=external. * feat: allow use of existing or Helm-managed ai-external-secret in deployment - Updated deployment.yaml to support referencing a user-provided Secret for AI external API key, with fallback to Helm-managed creation. - Added ai-external-secret.yaml template to optionally create the secret from values if not provided. * Fixing helm template validations * Adding values configuration --------- Co-authored-by: engineering * Gen AI Changes (#124) * Change resources of ai * Include gen ai on docker compose. * undo changes * Fix collab helm chart to allow usage of locator. (#134) * fix: invalid values in AI values section (#137) * fix: support automatic configuration of the LLM integration if AI is enabled (#138) * Fixes after Testing (#139) * Fixes after Testing - Refactored deployment.yaml to reference ai.externalSecret.name when create: false - Corrected CT_HQ_OLLAMA_AI_API_KEY key to apiKey to match Secret’s stringData - Updated ai-external-secret.yaml to generate a Secret only when create: true * Bump intel chart version to 1.2.5 * Fix to user http://codetogether-llm:8000/ always --------- Co-authored-by: engineering * Changes to use localhost always to avoid dns issues (#142) Co-authored-by: engineering * feat: support for optional keycloak deployment (#145) * initial config * Docker compose example to run keycloak --------- Co-authored-by: Ignacio Moreno * 144 keycloak (#146) * initial config * Docker compose example to run keycloak * Undo properties file change * fixes on properties file --------- Co-authored-by: Wojciech Galanciak * 144 keycloak (#147) * initial config * Docker compose example to run keycloak * Undo properties file change * fixes on properties file --------- Co-authored-by: Wojciech Galanciak * 144 keycloak (#149) * fixes on properties file * Prepare examples for deployment with keycloak. * move files * feat(charts, compose): add CT_TRUST_ALL_CERTS support (#158) * feat(charts, compose): add CT_TRUST_ALL_CERTS support Fixes: #157 - values.yaml: introduce `java.trustAllCerts` (default false) to toggle CT_TRUST_ALL_CERTS - deployment.yaml: inject `CT_TRUST_ALL_CERTS=true` into container env when `trustAllCerts` is enabled - .env-template: add `CT_TRUST_ALL_CERTS` entry for Docker Compose - compose.yml: reference `${CT_TRUST_ALL_CERTS}` in codetogether‑intel service * refactor(charts): move trustAllCerts under codetogether section - values.yaml: remove java.trustAllCerts; add codetogether.trustAllCerts (default false) - deployment.yaml: guard CT_TRUST_ALL_CERTS injection on .Values.codetogether.trustAllCerts * fix(compose): remove redundant CT_TRUST_ALL_CERTS env entry - Drop explicit `CT_TRUST_ALL_CERTS` from the `environment` section in the `codetogether-intel` service - Rely on `env_file: .env` to inject the variable --------- Co-authored-by: engineering * feat(chart): guard `ai-secrets` template behind `ai.enabled` (#161) Fixes: #160 Wrap the `ai-secrets` Secret manifest with a `.Values.ai.enabled` conditional so it is not rendered when AI is disabled. This prevents clashes with pre-existing `ai-secrets` owned by other releases and keeps templates clean. * fix: improve keycloak compose health check (#162) * fix(helm/intel): scope AI resources per-release to avoid cross-release Secret conflicts (#164) Fixes: #163 Problem - Deploying multiple `codetogether-intel` releases in the same namespace caused a collision on statically named resources (e.g., `ai-secrets` / `ai-config`), producing Helm ownership errors. What changed - templates/ai-config.yaml - Create ConfigMap only when `ai.enabled=true` and `ai.mode=external`. - Name is now release-scoped: `{{ .Release.Name }}-ai-config`. - templates/ai-external-secret.yaml - Respect `ai.externalSecret.create` and `ai.externalSecret.name`. - Default Secret name is release-scoped: `{{ include "codetogether.fullname" . }}-ai-external-secret`. - Store API key under `stringData.apiKey`. - templates/deployment.yaml - Read `AI_PROVIDER` / `AI_EXTERNAL_URL` from `{{ .Release.Name }}-ai-config`. - Read `AI_EXTERNAL_API_KEY` from the default or user-specified Secret: `{{ default (printf "%s-ai-external-secret" (include "codetogether.fullname" .)) .Values.ai.externalSecret.name }}`. - Bundled mode unchanged; external resources are not created in bundled mode. Why - Ensures two or more releases (e.g., `qa-intel` and `demo-staging-intel`) can coexist in the same namespace without Helm ownership clashes. How to test - External (chart-managed Secret): `helm template demo-staging-intel ./charts/intel -n default \ --set ai.enabled=true --set ai.mode=external \ --set ai.provider=openai --set ai.url=https://api.openai.com \ --set ai.externalSecret.create=true --set ai.externalSecret.apiKey=TESTKEY` → renders `demo-staging-intel-ai-config` and `demo-staging-intel-ai-external-secret`. - External (existing Secret): `kubectl create secret generic my-custom-ai-secret -n default \ --from-literal=apiKey=TESTKEY` `helm template qa-intel ./charts/intel -n default \ --set ai.enabled=true --set ai.mode=external \ --set ai.provider=openai --set ai.url=https://api.openai.com \ --set ai.externalSecret.create=false --set ai.externalSecret.name=my-custom-ai-secret` → renders only the release-scoped ConfigMap; Deployment references the existing Secret. - Bundled: `helm template demo ./charts/intel -n default --set ai.enabled=true --set ai.mode=bundled` → no AI ConfigMap/Secret rendered; sidecar included. * chore(keycloak): switch to KC_BOOTSTRAP_* admin vars and update compose/templates (#166) Fixes: #165 - Replace deprecated KEYCLOAK_ADMIN / KEYCLOAK_ADMIN_PASSWORD with KC_BOOTSTRAP_ADMIN_USERNAME / KC_BOOTSTRAP_ADMIN_PASSWORD. - Update compose files to pass new env vars to the Keycloak container. - Refresh .env templates to reflect the new names. - Remove references to deprecated vars. Touched: - compose/.env-with-keycloak-template - compose/keycloak/.env-template - compose/keycloak/compose-keycloak.yaml - compose/keycloak/compose-keycloak-no-nginx.yaml Why: eliminates KC-SERVICES0110 warnings and ensures deterministic, persistent admin on first bootstrap. BREAKING CHANGE: set KC_BOOTSTRAP_ADMIN_USERNAME and KC_BOOTSTRAP_ADMIN_PASSWORD instead of KEYCLOAK_ADMIN*. * feat(helm): add RO rootfs support for Intel and Collab (#169) * feat(helm): add RO rootfs support for Intel and Collab Fixes: #168 - tmpfs emptyDir for /run and /tmp - RW runtime at /run/volatile, reuse for /var/log/nginx and /var/cache/nginx - Intel: initContainer to create subpaths - enable via securityContext (readOnlyRootFileSystem, runAsUser=0) * Typo fixes * Typo fixes * Fixing typo * Changes to defauts * Fixes * feat(helm-collab): Support optional existing secret for Intel connection (#171) Fixes: #170 - add values: intelsecret.enabled/ref - conditionally render templates/secret-intel.yaml - deployment envs read from external secret when enabled(fail if ref missing) - default unchanged (chart still creates "release"-intel) * collab, intel: align read-only handling with live legacy chart (#175) * collab, intel: align read-only handling with live legacy chart Fixes: #174 - Gate all tmp/runtime mounts behind securityContext.readOnlyRootFileSystem - When RO=true, mount emptyDir to /run, /tmp, /var/log/nginx, /var/cache/nginx - Remove readOnlyMode flag and prepare-ro initContainer * Fixes * Bump version from 1.2.5 to 1.2.6 * Bump version to 1.2.3 in Chart.yaml * Fix indentation in deployment.yaml * Remove initContainers for readOnlyMode Removed initContainers configuration for read-only mode. * Bump version from 1.2.6 to 1.2.7 * Bump version from 1.2.3 to 1.2.4 * 177 collab intel rofs on open shift avoid run as user 0 support fs group (#178) * OpenShit Teting Commit * Intel Changes * Fixes * Fixes * Fix * feat(charts): OpenShift compatibility + read-only rootfs support for collab & intel Fixes: #177 This change makes the codetogether-collab and codetogether-intel charts work out-of-the-box on both vanilla Kubernetes and OpenShift (restricted-v2 SCC), and adds first-class support for readOnlyRootFilesystem via init containers. Key changes ----------- Collab - Add initContainer `prepare-volatile` to create writable runtime paths when readOnlyRootFilesystem=true (e.g., /run, /var/log/nginx, /var/cache/nginx, and the existing /run/volatile/* tree). - Conditionally handle OpenShift vs vanilla: - OpenShift: do NOT set runAsUser/runAsGroup/fsGroup; let SCC assign UIDs. Keep runAsNonRoot and disallow privilege escalation. Avoid chown. Use `install -d -m 0775/2775` for group-write with sticky set as needed. - Vanilla: init runs as root (UID 0) to chown created dirs to the non-root runtime user (defaults to 1000:1000); main container runs non-root. - When readOnlyRootFilesystem=true: - Mount EmptyDir volumes to /run, /tmp (Memory), /var/log/nginx, /var/cache/nginx. - Add matching volumeMounts. - Keep probes and ports unchanged. - Values: add/clarify `openshift.enabled` flag, securityContext defaults, imageCredentials usage, and sample values for both environments. Intel - Add initContainer `prepare-runtime` to create /var/log/nginx and /var/cache/nginx and make them writable under read-only rootfs. - Same OpenShift vs vanilla split as collab (no explicit UID/GID on OCP; root init + non-root app for vanilla). - Mount EmptyDir + volumeMounts for /run, /tmp (Memory), /var/log/nginx, /var/cache/nginx when readOnlyRootFilesystem=true. - Preserve existing envs (AI mode, HQ base URL, Java options, etc.). Why --- - Fixes SCC denials on OpenShift when explicit runAsUser/fsGroup were set. - Fixes initContainer permission errors (e.g., "Operation not permitted" on /run) by avoiding chown on OpenShift and using 2775 with umask 002. - Enables secure read-only rootfs operation by provisioning necessary writable paths via EmptyDir. Testing ------- - OpenShift 4.x: - `openshift.enabled=true`, remove fsGroup=0, do not set runAsUser/runAsGroup. - initContainers succeed; pods transition to Running. - Vanilla (DigitalOcean Kubernetes): - `openshift.enabled=false`, readOnlyRootFilesystem=true. - init runs as root, chowns to 1000:1000; app runs as non-root. - Pods healthy; readiness/liveness OK. Breaking changes ---------------- - None functionally; however, when enabling readOnlyRootFilesystem, the chart now requires the EmptyDir mounts (added by default when the flag is true). * Testing * fix(openshift): make Intel/Collab charts run on OpenShift; verified in-cluster Fixes: #177 - Validated (same OpenShift env) - This change fixes the customer’s OpenShift issue. * Allow to set the CT_CUSTOM_CLIENTS_ORIGIN env variable. * fix env variable name * Allow to add custom ide location url (#184) * Remove volumeMounts for readOnlyRootFilesystem Removed volumeMounts configuration for properties-volume. * Update codetogether-tmp volume medium configuration Changed the medium of the codetogether-tmp volume from 'Memory' to an empty object. * Simplify emptyDir volume definition in deployment.yaml * Update version and appVersion in Chart.yaml * refactor(helm): decouple customClientsUrl from AI config (#187) Fixes: #180 - Render clients url when codetogether.customClientsUrl * Bump version and appVersion in Chart.yaml * Bump version and appVersion in Chart.yaml * fix: enable read-only FS support (#189) * Bump version and appVersion in Chart.yaml * Bump version to 1.2.7 and appVersion to 2025.4.2 * Remove run-nginx volume mount Removed run-nginx volume mount from deployment. * Add run-volatile mount and volume to deployment.yaml * Refactor deployment.yaml for memory-backed volumes Updated volume mounts and volumes to use memory medium for tmp and run-volatile. * feat: add warning log when deprecated AV settings are detected (#193) * 192 add warning log when av related helm values are detected (#194) * feat(helm): add warning log when deprecated AV settings are detected Fixes: #192 - Added a startup warning when any Audio/Video related values (av.enabled, av.serverIP, av.stunServers, av.jitsiUrl) are present in Helm chart configurations. - Ensures deployments are notified that built in A/V support is no longer available. - No functional behavior changed, only logs a warning at container start. * chore: add AV deprecation warning and clean up env vars - Add Helm NOTES warning when AV related values are configured - Remove unused CT_AV_DEPRECATED_WARNING environment variable from Deployment - Keep AV env configuration minimal while clearly signaling that A/V is no longer supported * Bump version and appVersion in Chart.yaml * Bump version and appVersion in Chart.yaml * fix(intel-chart): ensure Ingress v1 + pathType for modern Kubernetes (#197) Fixes: #196 * feat(helm): add optional service annotations to collab chart Service (#199) Fixes: #198 - add service.annotations to values.yaml with default {} - render metadata.annotations in templates/service.yaml via .Values.service.annotations - keep backward compatibility when annotations are not set * Bump version and appVersion in Chart.yaml * Bump version and appVersion in Chart.yaml * feat(helm): add configurable initContainers (startup containers) to Intel deployment (#202) Fixes: #201 - This PR adds support for configurable “startup containers” by allowing users to define Kubernetes initContainers in the Intel Helm chart. * feat: add configurable initContainers to collab helm chart (#204) * Add dedicated Keycloak readiness gate to prevent Intel starting too e… (#205) * Add dedicated Keycloak readiness gate to prevent Intel starting too early This PR adds an optional Docker Compose overlay that supports customers running a dedicated/external Keycloak (Keycloak not started by our compose stack). Some customers still use an external Keycloak. In this mode, the previously recommended depends_on: codetogether-keycloak: condition: service_healthy cannot apply, because there is no codetogether-keycloak service in the final stack. As a result, docker compose up --wait can fail because codetogether-intel starts before Keycloak is reachable. Add a new compose overlay: compose/compose.dedicated-keycloak.yaml Introduces a lightweight keycloak-ready service with a healthcheck that polls: https://${KEYCLOAK_FQDN}/realms/${KEYCLOAK_REALM}/.well-known/openid-configuration Makes codetogether-intel depend on: - cassandra: service_healthy (keep existing dependency) - keycloak-ready: service_healthy (new gate) - Add a short compose/README.md describing: - required .env variables (KEYCLOAK_FQDN, KEYCLOAK_REALM) - exact docker compose command using the overlay docker compose \ -f compose/compose.yaml \ -f compose/compose.dedicated-keycloak.yaml \ --env-file ./.env \ up --pull always --wait -d * Fix * Support adding extra volume mounts via the values.yml file in Helm * Add extraContainers support for sidecar injection (#206) - The chart currently supports extraVolumes, extraVolumeMounts, and extraEnvVars but has no way to inject additional containers into the pod spec. - This adds an extraContainers parameter (empty by default) following the same convention, enabling sidecar use cases like Fluent Bit for CloudWatch log shipping. * feat: make health probe path/port configurable (v1.3.5) (#208) Template the hardcoded path (/) and port (http) in liveness and readiness probes so they can be overridden via values. Defaults preserve existing behavior for all current deployments. CTPD-4358 Made-with: Cursor --------- Co-authored-by: Wojciech Galanciak Co-authored-by: Ignacio Moreno Co-authored-by: engineering Co-authored-by: Ignacio Moreno Co-authored-by: Timothy Webb --- charts/intel/Chart.yaml | 2 +- charts/intel/templates/deployment.yaml | 8 ++++---- charts/intel/values.yaml | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/charts/intel/Chart.yaml b/charts/intel/Chart.yaml index 2fa000d..c80f096 100644 --- a/charts/intel/Chart.yaml +++ b/charts/intel/Chart.yaml @@ -3,7 +3,7 @@ name: codetogether-intel description: CodeTogether Intel provides advanced project insights for developers type: application -version: 1.3.4 +version: 1.3.5 appVersion: "2026.1.2" icon: https://www.codetogether.com/wp-content/uploads/2020/02/codetogether-circle-128.png diff --git a/charts/intel/templates/deployment.yaml b/charts/intel/templates/deployment.yaml index 110b1fd..d7ec1c5 100644 --- a/charts/intel/templates/deployment.yaml +++ b/charts/intel/templates/deployment.yaml @@ -147,8 +147,8 @@ spec: successThreshold: {{ .Values.livenessProbe.successThreshold }} failureThreshold: {{ .Values.livenessProbe.failureThreshold }} httpGet: - path: / - port: http + path: {{ .Values.livenessProbe.path | default "/" }} + port: {{ .Values.livenessProbe.port | default "http" }} readinessProbe: initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} @@ -157,8 +157,8 @@ spec: successThreshold: {{ .Values.readinessProbe.successThreshold }} failureThreshold: {{ .Values.readinessProbe.failureThreshold }} httpGet: - path: / - port: http + path: {{ .Values.readinessProbe.path | default "/" }} + port: {{ .Values.readinessProbe.port | default "http" }} resources: {{- toYaml .Values.resources | nindent 12 }} diff --git a/charts/intel/values.yaml b/charts/intel/values.yaml index c6f6863..4dfa92a 100644 --- a/charts/intel/values.yaml +++ b/charts/intel/values.yaml @@ -173,6 +173,8 @@ ai: #memory: "4Gi" readinessProbe: + path: / + port: http initialDelaySeconds: 60 periodSeconds: 60 timeoutSeconds: 15 @@ -180,6 +182,8 @@ readinessProbe: failureThreshold: 1 livenessProbe: + path: / + port: http initialDelaySeconds: 60 periodSeconds: 60 timeoutSeconds: 15 From 2fb3ec67e9841b6084886cdbfbcfab9332160a92 Mon Sep 17 00:00:00 2001 From: Daniel Garcia Rico Date: Tue, 30 Jun 2026 18:22:00 +0000 Subject: [PATCH 2/5] Publish CodeTogether AI Helm chart --- charts/ai/.helmignore | 22 ++ charts/ai/Chart.yaml | 21 ++ charts/ai/README.md | 228 +++++++++++++++++ .../ai/ctai-configuration.properties.template | 150 ++++++++++++ charts/ai/generate-master-key.sh | 158 ++++++++++++ charts/ai/generate-properties-secrets.sh | 159 ++++++++++++ charts/ai/templates/NOTES.txt | 36 +++ charts/ai/templates/_helpers.tpl | 231 ++++++++++++++++++ charts/ai/templates/deployment.yaml | 155 ++++++++++++ charts/ai/templates/ingress-class.yaml | 10 + charts/ai/templates/ingress.yaml | 51 ++++ .../ai/templates/secret-ctai-properties.yaml | 12 + charts/ai/templates/secret-master-key.yaml | 18 ++ charts/ai/templates/secret-pullimage.yaml | 12 + charts/ai/templates/service.yaml | 19 ++ charts/ai/templates/serviceaccount.yaml | 12 + .../ai/templates/tests/test-connection.yaml | 22 ++ charts/ai/values.yaml | 134 ++++++++++ 18 files changed, 1450 insertions(+) create mode 100644 charts/ai/.helmignore create mode 100644 charts/ai/Chart.yaml create mode 100644 charts/ai/README.md create mode 100644 charts/ai/ctai-configuration.properties.template create mode 100755 charts/ai/generate-master-key.sh create mode 100755 charts/ai/generate-properties-secrets.sh create mode 100644 charts/ai/templates/NOTES.txt create mode 100644 charts/ai/templates/_helpers.tpl create mode 100644 charts/ai/templates/deployment.yaml create mode 100644 charts/ai/templates/ingress-class.yaml create mode 100644 charts/ai/templates/ingress.yaml create mode 100644 charts/ai/templates/secret-ctai-properties.yaml create mode 100644 charts/ai/templates/secret-master-key.yaml create mode 100644 charts/ai/templates/secret-pullimage.yaml create mode 100644 charts/ai/templates/service.yaml create mode 100644 charts/ai/templates/serviceaccount.yaml create mode 100644 charts/ai/templates/tests/test-connection.yaml create mode 100644 charts/ai/values.yaml diff --git a/charts/ai/.helmignore b/charts/ai/.helmignore new file mode 100644 index 0000000..a81648f --- /dev/null +++ b/charts/ai/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +.DS_Store +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +*.swp +*.bak +*.tmp +*.orig +*~ +.project +.idea/ +*.tmproj +.vscode/ +SPEC.md +values-aitrax.yaml +values-cluster.yaml +values-local.yaml diff --git a/charts/ai/Chart.yaml b/charts/ai/Chart.yaml new file mode 100644 index 0000000..71962b1 --- /dev/null +++ b/charts/ai/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: codetogether-ai +description: CodeTogether AI on-premises Kubernetes deployment + +type: application +version: 0.1.0 +appVersion: "0.1.1204" + +icon: https://www.codetogether.com/wp-content/uploads/2020/02/codetogether-circle-128.png +home: https://www.codetogether.com + +maintainers: + - email: info@codetogether.com + name: CodeTogether Inc. + +keywords: + - codetogether + - ctai + - ai + - aitrax + - on-premises diff --git a/charts/ai/README.md b/charts/ai/README.md new file mode 100644 index 0000000..a407001 --- /dev/null +++ b/charts/ai/README.md @@ -0,0 +1,228 @@ +# Helm Chart for CodeTogether AI + +## Summary + +This chart deploys CodeTogether AI on a Kubernetes cluster using Helm. Runtime +configuration is supplied as `ctai-configuration.properties`, and the protected +storage master key is stored in a separate Kubernetes Secret. + +## Prerequisites + +- Helm v3.5+ +- Kubernetes v1.19+ +- PostgreSQL reachable from the cluster. This chart does not install Postgres. +- A DNS-routable HTTPS host for CodeTogether AI, configured as `service_fqdn`. +- A TLS Secret for Ingress when `ingress.enabled=true`. +- CodeTogether-provided credentials for `hub.edge.codetogether.com`. + +## Install + +### 1. Prepare the configuration file + +Copy `ctai-configuration.properties.template` to +`ctai-configuration.properties`, then replace the example values with the values +for your environment. + +```bash +cp ctai-configuration.properties.template ctai-configuration.properties +``` + +Set `service_fqdn` to the public HTTPS URL for the deployment, for example: + +```properties +service_fqdn=https://ai.example.com +``` + +Set the external Postgres connection properties: + +```properties +database_url=jdbc:postgresql://postgres.example.internal:5432/codetogether +database_username=codetogether +database_password=replace-with-postgres-password +``` + +Generate the random properties-file secrets and paste the output into +`ctai-configuration.properties`: + +```bash +./generate-properties-secrets.sh +``` + +The configuration file contains deployment secrets. Store it securely and do +not commit customer-specific values. + +### 2. Configure SSO + +Register this redirect URI with your identity provider: + +```text +https://ai.example.com/api/v1/auth/sso/provider/callback +``` + +Use the same host as `service_fqdn`. For Google OAuth or Google OIDC, add that +URI as an Authorized redirect URI in the Google Cloud Console, then set the +provider values in `ctai-configuration.properties`, for example: + +```properties +sso_provider1_type=google +sso_provider1=google +sso_provider1_client_id=replace-with-google-client-id +sso_provider1_client_secret=replace-with-google-client-secret +sso_provider1_client_issuer_url=https://accounts.google.com +``` + +### 3. Create the TLS Secret + +Create the TLS Secret in the namespace where CodeTogether AI will run. The +default Secret name is `codetogether-ai-tls`. + +```bash +kubectl create namespace codetogether-ai +kubectl create secret tls codetogether-ai-tls \ + --namespace codetogether-ai \ + --key /path/to/tls.key \ + --cert /path/to/tls.crt +``` + +### 4. Create the protected storage master-key Secret + +CodeTogether AI uses a 32-byte AES master key to encrypt sensitive values stored +in Postgres. Generate this key once per deployment environment and database. +Changing the key after encrypted data exists prevents that data from being +decrypted. + +```bash +./generate-master-key.sh --k8s-secret-yaml --secret-name ctai-master-key \ + > ctai-master-key-secret.yaml + +kubectl apply -f ctai-master-key-secret.yaml -n codetogether-ai +``` + +Save the generated base64 key in your password manager and keep it with your +Postgres backup procedure. + +### 5. Install the chart + +```bash +helm repo add codetogether https://helm.codetogether.io +helm repo update + +helm install codetogether-ai codetogether/codetogether-ai \ + --namespace codetogether-ai --create-namespace \ + --set-file ctaiPropertiesFile=./ctai-configuration.properties \ + --set imageCredentials.username=replace-with-hub-edge-username \ + --set imageCredentials.password=replace-with-hub-edge-password \ + --set masterKey.source=secret \ + --set masterKey.existingSecret=ctai-master-key +``` + +Ingress host and TLS are derived from `service_fqdn` in +`ctai-configuration.properties`. If you also set `service.fqdn` in Helm values, +it must exactly match `service_fqdn`. + +## Configuration + +The following table lists the primary configurable parameters and defaults. + +| Parameter | Description | Default | +| --------- | ----------- | ------- | +| `nameOverride` | Overrides the chart name | `""` | +| `fullnameOverride` | Overrides the full release name | `""` | +| `image.repository` | Container image repository | `hub.edge.codetogether.com/releases/codetogether-ai` | +| `image.pullPolicy` | Image pull policy | `Always` | +| `image.tag` | Container image tag | `latest` | +| `image.digest` | Optional image digest; overrides the tag when set | `""` | +| `imageCredentials.enabled` | Create a pull Secret from registry credentials | `true` | +| `imageCredentials.registry` | Private registry host | `hub.edge.codetogether.com` | +| `imageCredentials.username` | Registry username | `my-customer-username` | +| `imageCredentials.password` | Registry password | `my-customer-password` | +| `service.fqdn` | Public HTTPS URL; optional with `--set-file`, required for pre-created properties Secrets | `""` | +| `service.type` | Kubernetes Service type | `ClusterIP` | +| `service.port` | Service port for nginx / portal | `1080` | +| `service.annotations` | Kubernetes Service annotations | `{}` | +| `ctaiPropertiesFile` | Properties file contents, normally set with `--set-file` | `""` | +| `ctaipropertiessecret.enabled` | Mount a pre-created properties Secret instead of creating one from `ctaiPropertiesFile` | `false` | +| `ctaipropertiessecret.ref` | Name of the pre-created properties Secret | `""` | +| `masterKey.source` | Master key source: `secret`, `auto`, or `external` | `secret` | +| `masterKey.existingSecret` | Pre-created master-key Secret name when `source=secret` | `ctai-master-key` | +| `masterKey.existingSecretKey` | Key in the master-key Secret | `CTAI_PROTECTED_STORAGE_MASTER_KEY_B64` | +| `masterKey.existingSecretVersionKey` | Optional version key in the master-key Secret | `CTAI_PROTECTED_STORAGE_MASTER_KEY_VERSION` | +| `properties.mountPath` | Pod mount path for the properties file | `/opt/ctai/server/config` | +| `properties.fileName` | Properties filename inside the Secret | `ctai-configuration.properties` | +| `ingress.enabled` | Create an Ingress resource | `true` | +| `ingress.annotations` | Ingress annotations | `nginx.ingress.kubernetes.io/proxy-body-size: "16m"` | +| `ingress.tls.secretName` | TLS Secret for Ingress | `codetogether-ai-tls` | +| `serviceAccount.create` | Create a ServiceAccount | `true` | +| `serviceAccount.name` | ServiceAccount name | `codetogether-ai` | +| `replicaCount` | Deployment replica count | `1` | +| `readinessProbe.path` | Readiness endpoint on port 1080 | `/healthz` | +| `livenessProbe.path` | Liveness endpoint on port 8080 | `/actuator/health` | +| `startupProbe.enabled` | Enable startup probe | `true` | + +## Pre-Created Properties Secret + +For GitOps workflows, create and manage the properties Secret outside Helm: + +```bash +kubectl create secret generic ctai-properties \ + --namespace codetogether-ai \ + --from-file=ctai-configuration.properties=./ctai-configuration.properties +``` + +Then install or upgrade with: + +```yaml +ctaipropertiessecret: + enabled: true + ref: ctai-properties + +service: + fqdn: https://ai.example.com +``` + +When Helm cannot read the properties file through `--set-file`, `service.fqdn` +is required for Ingress and install notes. It must match `service_fqdn` inside +the Secret. + +## Validation and Troubleshooting + +Render the chart locally before installing: + +```bash +helm template codetogether-ai codetogether/codetogether-ai \ + --set-file ctaiPropertiesFile=./ctai-configuration.properties \ + --set imageCredentials.username=test \ + --set imageCredentials.password=test +``` + +At runtime, CodeTogether AI validates the mounted configuration before the +service starts. If validation fails, the pod exits and logs a block beginning +with `Configuration errors:`. + +```bash +kubectl logs -n codetogether-ai deploy/codetogether-ai +kubectl logs -n codetogether-ai deploy/codetogether-ai --previous +``` + +Common causes include unfilled example values, Postgres connectivity problems, +missing or changed master-key Secret, an HTTP `service_fqdn`, missing TLS +Secret, or SSO provider settings that do not match the registered redirect URI. + +## Upgrade + +```bash +helm repo update +helm upgrade codetogether-ai codetogether/codetogether-ai \ + --namespace codetogether-ai \ + --set-file ctaiPropertiesFile=./ctai-configuration.properties \ + --set imageCredentials.username=replace-with-hub-edge-username \ + --set imageCredentials.password=replace-with-hub-edge-password +``` + +The Deployment rolls when the chart-managed properties Secret changes. + +## Uninstall + +```bash +helm uninstall codetogether-ai -n codetogether-ai +``` diff --git a/charts/ai/ctai-configuration.properties.template b/charts/ai/ctai-configuration.properties.template new file mode 100644 index 0000000..8b74da0 --- /dev/null +++ b/charts/ai/ctai-configuration.properties.template @@ -0,0 +1,150 @@ +# ============================================================================= +# CodeTogether — configuration template (manual fill-in) +# ============================================================================= +# +# Copy this file, replace placeholder values, and save as: +# ctai-configuration.properties +# +# Lines starting with # are comments and are ignored when the file is loaded. +# Each setting uses key=value format (same keys written by the config wizard). +# +# Prefer the config wizard when possible — it validates settings, generates +# secrets, and can test database, SSO, and SMTP connectivity. +# +# After editing manually, you can open the saved file in the wizard (Intro → +# Open existing properties file...) to review or update settings. +# +# ============================================================================= + +# Company display name shown in the application. +# You can update this later from the dashboard. +company_name=Example Company + +# Public Fully Qualified Domain Name (fqdn) for the CodeTogether service. This hostname must be DNS routable and must use https://. +service_fqdn=https://example.codetogether.io + +# Sender address and display name for outbound mail. +email_from_address=noreply@example.com +email_from_name=Example Company + +# SMTP server hostname and port (587 is typical with STARTTLS). +smtp_host=smtp.example.com +smtp_port=587 + +# true when the SMTP server requires authentication; false for open relay / +# IP-allowlisted servers. +smtp_auth_enabled=false +# required when smtp_auth_enabled=true +smtp_username= +smtp_password= + +# STARTTLS: connect on a plain connection first, then upgrade to TLS before +# sending credentials (typical on port 587). +smtp_start_tls=true + +# Connection timeouts in ISO-8601 duration form (defaults shown). +smtp_connect_timeout=PT10S +smtp_read_timeout=PT30S + +# PostgreSQL JDBC URL. Pattern: jdbc:postgresql:/// +# Use a dedicated database for CodeTogether rather than reusing an existing one. +database_url=jdbc:postgresql://postgres.example.internal:5432/codetogether +database_username=codetogether +database_password=replace-with-postgres-password + +# Schemas for telemetry, platform, and datamart data (defaults shown). +# Telemetry: developer and AI activity. +# Datamart: analytics calculated from telemetry. +# Platform: backend server data. +database_telemetry_schema=telemetry +database_platform_schema=platform +database_datamart_schema=datamart + +# Signs short-lived state tokens during GitHub OAuth flows — used when connecting +# a GitHub App and when creating a new GitHub App via manifest provisioning. +# Generate a unique random value; do not reuse across deployments. +# Or run: ./generate-properties-secrets.sh (in this chart directory) +github_state_secret=replace-with-generated-github-state-secret + +# Signs JWT session cookies to secure user sessions after SSO login. +# Generate a unique random value; must differ from the other deployment secrets. +# Do not change after login to the dashboard unless you want your login cookies to change +# Or run: ./generate-properties-secrets.sh (in this chart directory) +sso_jwt_secret=replace-with-generated-sso-jwt-secret + +# Register the full callback URL at your IdP: +# https:///api/v1/auth/sso/provider/callback +# Example: https://mycompany.codetogether.com/api/v1/auth/sso/provider/callback +# +# ----------------------------------------------------------------------------- +# SSO providers +# ----------------------------------------------------------------------------- +# +# Each provider uses a numbered prefix: sso_provider1, sso_provider2, ... +# Use consecutive integers starting at 1 with no gaps. +# +# Required keys per provider (replace N with 1, 2, 3, ...): +# sso_providerN_type Provider kind (see valid types below). +# sso_providerN Provider name (see naming rules below). +# sso_providerN_client_id OAuth client ID from your identity provider. +# sso_providerN_client_secret OAuth client secret. +# +# Valid sso_providerN_type values: +# keycloak, github, google, azure, okta, custom +# +# sso_providerN (name field) rules: +# - For keycloak, google, azure, okta: use the same string as _type +# (e.g. sso_provider1_type=keycloak and sso_provider1=keycloak). +# - For github: use github. +# - For custom (optional second sign-in provider): use a unique lowercase +# name (e.g. customprovidername) or a built-in kind for an alternate +# account (github, keycloak, etc.). Only one custom provider is allowed. +# - You cannot register two providers with the same registration id +# (e.g. two keycloak entries); use custom for a second GitHub or Keycloak. +# +# OIDC providers (keycloak, google, azure, okta, and custom with issuer): +# sso_providerN_client_issuer_url= +# +# GitHub (and custom providers using GitHub OAuth endpoints): set _auth_uri, +# _token_uri, _info_uri, _jwt_set_uri, and optionally _logout_uri instead of +# client_issuer_url. Standard GitHub values: +# auth: https://github.com/login/oauth/authorize +# token: https://github.com/login/oauth/access_token +# info: https://api.github.com/user +# jwks: https://token.actions.githubusercontent.com/.well-known/jwks +# logout: https://github.com/logout +# +# Optional keys (omit to use runtime defaults): +# sso_providerN_client_authentication_method +# sso_providerN_display_label Custom provider label shown to users. +# sso_providerN_name_attribute Default varies by type (e.g. login for GitHub). +# sso_providerN_scopes Default: openid,email,profile (email,profile for GitHub). +# sso_providerN_authorization_grant_type Default: authorization_code +# sso_providerN_role_mapping_claim +# sso_providerN_role-mappings Note: hyphen in the property name. +# +# Example — first provider (Keycloak / OIDC): +sso_provider1_type=keycloak +sso_provider1=keycloak +sso_provider1_client_id=replace-with-client-id +sso_provider1_client_secret=replace-with-client-secret +sso_provider1_client_issuer_url=https://auth.example.com/realms/codetogether + +# Example — second provider (uncomment and renumber if needed): +# sso_provider2_type=custom +# sso_provider2= +# sso_provider2_client_id= +# sso_provider2_client_secret= +# sso_provider2_display_label=