Skip to main content

Installing ister with Helm

This chapter explains how the ister Helm chart works and how to install it. The chart deploys the full ister media server: the API server, the web player, and — unless you bring your own — PostgreSQL, RabbitMQ and Typesense.

What the chart deploys​

ComponentWhat it isBundled by default?
serverThe Spring Boot backend (ghcr.io/ister-app/server)always
websiteThe web player (ghcr.io/ister-app/player)always
PostgreSQLThe databaseyes (database.mode: internal)
RabbitMQThe message broker (official image, single node)yes (rabbitmq.enabled: true)
TypesenseThe search engineyes (typesense.enabled: true)
FlywayDatabase migrations (ghcr.io/ister-app/migrations)runs as an init container

The defaults deploy a self-contained ister with no ingress and no media volumes — enough to try it out, not a production setup.

Prerequisites​

  • A Kubernetes cluster and Helm 3.
  • A TMDB API key for movie/show metadata.
  • An OIDC issuer (for example Keycloak) — ister does not manage users itself. It has to be set up a particular way; see Setting up the identity provider.
  • For database.mode: cnpg: the CloudNativePG operator.
  • For ingress with TLS: an ingress controller and, optionally, cert-manager.

Installing​

The chart is published as an OCI artifact:

helm install ister oci://ghcr.io/ister-app/charts/ister \
--namespace ister --create-namespace \
--set server.tmdbApiKey=<your-key> \
--set server.oidc.url=https://keycloak.example.com/realms/auth

For anything beyond a first try, start from values-production.example.yaml in the chart repository and install with -f. Pin a chart version with --version; a GitHub Release exists for every chart version with release notes listing the exact image versions it deploys.

Bundled or external datastores​

Everything backing the server can either be deployed by the chart or pointed at an existing service. Whatever you choose, the templates downstream never notice the difference — that is the chart's central design rule.

PostgreSQL — database.mode​

  • internal — a single postgres Deployment + PVC. Development only: one instance, no backups.
  • cnpg — a CloudNativePG Cluster (3 instances by default, anti-affinity, optional Barman Cloud backups to S3 under database.cnpg.backup). Requires the CNPG operator.
  • external — an existing PostgreSQL, configured under database.external.

All three modes converge on one Secret with the keys host, port, dbname, user, password — the shape CNPG generates for its <cluster>-app Secret, which the other two modes hand-write to match. If you bring your own Secret (existingSecret), it must have exactly those keys; for a CNPG cluster managed outside this chart, its <cluster>-app Secret already does.

RabbitMQ — rabbitmq.enabled​

true deploys a single-node RabbitMQ StatefulSet on the official rabbitmq image (ister only uses the broker for pass-through work, so nothing needs clustering); the password and Erlang cookie are generated once, or come from rabbitmq.auth.existingSecret (keys rabbitmq-password, rabbitmq-erlang-cookie). false uses the externalRabbitmq block instead — its existingSecret needs the key rabbitmq-password.

Upgrading from a chart before 1.0, which shipped the Bitnami subchart: the old StatefulSet, Service and PVC named <release>-rabbitmq are not adopted. Delete them (the queues hold pass-through work only) before upgrading, or run the upgrade and delete the leftover PVC afterwards; the server reconnects to the new broker on its own.

Typesense — typesense.enabled​

true deploys Typesense with its own PVC. false uses typesense.external — its existingSecret needs the key api-key.

Secrets and passwords​

  • Nothing secret belongs in a values file. Every credential has an existingSecret escape hatch; use it (or a secret manager) anywhere that matters.
  • Generated passwords survive upgrades. When you let the chart generate a password, it looks up the live Secret on upgrade and keeps the existing value — otherwise every helm upgrade would lock the server out of its own database. This is also why helm template output differs from what helm install actually applies.
  • ...but not under GitOps. Argo CD, Flux and helm template | kubectl apply render without access to the cluster, so that lookup finds nothing and every sync generates a new password. PostgreSQL keeps the first one in its volume and the server then fails with password authentication failed; everything else restarts on every commit through the checksum/secrets annotation. Deploying that way means setting database.internal.password, rabbitmq.auth.password and typesense.apiKey explicitly, or pointing the matching existingSecret at a Secret you manage.
  • Rotating a Secret restarts the server. All credentials are hashed into a checksum/secrets pod annotation, so a changed Secret rolls the Deployment.

Database migrations​

Flyway runs as an init container on the server pod (preceded by a wait-for-db container), so the server can never start against an unmigrated schema. It is not a Helm hook on purpose: with a bundled database, a pre-install hook would wait for a database that Helm has not created yet. The migrations image publishes the same version as the server, so flyway.image.tag stays empty and follows the server version automatically.

Media libraries and volumes​

Two value lists connect the server to your media:

  • server.libraries — the libraries ister scans; each has a name and a type (SHOW, MOVIE, MUSIC, BOOK, PODCAST, COMIC).
  • server.mediaVolumes — the volumes mounted into the server pod, each backed by exactly one of hostPath, existingClaim or nfs, and linked to a library via library (omit it for a mount-only volume). No trailing slash on mountPath — the scanner skips the tree if there is one.

Two more storage knobs matter:

  • cache — a PVC for the server's cache directory (transcodes, images). It is ReadWriteOnce by default, which is why server.replicaCount must stay at 1 — the chart refuses to render more replicas unless you switch to ReadWriteMany.
  • server.tmp — scratch space for transcoding. Disable it when mountPath falls inside one of your media volumes, or the dedicated volume shadows that path.

Server settings — server.config​

Everything the server reads from its own configuration files can be set under server.config, a tree of Spring properties the chart renders into a ConfigMap and mounts into every server pod (the main server and all helpers) as /config/application.yaml. The block in values.yaml lists the tunables with the server's defaults — cache cleanup, continue watching, upload limits, RabbitMQ listener tuning, the Hikari pool, transcode concurrency — so the values reference below doubles as the list of what you can change. Any other Spring or app.ister.* property may be added (see the server docs, chapter Configuration); a change rolls the pods through a checksum/config annotation.

Precedence, from low to high: the server's built-in defaults, then server.config, then environment variables. The chart keeps everything it derives from other values as env vars (database, broker, search, OIDC, server name and URL, cache and tmp paths, libraries and directories, helper disks, hardware acceleration), so those keys have no effect in server.config; secrets never go there either. server.extraEnv still overrides a key set in server.config, but only under its canonical Spring name (APP_ISTER_SERVER_CACHE_CLEANUP_CRON): the short aliases the server's own defaults accept (CACHE_CLEANUP_CRON, HLS_MAX_CONCURRENT_FILES, …) are shadowed as soon as server.config sets that key. Helpers read the same ConfigMap; a per-helper difference goes in helpers[].extraEnv. If you set SPRING_CONFIG_ADDITIONAL_LOCATION yourself, keep file:/config/ in the comma-separated list.

The defaults in the block are those of the server release the chart pins (server.image.tag), and the chart keeps them that way: when a server release changes a default, the next chart release carries the new value, and its release notes list every server.config key that was added, changed or removed, plus any new server setting the chart does not mirror yet. A value you set yourself in your own values file is never touched by that.

One limit: the server is a GraalVM native image, and Spring decides which beans exist when that image is built. A property that only changes a value (a cron, a pool size, a log level, health details) works; one that would create a bean that is not in the image does not — the Actuator exposure list can be narrowed but not extended, and enabled-style feature flags only work where the server checks them at runtime.

Exposing it: Ingress or Gateway API​

Both publish the player at / and the API at server.contextPath (default /api) on one hostname; pick one.

  • Ingress — ingress.enabled: true with ingress.host. ingress.className is empty by default (the cluster's default IngressClass); set it when you run several controllers. TLS via cert-manager when ingress.tls.certIssuer is set.
  • Gateway API — gateway.enabled: true with gateway.hostnames and gateway.parentRefs (the Gateway and listener to attach to; the Gateway itself is yours and must allow routes from the chart's namespace). Works with Envoy Gateway, Cilium, Istio, Traefik's Gateway provider and the like.

Whatever fronts ister has to allow three things most proxies limit by default: unbounded request bodies (helper nodes upload whole HLS segments and subtitle files), responses that run for minutes to hours (HLS playback, a helper node reading a multi-GB source), and websocket upgrades on /api/graphql. ingress.controller (nginx | traefik | haproxy) renders the matching annotations from ingress.proxy; the HTTPRoute sets timeouts.request: 0s on the /api rule (gateway.apiTimeouts). Traefik needs nothing per Ingress, but its read timeouts are entrypoint settings (entryPoints.<name>.transport.respondingTimeouts).

/.well-known/ister, the document clients fetch first (instance name, OIDC issuer, API URL), is served by the website pod itself (website.wellKnown, default on), so it works behind any controller, a NodePort or a port-forward. The older ingress-nginx snippet (ingress.wellKnown) is still there for setups that rely on it.

The Services accept the usual knobs (server.service, website.service, typesense.service: type, nodePort, annotations, loadBalancerIP, ipFamilies, ...). Everything the chart deploys listens dual-stack, so no ipFamilies pin is needed on any cluster — see Address families for what to do if you pin an image of your own that does not.

Helper nodes and hardware encoding​

A second server pod can take the CPU-heavy work — HLS transcoding, intro/outro detection, subtitle extraction and OCR — for the main server's directories without owning any media: it reads the source over HTTP from the main server and uploads the result back. Declare them under helpers, one entry per pod, each naming the main server's directories (mediaVolumes[].name) it helps with and optionally which job families; the main server can hand families off entirely with server.helper.offloadJobs. Set server.clusterName so all pods present one cluster to clients. The helpers share the chart's database, broker and search and need nothing else. See the server documentation, chapter Multi-node, for how the work is shared.

Hardware encoding is hwaccel on the main server and on each helper: type: vaapi (Intel/AMD) or nvdec (NVIDIA), and a way to hand the pod the GPU. Prefer a device plugin (hwaccel.resources, for example gpu.intel.com/i915: 1, amd.com/gpu: 1, nvidia.com/gpu: 1, or squat.ai/dri: 1 with the generic device plugin) — unprivileged and schedulable. hwaccel.hostPath: true mounts the device file from the node instead, which the device cgroup only allows for a privileged container (hwaccel.privileged). Add the node's video/render group ids to hwaccel.supplementalGroups when the device is group-owned.

Address families: dual-stack and IPv6-only clusters​

The chart runs on an IPv4-only, a dual-stack or an IPv6-only cluster as it stands. It is still worth knowing what goes wrong when a container listens on IPv4 only, because it bites the moment you swap an image for one of your own — and because the two ways it bites look nothing alike:

  1. Its Service. Without an explicit ipFamilies, a Service on an IPv6-primary cluster gets an IPv6 ClusterIP, and the container never answers there. That reads as a crashed application; it is a networking choice.
  2. Its probes. kubelet aims an httpGet probe at the pod's first IP, which on such a cluster is the IPv6 one. The probe then fails against a pod that serves its Service perfectly well, and a liveness probe restarts it forever.

Where each component stands, measured on kind with ipFamily: ipv4, kind with ipFamily: ipv6, and a dual-stack cluster:

ComponentIPv4-onlydual-stack, IPv6-primaryIPv6-only
serverworksworksworks
PostgreSQL (internal)worksworksworks
RabbitMQ (AMQP)worksworksworks
Typesenseworksworksworks
websiteworksworksworks
  • Typesense listens dual-stack because typesense.apiAddress defaults to ::. The image's own default is 0.0.0.0, which fails both ways above. Set it back to 0.0.0.0 only on nodes that run with IPv6 disabled in the kernel.

  • The server, PostgreSQL and RabbitMQ's AMQP listener bind :: by themselves. RabbitMQ's management, Prometheus and Erlang-distribution listeners are IPv4-only, but nothing in this chart reaches them across the network: rabbitmq-diagnostics talks to the local node, and 127.0.0.1 exists in a pod on any cluster.

  • The web player's nginx listens dual-stack in the image the chart pins. If you point website.image at one of your own that binds IPv4 only, its Service needs

    website:
    service:
    ipFamilyPolicy: SingleStack
    ipFamilies: [IPv4]

    on a dual-stack cluster, and on an IPv6-only cluster it cannot be reached at all. The API is unaffected either way. Its readiness probe runs over 127.0.0.1 inside the container, so such an image reports Ready even where its Service is dead — check the Service, not the pod, if the player does not load.

  • RabbitMQ's management port (15672) rides along on the same Service as AMQP. The chart itself never reaches it across the network, so this only matters if you want to open the management UI or API through that Service on an IPv6-primary cluster: pin rabbitmq.service to [IPv4] for that, at the price of an IPv4 AMQP ClusterIP.

Changing the family of an existing Service​

A pin you set (or remove) later does not simply take effect, because a ClusterIP is immutable. Measured against a dual-stack Kubernetes 1.36 apiserver:

  • Adding a family in place is allowed. ipFamilyPolicy: RequireDualStack (or PreferDualStack) with ipFamilies: [<current>, <other>] keeps the existing ClusterIP and allocates a second one alongside it. No interruption.
  • Changing the primary family is refused: spec.clusterIPs[0]: Invalid value: "10.121.107.45": expected an IPv6 value as indicated by ipFamilies[0]. A helm upgrade aborts on that error.
  • Removing the pin does nothing at all, and says nothing either. With ipFamilies absent, the apiserver fills in the values the Service already has, so it silently keeps its old family. The release looks up to date and the Service is unchanged.

Going back to the cluster default after a pin is therefore a recreate — first make sure the new values are applied, then:

kubectl -n <namespace> delete svc <release>-typesense
helm upgrade ... # Helm 3 creates release resources that are missing

Between the two the name has no ClusterIP, so pick a moment when a short interruption of that component is acceptable. If you deploy the chart through a GitOps tool, note that the delete is drift, not a revision change: ArgoCD with automated but without selfHeal will leave the Service missing until you trigger a sync yourself.

Network policies and pod security​

networkPolicy.enabled: true renders ingress-only NetworkPolicies: the datastores accept traffic from this release's pods only, the server, helpers and website also from networkPolicy.ingressFrom — add your ingress controller's or Gateway's namespace there, and Prometheus for the monitor port. Egress stays open (metadata sources, podcast feeds, your OIDC issuer). The pods pass the "restricted" Pod Security Standard; on OpenShift set runAsUser/fsGroup to null in the podSecurityContext blocks so the SCC assigns the UID.

Operations​

  • Upgrades: helm upgrade ister oci://ghcr.io/ister-app/charts/ister --version <v> with your values file. Generated passwords are preserved (see above).
  • Smoke test: helm test ister -n ister --logs runs the shipped connectivity test.
  • Monitoring: monitoring.enabled renders a Prometheus Operator ServiceMonitor for the server's actuator; in cnpg mode, database.cnpg.podMonitor covers the database.
  • Uninstall: the database, cache and Typesense PVCs are kept by default (retain: true) so an uninstall is not destructive; set retain: false where you want them purged with the release.

Values reference​

Every value the chart accepts, with its default. This table is generated from the values.yaml of the release this documentation shipped with; values.schema.json enforces the same contract on every render.

KeyDefault
nameOverride""
fullnameOverride""
global.imageRegistry""
commonLabels{}
imagePullSecrets[]
revisionHistoryLimitnull
serviceAccount.createtrue
serviceAccount.name""
serviceAccount.annotations{}
server.name"Ister"
server.clusterName""
server.image.repository"ghcr.io/ister-app/server"
server.image.tag"5.4.0"
server.image.digest""
server.image.pullPolicy"IfNotPresent"
server.replicaCount1
server.revisionHistoryLimitnull
server.contextPath"/api"
server.url""
server.oidc.url""
server.oidc.audience""
server.tmdbApiKey""
server.existingSecret""
server.managementPort8081
server.enableServiceLinksfalse
server.languages""
server.websocketAllowedOrigins""
server.externalServices.tmdbApiUrl""
server.externalServices.tmdbImageBase""
server.externalServices.musicbrainzBase""
server.externalServices.coverArtReleaseBase""
server.externalServices.coverArtReleaseGroupBase""
server.externalServices.commonsFilepathBase""
server.externalServices.openLibraryBase""
server.externalServices.openLibraryCoversBase""
server.externalServices.openLibraryAuthorPhotoBase""
server.externalServices.wikidataEntityBase""
server.externalServices.wikidataApiBase""
server.externalServices.wikipediaSummaryTemplate""
server.externalServices.itunesBase""
server.externalServices.ludusaviManifestUrl""
server.hwaccel.type"none"
server.hwaccel.device"/dev/dri/renderD128"
server.hwaccel.resources{}
server.hwaccel.hostPathfalse
server.hwaccel.privilegedfalse
server.hwaccel.supplementalGroups[]
server.helper.disks[]
server.helper.jobs[]
server.helper.offloadJobs[]
server.helper.concurrency""
server.config.logging.level.[com.github.kokorin.jaffree.process.BaseStdReader]"ERROR"
server.config.logging.level.[com.github.kokorin.jaffree.ffmpeg.FFmpeg]"ERROR"
server.config.springdoc.swagger-ui.oauth.clientId"ister"
server.config.spring.graphql.graphiql.enabledtrue
server.config.spring.graphql.websocket.connection-init-timeout"30s"
server.config.spring.graphql.websocket.keep-alive"25s"
server.config.spring.datasource.hikari.maximum-pool-size20
server.config.spring.datasource.hikari.connection-timeout10000
server.config.spring.jpa.show-sqlfalse
server.config.spring.jpa.properties.hibernate.default_batch_fetch_size50
server.config.spring.rabbitmq.listener.simple.prefetch1
server.config.spring.rabbitmq.listener.simple.concurrency3
server.config.spring.rabbitmq.listener.simple.retry.enabledtrue
server.config.spring.rabbitmq.listener.simple.retry.max-attempts3
server.config.spring.rabbitmq.listener.simple.retry.initial-interval"2s"
server.config.spring.rabbitmq.listener.simple.retry.multiplier2
server.config.management.endpoints.web.exposure.include"health,metrics,prometheus"
server.config.app.ister.server.cache-cleanup.enabledtrue
server.config.app.ister.server.cache-cleanup.dry-runtrue
server.config.app.ister.server.cache-cleanup.cron"0 30 4 * * *"
server.config.app.ister.server.cache-cleanup.min-age"24h"
server.config.app.ister.server.image-thumbnail.max-idle"30d"
server.config.app.ister.server.continue-watching.history-days150
server.config.app.ister.server.continue-watching.rebuild.enabledtrue
server.config.app.ister.server.continue-watching.rebuild-cron"0 30 3 * * *"
server.config.app.ister.server.TMDB.max-requests-per-second30
server.config.app.ister.server.blur-hash.chunk-size500
server.config.app.ister.server.segment-detect.chunk-size4
server.config.app.ister.upload.enabledtrue
server.config.app.ister.upload.chunk-size"16MB"
server.config.app.ister.upload.max-active-sessions2
server.config.app.ister.upload.max-files-per-session100000
server.config.app.ister.upload.max-concurrent-chunks4
server.config.app.ister.upload.session-idle-timeout"24h"
server.config.app.ister.upload.cleanup-interval"PT1H"
server.config.app.ister.upload.min-free-space"5GB"
server.config.app.ister.s3.ffmpeg-directfalse
server.config.app.ister.s3.presign-ttl"2h"
server.config.app.ister.s3.local-copy-max-bytes2147483648
server.config.app.ister.transcoder.hls.max-concurrent-files2
server.extraEnv[]
server.extraEnvFrom[]
server.extraVolumes[]
server.extraVolumeMounts[]
server.podLabels{}
server.terminationGracePeriodSeconds120
server.priorityClassName""
server.topologySpreadConstraints[]
server.service.type"ClusterIP"
server.service.port8080
server.service.nodePortnull
server.service.annotations{}
server.service.labels{}
server.service.loadBalancerIP""
server.service.loadBalancerClass""
server.service.externalTrafficPolicy""
server.service.ipFamilyPolicy""
server.service.ipFamilies[]
server.podAnnotations{}
server.nodeSelector{}
server.tolerations[]
server.affinity{}
server.resources.requests.cpu"500m"
server.resources.requests.memory"1Gi"
server.resources.limits.memory"4Gi"
server.podSecurityContext.runAsNonRoottrue
server.podSecurityContext.runAsUser1000
server.podSecurityContext.fsGroup1000
server.podSecurityContext.seccompProfile.type"RuntimeDefault"
server.securityContext.allowPrivilegeEscalationfalse
server.securityContext.capabilities.drop["ALL"]
server.probes.enabledtrue
server.probes.path"/actuator/health"
server.probes.startup.failureThreshold30
server.probes.startup.periodSeconds10
server.probes.liveness.periodSeconds20
server.probes.liveness.failureThreshold3
server.probes.readiness.periodSeconds10
server.probes.readiness.failureThreshold3
server.tmp.mountPath"/tmp/ister"
server.tmp.enabledtrue
server.tmp.sizeLimit"10Gi"
server.tmp.existingClaim""
server.libraries[]
server.mediaVolumes[]
helpers[]
website.image.repository"ghcr.io/ister-app/player"
website.image.tag"2.15.0"
website.image.digest""
website.image.pullPolicy"IfNotPresent"
website.replicaCount1
website.revisionHistoryLimitnull
website.port8080
website.extraEnv[]
website.service.type"ClusterIP"
website.service.port8080
website.service.nodePortnull
website.service.annotations{}
website.service.labels{}
website.service.loadBalancerIP""
website.service.loadBalancerClass""
website.service.externalTrafficPolicy""
website.service.ipFamilyPolicy""
website.service.ipFamilies[]
website.wellKnown.enabledtrue
website.podAnnotations{}
website.nodeSelector{}
website.tolerations[]
website.affinity{}
website.resources.requests.cpu"10m"
website.resources.requests.memory"32Mi"
website.resources.limits.memory"128Mi"
website.podSecurityContext.runAsNonRoottrue
website.podSecurityContext.seccompProfile.type"RuntimeDefault"
website.securityContext.allowPrivilegeEscalationfalse
website.securityContext.capabilities.drop["ALL"]
website.probes.enabledtrue
website.probes.path"/"
cache.enabledtrue
cache.existingClaim""
cache.mountPath"/cache"
cache.storageClass""
cache.size"20Gi"
cache.accessMode"ReadWriteOnce"
cache.retaintrue
ingress.enabledfalse
ingress.className""
ingress.controller""
ingress.host""
ingress.annotations{}
ingress.proxy.bodySize"0"
ingress.proxy.timeoutSeconds3600
ingress.tls.enabledtrue
ingress.tls.secretName""
ingress.tls.certIssuer""
ingress.wellKnown.enabledfalse
gateway.enabledfalse
gateway.hostnames[]
gateway.parentRefs[]
gateway.annotations{}
gateway.tlstrue
gateway.apiTimeouts.request"0s"
gateway.apiTimeouts.backendRequest""
gateway.apiFilters[]
gateway.websiteFilters[]
database.mode"internal"
database.internal.image.repository"postgres"
database.internal.image.tag"18.6"
database.internal.image.pullPolicy"IfNotPresent"
database.internal.dbName"ister"
database.internal.user"ister"
database.internal.password""
database.internal.existingSecret""
database.internal.storageClass""
database.internal.storageSize"8Gi"
database.internal.retaintrue
database.internal.revisionHistoryLimitnull
database.internal.existingClaim""
database.internal.probes.enabledtrue
database.internal.probes.startup.failureThreshold30
database.internal.probes.startup.periodSeconds10
database.internal.probes.startup.timeoutSeconds5
database.internal.probes.liveness.periodSeconds10
database.internal.probes.liveness.timeoutSeconds5
database.internal.probes.liveness.failureThreshold6
database.internal.probes.readiness.periodSeconds5
database.internal.probes.readiness.timeoutSeconds5
database.internal.probes.readiness.failureThreshold3
database.internal.podSecurityContext.runAsNonRoottrue
database.internal.podSecurityContext.runAsUser999
database.internal.podSecurityContext.runAsGroup999
database.internal.podSecurityContext.fsGroup999
database.internal.podSecurityContext.seccompProfile.type"RuntimeDefault"
database.internal.resources.requests.cpu"100m"
database.internal.resources.requests.memory"256Mi"
database.internal.resources.limits.memory"1Gi"
database.cnpg.instances3
database.cnpg.imageName""
database.cnpg.dbName"ister"
database.cnpg.user"ister"
database.cnpg.storageClass""
database.cnpg.storageSize"12Gi"
database.cnpg.enablePodAntiAffinitytrue
database.cnpg.podMonitor.enabledtrue
database.cnpg.podMonitor.interval"30s"
database.cnpg.podMonitor.labels{}
database.cnpg.parameters.pgaudit.log"all, -misc"
database.cnpg.parameters.pgaudit.log_parameter"on"
database.cnpg.parameters.pgaudit.log_relation"on"
database.cnpg.resources{}
database.cnpg.backup.enabledfalse
database.cnpg.backup.destinationPath""
database.cnpg.backup.endpointURL""
database.cnpg.backup.region""
database.cnpg.backup.walCompression"gzip"
database.cnpg.backup.existingSecret""
database.cnpg.backup.accessKeyId""
database.cnpg.backup.secretAccessKey""
database.cnpg.backup.schedule.enabledtrue
database.cnpg.backup.schedule.cron"0 0 3 * * *"
database.cnpg.backup.schedule.backupOwnerReference"self"
database.external.host""
database.external.port5432
database.external.dbName"ister"
database.external.user"ister"
database.external.password""
database.external.existingSecret""
rabbitmq.enabledtrue
rabbitmq.revisionHistoryLimitnull
rabbitmq.image.repository"rabbitmq"
rabbitmq.image.tag"4.3.6-management-alpine"
rabbitmq.image.digest""
rabbitmq.image.pullPolicy"IfNotPresent"
rabbitmq.auth.username"user"
rabbitmq.auth.password""
rabbitmq.auth.existingSecret""
rabbitmq.persistence.enabledtrue
rabbitmq.persistence.existingClaim""
rabbitmq.persistence.storageClass""
rabbitmq.persistence.size"8Gi"
rabbitmq.extraEnv[]
rabbitmq.podAnnotations{}
rabbitmq.nodeSelector{}
rabbitmq.tolerations[]
rabbitmq.affinity{}
rabbitmq.service.annotations{}
rabbitmq.service.ipFamilyPolicy""
rabbitmq.service.ipFamilies[]
rabbitmq.podSecurityContext.runAsNonRoottrue
rabbitmq.podSecurityContext.runAsUser999
rabbitmq.podSecurityContext.runAsGroup999
rabbitmq.podSecurityContext.fsGroup999
rabbitmq.podSecurityContext.fsGroupChangePolicy"OnRootMismatch"
rabbitmq.podSecurityContext.seccompProfile.type"RuntimeDefault"
rabbitmq.securityContext.allowPrivilegeEscalationfalse
rabbitmq.securityContext.capabilities.drop["ALL"]
rabbitmq.resources.requests.cpu"50m"
rabbitmq.resources.requests.memory"256Mi"
rabbitmq.resources.limits.memory"512Mi"
externalRabbitmq.host""
externalRabbitmq.port5672
externalRabbitmq.user"user"
externalRabbitmq.password""
externalRabbitmq.existingSecret""
typesense.enabledtrue
typesense.revisionHistoryLimitnull
typesense.image.repository"docker.io/typesense/typesense"
typesense.image.tag"30.2"
typesense.image.pullPolicy"IfNotPresent"
typesense.port8108
typesense.collection"media"
typesense.apiAddress"::"
typesense.probes.enabledtrue
typesense.probes.startup.failureThreshold30
typesense.probes.startup.periodSeconds10
typesense.probes.liveness.periodSeconds20
typesense.probes.liveness.failureThreshold3
typesense.probes.readiness.periodSeconds10
typesense.probes.readiness.failureThreshold3
typesense.apiKey""
typesense.existingSecret""
typesense.persistence.enabledtrue
typesense.persistence.existingClaim""
typesense.persistence.storageClass""
typesense.persistence.size"8Gi"
typesense.persistence.retaintrue
typesense.podSecurityContext.runAsNonRoottrue
typesense.podSecurityContext.runAsUser1000
typesense.podSecurityContext.fsGroup1000
typesense.podSecurityContext.seccompProfile.type"RuntimeDefault"
typesense.securityContext.allowPrivilegeEscalationfalse
typesense.securityContext.capabilities.drop["ALL"]
typesense.nodeSelector{}
typesense.tolerations[]
typesense.resources.requests.cpu"100m"
typesense.resources.requests.memory"256Mi"
typesense.resources.limits.memory"1Gi"
typesense.service.annotations{}
typesense.service.ipFamilyPolicy""
typesense.service.ipFamilies[]
typesense.external.host""
typesense.external.port8108
typesense.external.protocol"http"
typesense.external.apiKey""
typesense.external.existingSecret""
flyway.enabledtrue
flyway.image.repository"ghcr.io/ister-app/migrations"
flyway.image.tag""
flyway.image.digest""
flyway.image.pullPolicy"IfNotPresent"
flyway.waitImage.repository"postgres"
flyway.waitImage.tag"18.6-alpine"
flyway.waitImage.pullPolicy"IfNotPresent"
flyway.resources.requests.cpu"100m"
flyway.resources.requests.memory"256Mi"
flyway.resources.limits.memory"512Mi"
monitoring.enabledfalse
monitoring.serviceMonitorLabels{}
monitoring.interval"30s"
networkPolicy.enabledfalse
networkPolicy.ingressFrom[]
podDisruptionBudget.enabledfalse
podDisruptionBudget.minAvailable1
tests.image.repository"curlimages/curl"
tests.image.tag"8.22.0"
tests.image.pullPolicy"IfNotPresent"