Skip to content

Apache Answer

Deploy Apache Answer on Kubernetes — an open-source Q&A platform for teams and communities. Supports SQLite (zero-configuration default), PostgreSQL, and MySQL, with automatic unattended installation and database-aware scheduled backups.

SQLite is the default — no database configuration required for small teams

With the default configuration (database.mode: auto and no subchart enabled), Answer uses SQLite stored in the /data PVC. No external database is needed for teams under a few hundred users. Migrate to PostgreSQL or MySQL when you need concurrent write performance or replication.

Key Features

  • Three database backends — SQLite (default), PostgreSQL, MySQL
  • Auto-detection — mode is inferred from which subchart or external host is configured
  • Auto-install — unattended first-boot setup via environment variables (autoInstall: true)
  • Database-aware backuptar for SQLite, pg_dump for PostgreSQL, mysqldump for MySQL
  • Admin credentialsexistingSecret for GitOps-safe secret management

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install answer helmforge/answer -f values.yaml

OCI registry:

helm install answer oci://ghcr.io/helmforgedev/helm/answer -f values.yaml

Deployment Examples

# values.yaml — Apache Answer with SQLite (zero database configuration)
answer:
  siteName: 'My Q&A'
  siteUrl: 'https://qa.example.com'
  language: en-US
  autoInstall: true

admin:
  name: admin
  email: admin@example.com
  existingSecret: answer-admin-credentials # key: admin-password
  existingSecretPasswordKey: admin-password

persistence:
  enabled: true
  size: 10Gi # covers both SQLite file (/data/answer.db) and uploads

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: qa.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: answer-tls
      hosts:
        - qa.example.com
# values.yaml — Apache Answer with bundled PostgreSQL
answer:
  siteName: 'My Q&A'
  siteUrl: 'https://qa.example.com'
  autoInstall: true

admin:
  name: admin
  email: admin@example.com
  password: 'change-me'

postgresql:
  enabled: true
  auth:
    database: answer
    username: answer
    password: 'strong-db-password'
  primary:
    persistence:
      enabled: true
      size: 20Gi

persistence:
  enabled: true
  size: 10Gi # uploads only (SQLite not used when PostgreSQL is active)

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: qa.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Apache Answer with bundled MySQL
answer:
  siteName: 'My Q&A'
  siteUrl: 'https://qa.example.com'
  autoInstall: true

admin:
  name: admin
  email: admin@example.com
  password: 'change-me'

mysql:
  enabled: true
  auth:
    database: answer
    username: answer
    password: 'strong-db-password'
    rootPassword: 'strong-root-password'
  primary:
    persistence:
      enabled: true
      size: 20Gi

persistence:
  enabled: true
  size: 10Gi

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: qa.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Apache Answer with external PostgreSQL
answer:
  siteName: 'My Q&A'
  siteUrl: 'https://qa.example.com'
  autoInstall: true

admin:
  existingSecret: answer-admin-credentials

postgresql:
  enabled: false

database:
  mode: external
  external:
    vendor: postgres # or: mysql
    host: postgres.database.svc.cluster.local
    port: '5432'
    name: answer
    username: answer
    existingSecret: answer-db-credentials
    existingSecretPasswordKey: database-password

persistence:
  enabled: true
  size: 10Gi

backup:
  enabled: true
  schedule: '0 3 * * *'
  s3:
    endpoint: https://s3.amazonaws.com
    bucket: answer-backups
    existingSecret: answer-s3-credentials

Configuration Reference

Core

ParameterTypeDefaultDescription
nameOverridestring""Override the chart name.
fullnameOverridestring""Override the full release name.
commonLabelsobject{}Extra labels added to all resources.

Image

ParameterTypeDefaultDescription
image.repositorystringdocker.io/apache/answerApache Answer container image.
image.tagstring"2.0.0"Image tag.
image.pullPolicystringIfNotPresentImage pull policy.

Answer Configuration

ParameterTypeDefaultDescription
answer.siteUrlstring""Full public URL. Auto-detected from Ingress if empty.
answer.siteNamestringApache AnswerSite name shown in browser tab and header.
answer.languagestringen-USDefault UI language.
answer.contactEmailstringadmin@example.comContact email shown in the site footer.
answer.autoInstallbooleantrueEnable unattended first-boot setup using admin credentials from values.
answer.logLevelstringINFOLog level: DEBUG, INFO, WARN, ERROR.
answer.extraEnvarray[]Extra environment variables for the container.

Admin Credentials

ParameterTypeDefaultDescription
admin.namestringadminAdmin username for initial setup.
admin.passwordstring""Admin password. Auto-generated if empty.
admin.emailstringadmin@example.comAdmin email address.
admin.existingSecretstring""Existing secret with admin credentials.
admin.existingSecretPasswordKeystringadmin-passwordKey inside the existing secret for the password.

Database

Auto-detection precedence (database.mode: auto):

PriorityConditionResult
1database.external.host or external.existingSecret setExternal DB
2postgresql.enabled: truePostgreSQL subchart
3mysql.enabled: trueMySQL subchart
4None of the aboveSQLite (default)
ParameterTypeDefaultDescription
database.modestringautoDatabase mode: auto, sqlite, external, postgresql, mysql.
database.sqlite.filestring/data/answer.dbSQLite file path inside the data volume.
database.external.vendorstringpostgresExternal DB vendor: postgres or mysql.
database.external.hoststring""External database hostname.
database.external.portstring""External database port. Auto-detected from vendor if empty.
database.external.namestringanswerDatabase name.
database.external.usernamestringanswerDatabase username.
database.external.existingSecretstring""Existing secret with database password.
database.external.existingSecretPasswordKeystringdatabase-passwordKey for the password in the existing secret.

Subcharts

ParameterTypeDefaultDescription
postgresql.enabledbooleanfalseDeploy the bundled PostgreSQL subchart.
postgresql.auth.databasestringanswerDatabase name.
postgresql.auth.passwordstring""Password. Auto-generated if empty.
postgresql.primary.persistence.sizestring8GiPVC size.
mysql.enabledbooleanfalseDeploy the bundled MySQL subchart.
mysql.auth.databasestringanswerDatabase name.
mysql.auth.passwordstring""Password. Auto-generated if empty.
mysql.primary.persistence.sizestring8GiPVC size.

Persistence

ParameterTypeDefaultDescription
persistence.enabledbooleantrueEnable PVC for /data (SQLite DB file + uploads).
persistence.sizestring5GiPVC size. Increase if using SQLite as the primary database.
persistence.storageClassstring""StorageClass for the PVC.
persistence.accessModestringReadWriteOncePVC access mode.
persistence.existingClaimstring""Use an existing PVC.

Backup

Backup mode is automatically selected based on the active database vendor

The backup CronJob detects which database is in use and runs the appropriate tool:

  • SQLitetar archive of the full /data directory (Alpine image)
  • PostgreSQLpg_dump (PostgreSQL Alpine image)
  • MySQLmysqldump (MySQL image)

Only the images needed for the active database vendor are used.

ParameterTypeDefaultDescription
backup.enabledbooleanfalseEnable scheduled S3 backup CronJob.
backup.schedulestring"0 3 * * *"Cron schedule.
backup.archivePrefixstringanswerPrefix for backup archive filenames.
backup.images.sqlitestringalpine:3.22Image for SQLite backup (tar).
backup.images.postgresqlstringpostgres:18.3-alpineImage for PostgreSQL backup (pg_dump).
backup.images.mysqlstringmysql:8.4Image for MySQL backup (mysqldump).
backup.images.uploaderstringhelmforge/mc:1.0.0Image for S3 upload (MinIO client).
backup.s3.endpointstring""S3-compatible endpoint URL.
backup.s3.bucketstring""Target bucket name.
backup.s3.existingSecretstring""Existing secret with S3 credentials.
backup.database.postgresDumpArgsstring""Extra arguments for pg_dump.
backup.database.mysqlDumpArgsstring--single-transaction ...Extra arguments for mysqldump.

Service and Ingress

ParameterTypeDefaultDescription
service.typestringClusterIPService type.
service.portinteger80Service port.
ingress.enabledbooleanfalseEnable an Ingress resource.
ingress.ingressClassNamestring""Ingress class name.
ingress.annotationsobject{}Ingress annotations.
ingress.hostsarray[]Host and path rules.
ingress.tlsarray[]TLS configuration.

Probes

All probes use /healthz as the HTTP path.

ParameterTypeDefaultDescription
startupProbe.enabledbooleantrueEnable startup probe.
startupProbe.failureThresholdinteger30Startup probe failure threshold.
livenessProbe.enabledbooleantrueEnable liveness probe.
readinessProbe.enabledbooleantrueEnable readiness probe.

Resources and Scheduling

ParameterTypeDefaultDescription
resourcesobject{}CPU and memory requests/limits.
terminationGracePeriodSecondsinteger30Termination grace period.
nodeSelectorobject{}Node selector for scheduling.
tolerationsarray[]Tolerations for scheduling.
extraVolumesarray[]Extra volumes.
extraVolumeMountsarray[]Extra volume mounts.
extraManifestsarray[]Extra Kubernetes manifests.

More Information