Seatmap Helm chart documentation
Overview
The Seatmap Helm chart deploys the Seatmap.pro application stack: the Editor and Booking services, the converter service when converter.enabled is true, and the PostgreSQL and Redis dependencies.
- Chart version: the chart has no version of its own. Install it from the repository tag of the Seatmap version you deploy, for example
1.74.0. - Application version: image tags default to
latest. Set every image tag to that same version, so that the chart and all components run the same version.
Prerequisites
- Kubernetes 1.26+
- Helm 3.2.0+
- PV provisioner support in the underlying infrastructure
- LoadBalancer support (for ingress)
Dependencies
The chart includes the following Bitnami dependencies:
- PostgreSQL (version 12.x.x)
- Redis (version 17.x.x)
Installation
Installation from monorepo
The Helm chart is located at deployment/helm/seatmap/ in the monorepo. Check out the tag of the
version you deploy, resolve the bitnami dependencies, and install:
git checkout ${SEATMAP_VERSION}
helm repo add bitnami https://charts.bitnami.com/bitnami
helm dependency update deployment/helm/seatmap
helm upgrade --install seatmap deployment/helm/seatmap \
--create-namespace \
--namespace seatmap \
--set converter.enabled=true \
--set global.hosts.editor=${EDITOR_HOST} \
--set global.hosts.booking=${BOOKING_HOST} \
--set-string editor.image.tag=${SEATMAP_VERSION} \
--set-string editor.frontend.image.tag=${SEATMAP_VERSION} \
--set-string booking.image.tag=${SEATMAP_VERSION} \
--set-string booking.frontend.image.tag=${SEATMAP_VERSION} \
--set-string converter.image.tag=${SEATMAP_VERSION} \
--set global.s3.bucket=${S3_BUCKET} \
--set global.s3.region=${S3_REGION} \
--set global.s3.endpoint=${S3_ENDPOINT} \
--set global.mail.host=${MAIL_HOST} \
--set global.mail.fromAddress=${MAIL_FROM} \
--set global.mail.port=${MAIL_PORT} \
--set global.mail.strategy=${MAIL_STRATEGY} \
--set-string secrets.s3.accessKey=${S3_ACCESS_KEY} \
--set-string secrets.s3.secretKey=${S3_SECRET_KEY} \
--set-string secrets.mail.username=${MAIL_USERNAME} \
--set-string secrets.mail.password=${MAIL_PASSWORD} \
--set-string secrets.google.apiKey=${GOOGLE_API_KEY} \
--set imageCredentials.registry=${REGISTRY} \
--set-string imageCredentials.username=${REGISTRY_USERNAME} \
--set-string imageCredentials.password=${REGISTRY_PASSWORD}
Local testing
Run the full local stack test using kind:
./deployment/helm/test-local.sh
Configuration
Global parameters
Host Configuration
global:
hosts:
editor: editor.test-5.seatmap.dev
booking: booking.test-5.seatmap.dev
Image Registry
imageCredentials:
registry: registry.gitlab.com
username: seatmap
password: <password>
Resource configurations
Unless you set global.resources, the Editor, Booking and converter containers run without CPU or memory requests and limits. default applies to the Editor, Booking and converter services and frontend to both frontends. Each group you set needs all four values. The values below are a starting point:
global:
resources:
default:
requests:
cpu: '500m'
memory: '2Gi'
limits:
cpu: '1000m'
memory: '3Gi'
frontend:
requests:
cpu: '100m'
memory: '192Mi'
limits:
cpu: '1000m'
memory: '512Mi'
Ingress configuration
The chart provides ingress configurations for both Editor and Booking services with separate hostnames.
Global ingress settings
global:
ingress:
className: public
proxyBodySize: '50m'
annotations:
cert-manager.io/cluster-issuer: 'letsencrypt-prod'
hosts:
editor: editor.test-5.seatmap.dev
booking: booking.test-5.seatmap.dev
Editor Ingress
The Editor service ingress is configured to handle both web and API traffic on its dedicated domain.
editor:
ingress:
enabled: true
annotations: {} # Additional service-specific annotations
apiPaths:
- /api
- /swagger-ui
- /preview
- /media
- /ws
- /webjars
- /v3
Features:
- Host:
editor.{domain}(e.g., editor.test-5.seatmap.dev) - TLS enabled with hostname-based certificate
- Default web path (/) routes to web port
- API paths route to API port
- WebSocket support enabled
- Configurable max body size
Booking Ingress
The Booking service ingress is configured on its own dedicated domain.
booking:
ingress:
enabled: true
annotations: {} # Additional service-specific annotations
apiPaths:
- /api
- /swagger-ui
- /custom
- /scalar
- /scalar.html
- /scalar-v1.html
- /scalar-v2-booking.html
- /scalar-v2-management.html
- /webjars
- /v3
- /csrf
- /oauth2
- /login
- /.well-known
Features:
- Host:
booking.{domain}(e.g., booking.test-5.seatmap.dev) - TLS enabled with hostname-based certificate
- Default web path (/) routes to web port
- API paths route to API port
- WebSocket support enabled
- Shared proxy body size configuration with Editor
Common ingress features
Both ingresses include:
- NGINX annotations for body size limits
- WebSocket support
- TLS configuration
- Implementation-specific path types for root paths
- Prefix path types for API endpoints
Component configurations
PostgreSQL
- Authentication managed through
postgresql-secret - Default database and username:
seatmap - Includes
uuid-osspextension initialization
postgresql:
enabled: true
auth:
existingSecret: 'postgresql-secret'
username: seatmap
database: seatmap
Redis
- Standalone architecture
- Authentication enabled through
redis-secret - Memory configuration:
- Max memory: 512MB
- Policy: allkeys-lru
redis:
enabled: true
architecture: standalone
auth:
enabled: true
existingSecret: 'redis-secret'
master:
persistence:
enabled: true
size: 8Gi
Container registry
All service images are hosted on the GitLab Container Registry:
| Service | Image |
|---|---|
| Editor Backend | registry.gitlab.com/seatmap.pro/seatmap/editor-service |
| Editor Frontend | registry.gitlab.com/seatmap.pro/seatmap/editor-client |
| Booking Backend | registry.gitlab.com/seatmap.pro/seatmap/booking-service |
| Booking Frontend | registry.gitlab.com/seatmap.pro/seatmap/booking-client |
| Converter | registry.gitlab.com/seatmap.pro/seatmap/converter-service |
| Knowledge Base | registry.gitlab.com/seatmap.pro/seatmap/knowledge-base |
Image tags follow semantic versioning (e.g., 1.74.0 for releases, 1.75.0-dev.18-939ed1ec for dev/stage builds).
Service components
Editor service
editor:
image:
repository: registry.gitlab.com/seatmap.pro/seatmap/editor-service
tag: '1.74.0'
frontend:
image:
repository: registry.gitlab.com/seatmap.pro/seatmap/editor-client
tag: '1.74.0'
Key configurations:
- HikariCP connection pool settings
- Token expiration settings
- SSO integration support
- API paths for ingress
Booking service
booking:
image:
repository: registry.gitlab.com/seatmap.pro/seatmap/booking-service
tag: '1.74.0'
frontend:
image:
repository: registry.gitlab.com/seatmap.pro/seatmap/booking-client
tag: '1.74.0'
Features:
- JPA/Hibernate configuration
- Connection pool settings
- OAuth2 support
- Actuator endpoints
Converter service
converter:
image:
repository: registry.gitlab.com/seatmap.pro/seatmap/converter-service
tag: '1.74.0'
converter:
config:
async:
enabled: true
cpuClaimDelayMs: 5000
rateLimit:
jobsMax: 5000
gpu:
enabled: false
Behaviour:
- The chart deploys the converter only when
converter.enabledistrue, as in the install command above. - Conversions are queued in the release’s Redis while
converter.config.async.enabledistrue(the default). Set it tofalseto render inside the request without Redis. converter.gpu.enabledadds a GPU pod variant that claims queued jobs first; the CPU pods pick up whatever it does not take.- With
converter.enabledset, the chart generates a shared secret in<release>-converterand wires it into editor-service. A deployment that runs the converter in a separate release leavesconverter.enabledoff, pointseditor.converterat that converter’s URL, and sets the samesecrets.converter.apiKeyon both sides before upgrading either.
Limitations:
- Max content length: 32MB
- Max image dimensions: 15000x15000 pixels
- S3 storage integration
External service configuration
S3 storage
global:
s3:
bucket: 'seatmap-storage'
region: 'us-east-1'
endpoint: 'https://s3.amazonaws.com'
Mail server
global:
mail:
host: 'smtp.example.com'
port: 587
strategy: 'SMTP_TLS'
fromAddress: 'seatmap@example.com'
Password reset email stays off until host and fromAddress are set. strategy takes SMTPS for implicit TLS, usually on port 465, SMTP_TLS for STARTTLS, usually on port 587, or SMTP, which sends unencrypted when the server does not offer STARTTLS and suits only a trusted network; the chart refuses any other value. Left empty, the editor uses SMTPS on port 465 and SMTP_TLS on any other port. Leave secrets.mail.username and secrets.mail.password empty when the mail server accepts mail without signing in.
Security considerations
JWT signing keys
The editor service signs its tokens with an RSA keypair held in the {release}-rsa Secret. A pre-install and pre-upgrade hook creates it and never overwrites an existing one, so the keypair survives every upgrade and issued tokens keep verifying.
The hook migrates existing key material into the Secret verbatim on upgrade – no token is invalidated and no user is signed out. If the existing key data is empty the hook refuses to migrate and fails the upgrade, rather than silently generating a new keypair and invalidating every live session.
A new keypair is generated only on a fresh install, where there is nothing to carry over.
Once the upgrade succeeds you can delete the old ConfigMap. Nothing reads it any more.
kubectl delete configmap {release}-rsa -n {namespace}
Secrets management
The following secrets must be provided:
- PostgreSQL credentials
- Redis password
- S3 access credentials
- Mail server credentials, when the mail server requires sign-in
- Google API key
- Converter shared secret (generated by the chart when
converter.enabledistrue, orsecrets.converter.apiKeyfor a split release)
Network security
- TLS termination through ingress
- cert-manager integration for automated certificate management
- Separate API and web ports for services
Scaling
Horizontal pod autoscaling
Each service has its own autoscaler switch, off by default: editor.hpa.enabled, booking.hpa.enabled and converter.hpa.enabled. These targets apply to all three:
global:
hpa:
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
The autoscalers measure utilization against the containers’ requests, so set global.resources before you enable them.
Replica ranges (*.hpa.minReplicas and *.hpa.maxReplicas):
- Editor: 2-6 replicas
- Booking: 2-6 replicas
- Converter: 1-4 replicas
Monitoring and metrics
- Actuator endpoints enabled for Spring Boot services
- Redis metrics disabled by default
- Custom metrics endpoints configured for editor and booking services
Troubleshooting
Common issues
-
Image pull errors
- Verify registry credentials
- Check image tags exist
-
Database connection issues
- Verify PostgreSQL secret exists
- Check connection pool settings
-
Storage issues
- Validate S3 credentials and bucket accessibility
- Check storage quotas and limits
Debugging
-
Access logs through:
kubectl logs -f deployment/seatmap-<component> -
Check service status:
kubectl get pods -l app.kubernetes.io/instance=seatmap
Configuration variables reference
Global variables
| Parameter | Description | Default Value |
|---|---|---|
global.hosts.editor |
Editor hostname | editor.seatmap.dev |
global.hosts.booking |
Booking hostname | booking.seatmap.dev |
global.hosts.media |
Converter hostname, used when converter.enabled and converter.ingress.enabled are true |
media.seatmap.dev |
global.resources.default.requests.cpu |
Default CPU request | unset |
global.resources.default.requests.memory |
Default memory request | unset |
global.resources.default.limits.cpu |
Default CPU limit | unset |
global.resources.default.limits.memory |
Default memory limit | unset |
global.resources.frontend.requests.cpu |
Frontend CPU request | unset |
global.resources.frontend.requests.memory |
Frontend memory request | unset |
global.resources.frontend.limits.cpu |
Frontend CPU limit | unset |
global.resources.frontend.limits.memory |
Frontend memory limit | unset |
global.bookingSessions.enabled |
Serve the booking-session endpoints | true |
Instance variables
| Parameter | Description | Default Value |
|---|---|---|
instance.environment |
Declared deployment environment: production, staging, development or unspecified. Validated at render time |
unset |
instance.heartbeatEnabled |
Periodic diagnostic check-in from editor-service | true |
PostgreSQL variables
| Parameter | Description | Default Value |
|---|---|---|
postgresql.enabled |
Enable PostgreSQL deployment | true |
postgresql.auth.existingSecret |
Secret name for auth | postgresql-secret |
postgresql.auth.username |
PostgreSQL username | seatmap |
postgresql.auth.database |
PostgreSQL database name | seatmap |
global.postgresql.service.port |
PostgreSQL service port | 5432 |
Redis variables
| Parameter | Description | Default Value |
|---|---|---|
redis.enabled |
Enable Redis deployment | true |
redis.architecture |
Redis architecture type | standalone |
redis.auth.enabled |
Enable Redis authentication | true |
redis.auth.existingSecret |
Secret name for auth | redis-secret |
redis.master.persistence.enabled |
Enable persistence | true |
redis.master.persistence.size |
Persistence size | 8Gi |
global.redis.port |
Redis service port | 6379 |
Editor service variables
| Parameter | Description | Default Value |
|---|---|---|
editor.image.repository |
Editor service image repository | registry.gitlab.com/seatmap.pro/seatmap/editor-service |
editor.image.tag |
Editor service image tag | latest |
editor.frontend.image.repository |
Editor frontend image repository | registry.gitlab.com/seatmap.pro/seatmap/editor-client |
editor.frontend.image.tag |
Editor frontend image tag | latest |
editor.config.initial.delay |
Initial delay | 5000 |
editor.config.spring.datasource.hikari.connectionTimeout |
Database connection timeout | 60000 |
editor.config.spring.datasource.hikari.maximumPoolSize |
Database connection pool size | 20 |
editor.config.spring.flyway.outOfOrder |
Allow out-of-order Flyway migrations | false |
editor.hpa.minReplicas |
Minimum replicas for HPA | 2 |
editor.hpa.maxReplicas |
Maximum replicas for HPA | 6 |
Booking service variables
| Parameter | Description | Default Value |
|---|---|---|
booking.image.repository |
Booking service image repository | registry.gitlab.com/seatmap.pro/seatmap/booking-service |
booking.image.tag |
Booking service image tag | latest |
booking.frontend.image.repository |
Booking frontend image repository | registry.gitlab.com/seatmap.pro/seatmap/booking-client |
booking.frontend.image.tag |
Booking frontend image tag | latest |
booking.config.spring.profiles.include |
Spring active profiles | prod |
booking.config.spring.jpa.generateDdl |
Enable DDL generation | true |
booking.config.spring.jpa.hibernate.ddlAuto |
Hibernate DDL auto | update |
booking.config.seatmap.watermark.disabled |
Disable booking widget branding | false |
booking.hpa.minReplicas |
Minimum replicas for HPA | 2 |
booking.hpa.maxReplicas |
Maximum replicas for HPA | 6 |
Converter service variables
| Parameter | Description | Default Value |
|---|---|---|
converter.enabled |
Deploy the Converter service | false |
converter.ingress.enabled |
Expose the Converter service on global.hosts.media |
false |
converter.image.repository |
Converter service image repository | registry.gitlab.com/seatmap.pro/seatmap/converter-service |
converter.image.tag |
Converter service image tag | latest |
converter.config.max.contentLength |
Maximum content length | 33554432 |
converter.config.max.image.width |
Maximum image width | 15000 |
converter.config.max.image.height |
Maximum image height | 15000 |
converter.hpa.minReplicas |
Minimum replicas for HPA | 1 |
converter.hpa.maxReplicas |
Maximum replicas for HPA | 4 |
converter.gpu.enabled |
Run an additional GPU-accelerated converter deployment alongside the software one | false |
converter.gpu.renderGroupId |
Host render group id granted to the GPU converter pod | 109 |
converter.config.async.enabled |
Queue conversions in the release’s Redis; false renders inside the request |
true |
converter.config.async.cpuClaimDelayMs |
Head start a GPU pod gets before a CPU pod claims a queued job; passed as 0 when no GPU pod is deployed |
5000 |
converter.config.rateLimit.jobsMax |
Requests per minute per IP allowed on GET /jobs/{id} |
5000 |
External service variables
| Parameter | Description | Default Value |
|---|---|---|
secrets.s3.accessKey |
S3 access key | secrets.s3.accessKey |
secrets.s3.secretKey |
S3 secret key | secrets.s3.secretKey |
secrets.mail.username |
Mail server username | "" |
secrets.mail.password |
Mail server password | "" |
secrets.google.apiKey |
Google API key | secrets.google.apiKey |
secrets.google.serverApiKey |
Server-side Google API key for address search. Falls back to secrets.google.apiKey when empty |
"" |
secrets.converter.apiKey |
Converter bearer token. Empty means generated per release and kept across upgrades; set it when editor-service and the converter are separate releases | "" |
global.s3.bucket |
S3 bucket name | seatmap-storage |
global.s3.region |
S3 region | us-east-1 |
global.s3.endpoint |
S3 endpoint | https://s3.amazonaws.com |
global.mail.host |
Mail server host | "" |
global.mail.port |
Mail server port | 587 |
global.mail.strategy |
Mail connection security: SMTPS, SMTP_TLS or SMTP |
"" |
global.mail.fromAddress |
Mail from address | "" |
Support and maintenance
- Regular updates through version tags
- Configuration changes through Helm upgrade
- Persistent storage management for PostgreSQL and Redis