Middleware
Deploy Middleware, the open-source DORA metrics platform, with the official image and either bundled or external PostgreSQL. The chart measures deployment frequency, lead time for changes, change failure rate, and time to restore.
Middleware encrypts integration credentials with an RSA key pair stored on the application PVC. Back up and restore PostgreSQL and that PVC together. A database restored without its matching key pair can contain credentials the application can no longer decrypt.
Key features
- Official
middlewareeng/middleware:0.3.1image - HelmForge PostgreSQL subchart or an external PostgreSQL service
- Database migrations applied before application startup
- Persistent encryption keys at the upstream configuration path
- Real frontend, analytics, and sync port configuration
- Readiness checks for all three application listeners and embedded Redis
- Tokenless ServiceAccount, seccomp, capability drop, and NetworkPolicy defaults
- Ingress, scheduling, resource, additional volume, and extra manifest controls
Architecture
The upstream image supervises a Next.js frontend, analytics API, sync server, cron, and optional embedded datastores. This chart disables embedded PostgreSQL and enables the upstream embedded Redis process on loopback.
| Process | Default port | Exposure |
|---|---|---|
| Frontend | 3333 |
Service and optional Ingress |
| Analytics API | 9696 |
Pod-internal |
| Sync server | 9697 |
Pod-internal |
An init container runs the migrations included in the same official image and
writes the startup signal expected by the analytics process. The application
Deployment remains single-replica and uses Recreate because the key volume is
stateful and upstream does not define a multi-replica coordination model.
Middleware 0.3.1 does not expose a remote Redis password and forces TLS whenever the Redis host is not localhost. A
normal authenticated Redis Service is therefore incompatible. The chart uses the upstream-supported loopback Redis
runtime and rejects legacy redis.enabled or externalRedis.enabled overrides.
Installation
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install middleware helmforge/middleware \
--namespace middleware \
--create-namespace
Using OCI:
helm install middleware oci://ghcr.io/helmforgedev/helm/middleware \
--namespace middleware \
--create-namespace
Deployment examples
postgresql:
enabled: true
auth:
database: mhq-oss
username: middleware
persistence:
enabled: true
size: 1Gi
middleware:
timezone: America/Sao_Paulopostgresql:
enabled: false
externalDatabase:
enabled: true
host: postgres.database.svc.cluster.local
port: 5432
name: mhq-oss
user: middleware
existingSecret: middleware-database
existingSecretPasswordKey: user-password
sslMode: require
persistence:
enabled: truemiddleware:
frontendPort: 4333
analyticsPort: 10696
syncPort: 10697
service:
port: 8080The Service targets the named frontend port, so its port remains independent from the process listener.
External database credentials
Create the Secret before installation or let an external secret controller create the same target:
read -r -s -p 'External PostgreSQL password: ' MIDDLEWARE_DB_PASSWORD
printf '\n'
kubectl create namespace middleware --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret generic middleware-database \
--namespace middleware \
--from-literal=user-password="$MIDDLEWARE_DB_PASSWORD"
unset MIDDLEWARE_DB_PASSWORD
An inline externalDatabase.password is supported for development and is
rendered into a Secret rather than directly into the Deployment. It can still
be retained in Helm release storage, so use an existing Secret for production.
Production example
postgresql:
enabled: true
auth:
database: mhq-oss
username: middleware
persistence:
enabled: true
size: 5Gi
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: '4'
memory: 8Gi
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: middleware.example.com
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- middleware.example.com
secretName: middleware-tls
Configuration reference
Application
| Parameter | Default | Description |
|---|---|---|
middleware.frontendPort |
3333 |
Frontend process and container port. |
middleware.analyticsPort |
9696 |
Analytics process and container port. |
middleware.syncPort |
9697 |
Sync process and container port. |
middleware.environment |
prod |
Backend and frontend environment. |
middleware.timezone |
UTC |
IANA timezone for metric windows. |
middleware.extraEnv |
[] |
Additional environment entries. |
The internal database flag must remain "false", and the internal Redis flag
must remain "true". The chart validates both constraints.
PostgreSQL
| Parameter | Default | Description |
|---|---|---|
postgresql.enabled |
true |
Deploy bundled PostgreSQL. |
postgresql.auth.database |
mhq-oss |
Application database. |
postgresql.auth.username |
middleware |
Application role. |
externalDatabase.enabled |
false |
Use external PostgreSQL. |
externalDatabase.host |
"" |
External hostname. |
externalDatabase.port |
5432 |
External port. |
externalDatabase.existingSecret |
"" |
Password Secret. |
externalDatabase.existingSecretPasswordKey |
user-password |
Password key. |
externalDatabase.sslMode |
disable |
libpq SSL mode. |
Exactly one database mode must be active. PostgreSQL custom names, existing Secrets, custom password keys, replication primary Services, and External Secrets target names are honored by the application wiring.
Persistence and exposure
| Parameter | Default | Description |
|---|---|---|
persistence.enabled |
true |
Persist encryption keys. |
persistence.size |
1Gi |
Key PVC capacity. |
persistence.existingClaim |
"" |
Reuse a PVC. |
service.port |
80 |
Frontend Service port. |
ingress.enabled |
false |
Render Ingress. |
networkPolicy.enabled |
true |
Restrict inbound traffic to frontend. |
Security
By default the pod receives no Kubernetes API token, uses RuntimeDefault seccomp, disallows privilege escalation, and drops all capabilities. The NetworkPolicy restricts ingress to the frontend while leaving egress open for operator-selected Git and CI providers.
The official image runs as root and writes runtime artifacts under /opt and
/app; runAsNonRoot and a read-only root filesystem are therefore not safe
defaults without a different upstream image.
Operations and troubleshooting
Check migrations and application logs independently:
kubectl logs -n middleware deployment/middleware-middleware -c migrate-database
kubectl logs -n middleware deployment/middleware-middleware -c middleware --tail=200
kubectl describe pod -n middleware -l app.kubernetes.io/instance=middleware
If migration waits, verify PostgreSQL DNS, credentials, SSL mode, and network access. If migrations pass but the pod is not Ready, one of the frontend, analytics, sync, or embedded Redis listeners is unavailable.
Preserve the key PVC on every upgrade. Remove legacy Redis overrides before upgrading to this contract.