Stack Examples
These examples show how to combine multiple HelmForge charts into production-ready stacks. Each stack uses shared S3 credentials for backup and production-grade defaults.
All examples assume:
- A running Kubernetes cluster (v1.26+)
- Helm 3.x installed
- The HelmForge repository added:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
Blog Stack
WordPress + MySQL + S3 Backup
A complete blog platform with a bundled database and daily backups to S3-compatible storage.
Install
helm install blog helmforge/wordpress -f blog-values.yaml
blog-values.yaml
# WordPress application
wordpress:
siteTitle: 'My Blog'
adminUser: admin
adminEmail: [email protected]
# Bundled MySQL database
mysql:
enabled: true
architecture: standalone
auth:
database: wordpress
username: wordpress
existingSecret: blog-mysql-credentials
primary:
persistence:
enabled: true
size: 10Gi
# WordPress file persistence
persistence:
enabled: true
size: 10Gi
# Daily S3 backup (database dump + uploads archive)
backup:
enabled: true
schedule: '0 3 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-backups
prefix: blog
existingSecret: blog-s3-credentials
# Public ingress with TLS
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: blog.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: blog-tls
hosts:
- blog.example.com
# Production defaults
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
Secrets
Create the required secrets before installing:
# MySQL credentials
kubectl create secret generic blog-mysql-credentials \
--from-literal=password='<db-password>' \
--from-literal=root-password='<root-password>'
# S3 backup credentials
kubectl create secret generic blog-s3-credentials \
--from-literal=access-key='<aws-access-key>' \
--from-literal=secret-key='<aws-secret-key>'
What you get
- WordPress accessible at
https://blog.example.com - MySQL database with 10Gi persistent storage
- Daily database dump uploaded to S3 at 03:00 UTC
- TLS certificate via cert-manager
SaaS Automation Stack
n8n + PostgreSQL + Redis (Queue Mode) + S3 Backup
A horizontally scalable workflow automation platform with PostgreSQL for persistence, Redis for job queues, and automated backups.
Install
helm install automation helmforge/n8n -f automation-values.yaml
automation-values.yaml
# n8n application
n8n:
logLevel: info
# Queue mode with Redis for horizontal scaling
queue:
enabled: true
workers: 2
concurrency: 10
# Bundled PostgreSQL database
postgresql:
enabled: true
architecture: standalone
auth:
database: n8n
username: n8n
existingSecret: automation-pg-credentials
primary:
persistence:
enabled: true
size: 20Gi
# Bundled Redis for queue
redis:
enabled: true
architecture: standalone
auth:
existingSecret: automation-redis-credentials
primary:
persistence:
enabled: true
size: 1Gi
# Daily S3 backup (PostgreSQL dump)
backup:
enabled: true
schedule: '0 2 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-backups
prefix: automation
existingSecret: automation-s3-credentials
# Internal ingress (not public-facing)
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: n8n.internal.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: automation-tls
hosts:
- n8n.internal.example.com
# Production resources
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
Secrets
# PostgreSQL credentials
kubectl create secret generic automation-pg-credentials \
--from-literal=password='<pg-password>' \
--from-literal=root-password='<pg-root-password>'
# Redis credentials
kubectl create secret generic automation-redis-credentials \
--from-literal=password='<redis-password>'
# S3 backup credentials
kubectl create secret generic automation-s3-credentials \
--from-literal=access-key='<aws-access-key>' \
--from-literal=secret-key='<aws-secret-key>'
What you get
- n8n editor at
https://n8n.internal.example.com - 2 queue workers processing workflows in parallel
- PostgreSQL with 20Gi persistent storage
- Redis for reliable job queue distribution
- Daily PostgreSQL dump uploaded to S3 at 02:00 UTC
Self-Hosted Security Stack
Vaultwarden + Keycloak + PostgreSQL + S3 Backup
A self-hosted password manager with centralized SSO authentication and per-service database backups. Each application gets its own PostgreSQL instance for isolation.
Install
This stack uses three separate releases. Install in order:
# 1. PostgreSQL for Keycloak
helm install keycloak-db helmforge/postgresql -f keycloak-db-values.yaml
# 2. Keycloak (SSO provider)
helm install keycloak helmforge/keycloak -f keycloak-values.yaml
# 3. Vaultwarden (password manager)
helm install vaultwarden helmforge/vaultwarden -f vaultwarden-values.yaml
keycloak-db-values.yaml
architecture: standalone
auth:
database: keycloak
username: keycloak
existingSecret: keycloak-db-credentials
primary:
persistence:
enabled: true
size: 10Gi
backup:
enabled: true
schedule: '0 4 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-backups
prefix: keycloak-db
existingSecret: infra-s3-credentials
keycloak-values.yaml
# External PostgreSQL (deployed above)
postgresql:
enabled: false
database:
mode: external
external:
host: keycloak-db-postgresql
port: 5432
name: keycloak
username: keycloak
existingSecret: keycloak-db-credentials
existingSecretPasswordKey: password
# Keycloak production settings
keycloak:
adminUser: admin
adminPassword: ''
existingSecret: keycloak-admin-credentials
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: sso.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: keycloak-tls
hosts:
- sso.example.com
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
vaultwarden-values.yaml
# Vaultwarden core settings
domain: 'https://vault.example.com'
vaultwarden:
signupsAllowed: false
invitationsAllowed: true
admin:
existingSecret: vaultwarden-admin-credentials
existingSecretTokenKey: admin-token
# Bundled PostgreSQL for Vaultwarden
postgresql:
enabled: true
architecture: standalone
auth:
database: vaultwarden
username: vaultwarden
existingSecret: vaultwarden-pg-credentials
# Data persistence
data:
persistence:
enabled: true
size: 5Gi
# Daily S3 backup (PostgreSQL dump + data directory)
backup:
enabled: true
schedule: '0 5 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-backups
prefix: vaultwarden
existingSecret: infra-s3-credentials
# SMTP for email notifications
smtp:
enabled: true
host: smtp.example.com
port: 587
from: [email protected]
fromName: Vaultwarden
security: starttls
existingSecret: vaultwarden-smtp-credentials
existingSecretPasswordKey: smtp-password
ingress:
enabled: true
ingressClassName: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: vault.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: vaultwarden-tls
hosts:
- vault.example.com
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 256Mi
Secrets
# Shared S3 credentials (reused across stack)
kubectl create secret generic infra-s3-credentials \
--from-literal=access-key='<aws-access-key>' \
--from-literal=secret-key='<aws-secret-key>'
# Keycloak database
kubectl create secret generic keycloak-db-credentials \
--from-literal=password='<keycloak-db-password>' \
--from-literal=root-password='<pg-root-password>'
# Keycloak admin
kubectl create secret generic keycloak-admin-credentials \
--from-literal=admin-password='<keycloak-admin-password>'
# Vaultwarden database
kubectl create secret generic vaultwarden-pg-credentials \
--from-literal=password='<vaultwarden-db-password>' \
--from-literal=root-password='<pg-root-password>'
# Vaultwarden admin token (Argon2 hash recommended)
kubectl create secret generic vaultwarden-admin-credentials \
--from-literal=admin-token='<argon2-phc-string>'
# Vaultwarden SMTP
kubectl create secret generic vaultwarden-smtp-credentials \
--from-literal=smtp-password='<smtp-password>'
What you get
- Keycloak SSO at
https://sso.example.com - Vaultwarden at
https://vault.example.com - Isolated PostgreSQL instances per service
- Staggered daily backups to S3 (Keycloak DB at 04:00, Vaultwarden at 05:00)
- SMTP notifications for Vaultwarden events
- All secrets managed via Kubernetes Secrets with
existingSecretreferences
Tips for Production Stacks
- Stagger backup schedules — avoid running all backup CronJobs at the same time to reduce I/O spikes
- Use
existingSecreteverywhere — never put passwords in values files that get committed to git - Share S3 credentials — use one secret with different
prefixvalues per service to keep backups organized in the same bucket - Set resource requests and limits — prevents noisy-neighbor issues in shared clusters
- Use cert-manager — automates TLS certificate issuance and renewal across all ingresses