Skip to main content

Installation Guide

Deploy Align on your Kubernetes cluster.

Getting the Helm Chart

Align's chart and images are served from a private, credentialed OCI registry. The registry host, and the credentials that reach it, are issued to you at onboarding alongside your license. There is no public Align registry to pull from anonymously.

These pages write $ALIGN_REGISTRY for that host. Set it once and the examples below work as written:

export ALIGN_REGISTRY="<the registry host issued to you at onboarding>"
export ALIGN_REGISTRY_REGION="<the region issued to you at onboarding>"
export ALIGN_CHART_VERSION="<the chart version for your release>"
export ALIGN_VERSION="<the release tag for your release, e.g. v0.22.26>"

Authenticate to the registry

Do this first. Every helm and docker command on this page pulls from a private registry, and without credentials the very first one fails with a 401 rather than anything that names the cause.

The registry is AWS ECR, and onboarding grants your AWS account pull access to it. One token serves both clients:

# Helm, for the chart
aws ecr get-login-password --region "$ALIGN_REGISTRY_REGION" | \
helm registry login "$ALIGN_REGISTRY" --username AWS --password-stdin

# Docker, for the images - only needed if you are mirroring (Option B below)
aws ecr get-login-password --region "$ALIGN_REGISTRY_REGION" | \
docker login "$ALIGN_REGISTRY" --username AWS --password-stdin
note

These are your credentials, so that your machine can pull. They are a different thing from the imagePullSecrets created further down this page, which are what let the cluster pull images at runtime. You need both, and neither substitutes for the other.

ECR tokens are short-lived, so re-run the login if a pull starts returning 401 partway through an upgrade.

Your onboarding pack names both versions above. To see what the registry actually holds:

helm show chart oci://$ALIGN_REGISTRY/align/charts/align # omit --version to take the latest
# Pull the chart
helm pull oci://$ALIGN_REGISTRY/align/charts/align --version "$ALIGN_CHART_VERSION"

# Or install directly
helm install align \
oci://$ALIGN_REGISTRY/align/charts/align \
--version "$ALIGN_CHART_VERSION" \
--namespace align \
--values values.yaml
note

For production deployments, we recommend mirroring artifacts to your own registry (Option B below).

For production deployments, we recommend mirroring all artifacts to your own registry. This provides:

  • Reliability - No dependency on Align's infrastructure
  • Security - Full control over what runs in your cluster
  • Compliance - Artifacts scanned by your security tools
  • Air-gap support - Works in isolated environments

Step 1: Mirror the Helm Chart

# Pull the chart from Align's registry
helm pull oci://$ALIGN_REGISTRY/align/charts/align --version "$ALIGN_CHART_VERSION"

# Push to your registry (choose your cloud provider)
helm push "align-${ALIGN_CHART_VERSION}.tgz" oci://your-registry/align/charts

Step 2: Mirror Docker Images

All images for a release use the same version tag:

VERSION="$ALIGN_VERSION"
SOURCE_REGISTRY="$ALIGN_REGISTRY/align"

# Set your target registry based on your cloud:
# AWS ECR: TARGET_REGISTRY="123456789.dkr.ecr.us-east-1.amazonaws.com/align"
# Azure ACR: TARGET_REGISTRY="myregistry.azurecr.io/align"
# GCP: TARGET_REGISTRY="us-docker.pkg.dev/my-project/align"
# Docker Hub: TARGET_REGISTRY="docker.io/myorg/align"
TARGET_REGISTRY="your-registry/align"

IMAGES=(
"gateway"
"brain"
"ui"
"migrations"
"connector-slack"
"connector-github"
"connector-jira"
"connector-teams"
"connector-align"
)

for image in "${IMAGES[@]}"; do
docker pull "${SOURCE_REGISTRY}/${image}:${VERSION}"
docker tag "${SOURCE_REGISTRY}/${image}:${VERSION}" "${TARGET_REGISTRY}/${image}:${VERSION}"
docker push "${TARGET_REGISTRY}/${image}:${VERSION}"
done

Step 3: Configure Helm to Use Your Registry

# values.yaml
global:
# Your container registry ROOT - not including the `align/` path segment, which the
# chart already carries in each image's repository. The mirror step above pushes to
# ${TARGET_REGISTRY}/<image>, so `your-registry` here resolves to
# `your-registry/align/gateway`, which is exactly where the mirror put it.
# AWS ECR: imageRegistry: "123456789.dkr.ecr.us-east-1.amazonaws.com"
# Azure ACR: imageRegistry: "myregistry.azurecr.io"
# GCP: imageRegistry: "us-docker.pkg.dev/my-project"
imageRegistry: your-registry

# Registry authentication (if required)
imagePullSecrets:
- name: registry-credentials

Creating Registry Pull Secrets

AWS ECR
# Create secret with ECR credentials
kubectl create secret docker-registry ecr-credentials \
--namespace align \
--docker-server=123456789.dkr.ecr.us-east-1.amazonaws.com \
--docker-username=AWS \
--docker-password=$(aws ecr get-login-password --region us-east-1)

Or use ECR credential helper with IRSA.

Azure ACR
# Create secret with ACR credentials
kubectl create secret docker-registry acr-credentials \
--namespace align \
--docker-server=myregistry.azurecr.io \
--docker-username=<service-principal-id> \
--docker-password=<service-principal-password>

Or use ACR with AKS managed identity.

Google Artifact Registry
# Create secret with GCP credentials
kubectl create secret docker-registry gcr-credentials \
--namespace align \
--docker-server=us-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(cat service-account-key.json)"

Or use Workload Identity.

Registry-based distribution

Align is distributed as signed container images and a Helm chart from Align's private registry - source code is never distributed. Licensing is validated locally with an offline JWT license file. See Licensing for details.

Prerequisites

Before you begin, ensure you have:

  • Kubernetes 1.25+ cluster (EKS, AKS, GKE, or self-managed)
  • Helm 3.10+
  • kubectl configured for your cluster
  • PostgreSQL 15+ database with pgvector extension:
    • AWS: RDS PostgreSQL or Aurora PostgreSQL
    • Azure: Azure Database for PostgreSQL Flexible Server
    • GCP: Cloud SQL for PostgreSQL
    • Self-hosted: PostgreSQL with pgvector installed
  • Ingress controller (Traefik, nginx, or cloud-native like ALB/Application Gateway)
  • (Recommended) cert-manager for TLS

Step 1: Create Namespace

kubectl create namespace align

Step 2: Configure Database

Create a secret with your database credentials:

kubectl create secret generic align-database \
--namespace align \
--from-literal=url="postgresql://user:password@host:5432/align" \
--from-literal=host="your-db-host.example.com" \
--from-literal=port="5432" \
--from-literal=username="align" \
--from-literal=password="your-secure-password"

Option B: Deploy PostgreSQL in Cluster

For development/testing, you can deploy PostgreSQL alongside Align:

# values.yaml
postgresql:
enabled: true
auth:
database: align
username: align
password: your-secure-password
warning

In-cluster PostgreSQL is not recommended for production. Use a managed database service:

  • AWS: RDS PostgreSQL or Aurora PostgreSQL
  • Azure: Azure Database for PostgreSQL Flexible Server
  • GCP: Cloud SQL for PostgreSQL

Step 3: Configure Secrets

Align requires several secrets for operation. See Secrets Management for detailed options.

Minimal Secrets

At minimum, create internal secrets:

kubectl create secret generic align-internal \
--namespace align \
--from-literal=jwt-secret="$(openssl rand -base64 32)" \
--from-literal=cookie-secret="$(openssl rand -base64 32)" \
--from-literal=encryption-key="$(openssl rand -base64 32)" \
--from-literal=service-auth-token="$(openssl rand -base64 32)"

LLM Secrets (Required for AI features)

kubectl create secret generic align-llm \
--namespace align \
--from-literal=openai-api-key="sk-..." \
# OR
--from-literal=anthropic-api-key="sk-ant-..."

Or see LLM Setup for self-hosted models.

Step 4: Create Values File

Create a values.yaml file for your deployment:

# values.yaml
global:
environment: production

# REQUIRED. The registry root your images come from - the Align registry host issued at
# onboarding, or your own registry once you have mirrored our images into it. The chart
# refuses to render if this is unset: an empty value would produce a bare image name, and
# Docker resolves a bare name against Docker Hub rather than anywhere Align controls.
imageRegistry: "<your ALIGN_REGISTRY, or your own registry root>"

# Database
database:
secretName: align-database

# Gateway
gateway:
replicaCount: 2
frontendUrl: "https://app.yourdomain.com"
ingress:
enabled: true
className: "nginx" # or "traefik"
hosts:
- host: api.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-tls
hosts:
- api.yourdomain.com

# UI
ui:
replicaCount: 2
ingress:
enabled: true
className: "nginx"
hosts:
- host: app.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.yourdomain.com

# Brain (AI Service)
brain:
replicaCount: 2

# Connectors - disable unused ones
connectors:
slack:
enabled: true
teams:
enabled: true
jira:
enabled: true
github:
enabled: true
linear:
enabled: false # Enable if needed
align:
enabled: false # Enable for AI assistant integration (Claude, Cursor)

# Secrets
secrets:
create: false # Use pre-created secrets

See Configuration Reference for all options.

Step 4b: GPU Inference (Optional)

To run LLM inference locally instead of using cloud APIs, add GPU configuration to your values file. This requires GPU nodes in your cluster.

# values.yaml (add to existing file)
gpu:
devicePlugin:
enabled: true
llmServer:
enabled: true

# Tell Brain which model the local server runs
brain:
extraEnv:
- name: LOCAL_LLM_MODEL
value: "meta-llama/Llama-3.1-8B-Instruct"

If you need a HuggingFace token for gated models (e.g., Llama), create the secret:

kubectl create secret generic hf-token \
--namespace align \
--from-literal=token="hf_..."

See LLM Configuration - GPU Inference for full GPU setup including node requirements.

tip

GPU inference is optional. Without it, Align uses cloud APIs (OpenAI/Anthropic) or CPU-based models (Ollama). You can add GPU later without downtime.

Step 5: Install Align

helm install align \
oci://your-registry/align/charts/align \
--version "$ALIGN_CHART_VERSION" \
--namespace align \
--values values.yaml

From Align's Registry (Direct)

helm install align \
oci://$ALIGN_REGISTRY/align/charts/align \
--version "$ALIGN_CHART_VERSION" \
--namespace align \
--values values.yaml

Step 6: Verify Installation

# Check pods are running
kubectl get pods -n align

# Expected output:
# NAME READY STATUS RESTARTS AGE
# align-gateway-xxx 1/1 Running 0 2m
# align-brain-xxx 1/1 Running 0 2m
# align-ui-xxx 1/1 Running 0 2m
# align-connector-slack-xxx 1/1 Running 0 2m
# ...

# Check services
kubectl get svc -n align

# Check ingress
kubectl get ingress -n align

Step 7: Run Migrations

Migrations run automatically as a Helm pre-install hook. Verify they completed:

kubectl get jobs -n align

# Should show:
# NAME COMPLETIONS DURATION AGE
# align-migrations 1/1 30s 5m

Step 8: Access Align

  1. Ensure DNS is configured for your domains
  2. Navigate to https://app.yourdomain.com
  3. Sign in or create your first user

Troubleshooting

Pods not starting

# Check pod status
kubectl describe pod -n align <pod-name>

# Check logs
kubectl logs -n align <pod-name>

Database connection issues

# Verify secret exists
kubectl get secret align-database -n align

# Test connection from a pod
kubectl run -it --rm debug --image=postgres:15 \
--restart=Never -n align -- \
psql "postgresql://user:pass@host:5432/align"

Ingress not working

# Check ingress status
kubectl describe ingress -n align

# Verify TLS secret exists
kubectl get secret api-tls -n align

Next Steps