Helm Chart Configuration
Complete reference for all values.yaml options. Install AllureDeck from the OCI registry — no helm repo add required.
Prerequisites
Before installing AllureDeck, ensure you have:
- Kubernetes 1.26+ — required for modern security context and policy APIs
- Helm 3.10+ — required for OCI registry support
- PostgreSQL 14+ — external database; the chart does not deploy PostgreSQL
Quick Start
The fastest path to a running installation. All three commands install directly from the OCI registry.
helm install alluredeck oci://ghcr.io/mkutlak/charts/alluredeck \ --set api.config.databaseURL="postgres://user:password@postgres-host:5432/alluredeck?sslmode=require"
helm install alluredeck oci://ghcr.io/mkutlak/charts/alluredeck -f values.yaml
helm install alluredeck oci://ghcr.io/mkutlak/charts/alluredeck --version 0.4.0
API Configuration
Core settings for the Go API backend. Values under api.config.* are passed as environment variables to the container.
| Key | Description | Default |
|---|---|---|
| api.image.repository | API container image | ghcr.io/mkutlak/alluredeck-api |
| api.image.tag | Image tag | "" (appVersion) |
| api.config.devMode | Enable dev mode (verbose logging, relaxed security) | "false" |
| api.config.logLevel | Log level (debug, info, warn, error) |
"info" |
| api.config.storageType | File storage backend (local or s3) |
"local" |
| api.config.databaseURL | PostgreSQL connection string | "" |
| api.config.keepHistory | Enable test history tracking | "true" |
| api.config.keepHistoryLatest | Number of history entries to keep (0 = unlimited) | "100" |
| api.config.keepHistoryMaxAgeDays | Delete reports older than N days (0 = disabled) | "0" |
| api.config.maxUploadSizeMb | Max upload size in MB | "100" |
| api.config.goMemLimit | Go memory limit — set to ~80% of the memory limit | "768MiB" |
| api.config.swaggerEnabled | Enable Swagger UI at /swagger/index.html |
"false" |
| api.config.makeViewerEndpointsPublic | Allow unauthenticated read access to viewer endpoints | "false" |
| api.config.corsAllowedOrigins | CORS origins list (auto-computed from ingress host if empty) | [] |
| api.config.checkResultsEverySeconds | Polling interval for result processing | "NONE" |
| api.config.trustXForwardedFor | Trust X-Forwarded-For header from ingress |
"true" |
| api.kind | Workload kind — Deployment or StatefulSet |
Deployment |
| api.replicaCount | Number of API replicas | 1 |
| api.resources.requests.cpu | CPU request | 100m |
| api.resources.requests.memory | Memory request | 256Mi |
| api.resources.limits.memory | Memory limit | 1Gi |
S3 / MinIO
When api.config.storageType is set to "s3", these values configure the S3-compatible storage backend. Works with AWS S3, MinIO, and any S3-compatible service.
| Key | Description | Default |
|---|---|---|
| api.s3.endpoint | S3 endpoint URL (leave empty for AWS S3) | "" |
| api.s3.bucket | Bucket name | "" |
| api.s3.region | AWS region | "us-east-1" |
| api.s3.pathStyle | Enable path-style addressing — required for MinIO | "false" |
| api.s3.tlsInsecureSkipVerify | Skip TLS certificate verification (dev only) | "false" |
| api.s3.concurrency | Upload concurrency for multipart transfers | "10" |
| api.s3.existingSecret | Name of a pre-existing Secret with S3_ACCESS_KEY and S3_SECRET_KEY |
"" |
api.serviceAccount.annotations with the IAM role ARN and leave api.s3.existingSecret empty. See the EKS with IRSA example.
Security
Built-in role-based authentication with admin and viewer roles. All credential values are auto-generated as secure random secrets on first install and preserved across upgrades.
| Key | Description | Default |
|---|---|---|
| api.security.enabled | Enable JWT-based authentication | "true" |
| api.security.user | Admin username | "admin" |
| api.security.password | Admin password — auto-generated if empty | "" |
| api.security.viewerUser | Viewer username | "viewer" |
| api.security.viewerPassword | Viewer password — auto-generated if empty | "" |
| api.security.jwtSecretKey | HMAC signing key for JWT tokens — auto-generated if empty | "" |
| api.security.jwtAccessTokenExpires | Access token TTL in seconds | "3600" |
| api.security.jwtRefreshTokenExpires | Refresh token TTL in seconds | "2592000" |
| api.security.existingSecret | Use a pre-created Kubernetes Secret for all credentials | "" |
api.security.enabled: "false" removes all authentication. Only do this in isolated development environments — never in production.
OIDC SSO
AllureDeck supports Single Sign-On via OpenID Connect. When enabled, users can log in with any compatible identity provider (Azure AD, Keycloak, Google, Okta, and others). OIDC login can coexist with the built-in admin/viewer accounts.
| Key | Description | Default |
|---|---|---|
| api.oidc.enabled | Enable OIDC SSO | false |
| api.oidc.issuerUrl | Identity provider discovery URL (e.g. https://login.microsoftonline.com/<tenant>/v2.0) |
"" |
| api.oidc.clientId | OIDC client (application) ID | "" |
| api.oidc.clientSecret | Client secret — stored in a Kubernetes Secret | "" |
| api.oidc.redirectUrl | OAuth2 callback URL (must match IdP registration) | "" |
| api.oidc.scopes | Requested OIDC scopes (comma-separated) | "openid,profile,email" |
| api.oidc.groupsClaim | JWT claim name containing group memberships | "groups" |
| api.oidc.adminGroups | Comma-separated group IDs granted the admin role | "" |
| api.oidc.editorGroups | Comma-separated group IDs granted the editor role | "" |
| api.oidc.defaultRole | Role assigned to authenticated users not in any mapped group | "viewer" |
| api.oidc.stateCookieSecret | 32-byte AES key for encrypting OAuth2 state cookies — auto-generated if empty | "" |
For provider-specific setup instructions (Azure AD, Keycloak, Google, Okta), see the OIDC Authentication guide.
UI Configuration
Settings for the React frontend. The ui.config.apiUrl is automatically computed from the ingress host when ingress is enabled and the field is left empty.
| Key | Description | Default |
|---|---|---|
| ui.image.repository | UI container image | ghcr.io/mkutlak/alluredeck-ui |
| ui.image.tag | Image tag | "" (appVersion) |
| ui.config.apiUrl | API base URL — auto-computed from ingress host if empty | "" |
| ui.config.appTitle | Application title shown in the browser tab and header | "AllureDeck" |
| ui.replicaCount | Number of UI replicas | 1 |
| ui.resources.requests.cpu | CPU request | 50m |
| ui.resources.requests.memory | Memory request | 64Mi |
| ui.resources.limits.memory | Memory limit | 128Mi |
Persistence
AllureDeck supports two storage backends: a local PersistentVolumeClaim for on-premises or single-node deployments, and S3-compatible object storage for cloud or multi-replica setups.
Local filesystem with PVC
Use api.kind: StatefulSet with a local PVC for stable volume binding. This is the recommended approach for single-replica on-prem deployments.
api:
kind: StatefulSet
config:
storageType: "local"
persistence:
projects:
enabled: true
size: 10Gi
storageClass: "standard"
S3 / MinIO with existingSecret
For S3 storage, set storageType: "s3" and provide credentials either inline or via an existing Secret.
api:
kind: Deployment
config:
storageType: "s3"
s3:
endpoint: "https://minio.example.com"
bucket: "alluredeck"
region: "us-east-1"
pathStyle: "true"
existingSecret: "alluredeck-s3-credentials"
EKS with IRSA (no static credentials)
On EKS, annotate the ServiceAccount with the IAM role ARN. The AWS SDK picks up credentials automatically — no Secret needed.
api:
kind: Deployment
config:
storageType: "s3"
s3:
bucket: "alluredeck-reports"
region: "eu-west-1"
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/alluredeck-s3
Ingress & TLS
The chart creates a single path-based Ingress resource routing all traffic through one hostname. CORS is automatically configured when the ingress host is set.
Path routing
| Path | Backend |
|---|---|
| / | UI (React frontend) |
| /api | API (Go backend) |
| /swagger | API — Swagger UI (only when api.config.swaggerEnabled: "true") |
Ingress values
| Key | Description | Default |
|---|---|---|
| ingress.enabled | Create the Ingress resource | false |
| ingress.className | IngressClass name (e.g. nginx, traefik) |
"" |
| ingress.host | Hostname for the Ingress rule | "" |
| ingress.tls.enabled | Enable TLS on the Ingress | false |
| ingress.tls.secretName | Name of the TLS Secret (created by cert-manager or manually) | "" |
| ingress.annotations | Additional annotations for the Ingress resource | {} |
TLS with cert-manager
ingress:
enabled: true
className: nginx
host: allure.example.com
tls:
enabled: true
secretName: alluredeck-tls
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "200m"
nginx.ingress.kubernetes.io/proxy-body-size to at least twice the value of api.config.maxUploadSizeMb. The default annotation value in the example above (200m) matches a 100 MB upload limit with headroom. Omitting this annotation causes nginx to reject large report uploads with a 413 error.
Network Policy
When enabled, the chart creates Kubernetes NetworkPolicy resources that restrict ingress to the API and UI pods. Only traffic from the ingress controller namespace is allowed — pod-to-pod communication is locked down by default.
networkPolicy:
enabled: true
# Allow traffic from pods with this label in the ingress controller namespace
ingressControllerSelector:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ingressControllerSelector to match your ingress controller's namespace and pod labels. For Traefik in the traefik namespace, replace the selector values accordingly.
PostgreSQL
AllureDeck requires an external PostgreSQL 14+ instance. The chart does not deploy a database. Schema migrations run automatically via Goose on every pod startup — no manual migration steps needed.
Connection string format
postgres://username:password@hostname:5432/dbname?sslmode=require
Option A: Inline via api.config.databaseURL
Suitable for testing and development. The connection string is stored in the chart-managed Secret.
api:
config:
databaseURL: "postgres://alluredeck:secret@postgres.example.com:5432/alluredeck?sslmode=require"
Option B: existingSecret (recommended for production)
Reference a pre-existing Kubernetes Secret. The Secret must contain a databaseURL key. See the Secrets Management section for the full list of required keys.
api:
security:
existingSecret: alluredeck-credentials
CloudNativePG example
api:
security:
existingSecret: alluredeck-app # Secret created by CloudNativePG cluster
AWS RDS example
api:
config:
databaseURL: "postgres://alluredeck:secret@alluredeck.cluster-xyz.eu-west-1.rds.amazonaws.com:5432/alluredeck?sslmode=require"
Secrets Management
All credentials (admin/viewer passwords, JWT signing key, database URL) are managed in a single Kubernetes Secret. On first install the chart auto-generates secure random values for any field left empty. Existing values are preserved on helm upgrade.
For production deployments, use api.security.existingSecret to reference a Secret managed externally (Vault, AWS Secrets Manager, SOPS, etc.). The Secret must contain the following keys:
| Key | Description |
|---|---|
| adminUser | Admin username |
| adminPassword | Admin password (bcrypt-hashed by the API at startup) |
| viewerUser | Viewer username |
| viewerPassword | Viewer password |
| jwtSecretKey | HMAC signing key for JWT tokens (min 32 bytes recommended) |
| jwtAccessTokenExpires | Access token TTL in seconds |
| jwtRefreshTokenExpires | Refresh token TTL in seconds |
| databaseURL | PostgreSQL connection string |
CSI driver example with extraResources
Use extraResources to inject a SecretProviderClass (Vault, AWS Secrets Manager, Azure Key Vault) alongside the chart manifests.
api:
security:
existingSecret: alluredeck-credentials
extraResources:
- apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: alluredeck-vault
spec:
provider: vault
secretObjects:
- secretName: alluredeck-credentials
type: Opaque
data:
- objectName: adminPassword
key: adminPassword
- objectName: jwtSecretKey
key: jwtSecretKey
- objectName: databaseURL
key: databaseURL
parameters:
vaultAddress: "https://vault.example.com"
roleName: "alluredeck"
objects: |
- objectName: "adminPassword"
secretPath: "secret/alluredeck"
secretKey: "adminPassword"
- objectName: "jwtSecretKey"
secretPath: "secret/alluredeck"
secretKey: "jwtSecretKey"
- objectName: "databaseURL"
secretPath: "secret/alluredeck"
secretKey: "databaseURL"
Complete Examples
Ready-to-use values.yaml files for common deployment scenarios.
Minimal
The smallest possible configuration — only a database URL is required. Uses local storage, auto-generated credentials, no ingress.
api:
config:
databaseURL: "postgres://alluredeck:password@postgres-host:5432/alluredeck?sslmode=require"
Production with S3
Full production setup: S3 storage, custom credentials, path-based ingress with TLS, and NetworkPolicy.
api:
kind: Deployment
replicaCount: 2
config:
storageType: "s3"
logLevel: "info"
keepHistory: "true"
keepHistoryLatest: "200"
maxUploadSizeMb: "150"
goMemLimit: "768MiB"
s3:
bucket: "alluredeck-reports"
region: "eu-west-1"
existingSecret: "alluredeck-s3"
security:
existingSecret: "alluredeck-credentials"
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
ui:
replicaCount: 2
config:
appTitle: "AllureDeck"
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
ingress:
enabled: true
className: nginx
host: allure.example.com
tls:
enabled: true
secretName: alluredeck-tls
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "300m"
networkPolicy:
enabled: true
ingressControllerSelector:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
EKS with IRSA
EKS deployment using IAM Roles for Service Accounts — no static S3 credentials required. The AWS SDK picks up the role automatically via the projected token volume.
api:
kind: Deployment
config:
storageType: "s3"
goMemLimit: "768MiB"
s3:
bucket: "alluredeck-reports"
region: "eu-west-1"
# No existingSecret — credentials come from IRSA
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/alluredeck-s3-role
security:
existingSecret: "alluredeck-credentials"
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
ui:
config:
appTitle: "AllureDeck"
ingress:
enabled: true
className: alb
host: allure.example.com
tls:
enabled: true
secretName: alluredeck-tls
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-west-1:123456789012:certificate/abc-123