Ga naar hoofdinhoud

Ister installeren met Helm

Dit hoofdstuk legt uit hoe de ister Helm chart werkt en hoe je hem installeert. De chart zet de volledige ister-mediaserver neer: de API-server, de webplayer, en — tenzij je je eigen diensten meebrengt — PostgreSQL, RabbitMQ en Typesense.

Wat de chart installeert​

ComponentWat het isStandaard meegeleverd?
serverDe Spring Boot-backend (ghcr.io/ister-app/server)altijd
websiteDe webplayer (ghcr.io/ister-app/player)altijd
PostgreSQLDe databaseja (database.mode: internal)
RabbitMQDe message broker (officiële image, één node)ja (rabbitmq.enabled: true)
TypesenseDe zoekmachineja (typesense.enabled: true)
FlywayDatabasemigraties (ghcr.io/ister-app/migrations)draait als init-container

De standaardwaarden leveren een op zichzelf staande ister zonder ingress en zonder mediavolumes — genoeg om het te proberen, geen productie-opstelling.

Vereisten​

  • Een Kubernetes-cluster en Helm 3.
  • Een TMDB API-key voor film-/seriemetadata.
  • Een OIDC-issuer (bijvoorbeeld Keycloak) — ister beheert zelf geen gebruikers. Die moet op een bepaalde manier ingericht zijn; zie De identity provider instellen.
  • Voor database.mode: cnpg: de CloudNativePG-operator.
  • Voor ingress met TLS: een ingress-controller en optioneel cert-manager.

Installeren​

De chart wordt gepubliceerd als OCI-artifact:

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

Voor alles voorbij een eerste test: begin met values-production.example.yaml uit de chart-repository en installeer met -f. Pin een chartversie met --version; bij elke chartversie hoort een GitHub Release waarvan de release notes de exact meegeleverde image-versies vermelden.

Gebundelde of externe datastores​

Alles waar de server op leunt kan óf door de chart worden uitgerold, óf naar een bestaande dienst wijzen. Wat je ook kiest, de onderliggende templates merken het verschil nooit — dat is de centrale ontwerpregel van de chart.

PostgreSQL — database.mode​

  • internal — één postgres-Deployment + PVC. Alleen voor ontwikkeling: één instantie, geen back-ups.
  • cnpg — een CloudNativePG-Cluster (standaard 3 instanties, anti-affinity, optionele Barman Cloud-back-ups naar S3 onder database.cnpg.backup). Vereist de CNPG-operator.
  • external — een bestaande PostgreSQL, geconfigureerd onder database.external.

Alle drie de modi komen uit op één Secret met de sleutels host, port, dbname, user, password — de vorm die CNPG genereert voor zijn <cluster>-app-Secret; de andere twee modi schrijven diezelfde vorm zelf. Breng je een eigen Secret mee (existingSecret), dan moet die exact deze sleutels hebben; het <cluster>-app-Secret van een buiten deze chart beheerd CNPG-cluster voldoet al.

RabbitMQ — rabbitmq.enabled​

true installeert een RabbitMQ-StatefulSet met één node op de officiële rabbitmq-image (ister gebruikt de broker alleen voor doorstroomwerk, dus clustering is niet nodig); het wachtwoord en de Erlang-cookie worden eenmalig gegenereerd, of komen uit rabbitmq.auth.existingSecret (sleutels rabbitmq-password, rabbitmq-erlang-cookie). false gebruikt het blok externalRabbitmq — diens existingSecret heeft de sleutel rabbitmq-password nodig.

Upgraden vanaf een chart van vóór 1.0, die de Bitnami-subchart meeleverde: de oude StatefulSet, Service en PVC met de naam <release>-rabbitmq worden niet overgenomen. Verwijder ze vóór de upgrade (de queues bevatten alleen doorstroomwerk), of draai de upgrade en verwijder daarna de achtergebleven PVC; de server verbindt zelf opnieuw met de nieuwe broker.

Typesense — typesense.enabled​

true installeert Typesense met een eigen PVC. false gebruikt typesense.external — diens existingSecret heeft de sleutel api-key nodig.

Secrets en wachtwoorden​

  • Niets geheims hoort in een values-bestand. Elke credential heeft een existingSecret-ontsnappingsluik; gebruik dat (of een secret manager) overal waar het ertoe doet.
  • Gegenereerde wachtwoorden overleven upgrades. Laat je de chart een wachtwoord genereren, dan zoekt hij bij een upgrade het live Secret op en behoudt de bestaande waarde — anders zou elke helm upgrade de server buiten zijn eigen database sluiten. Daarom verschilt de uitvoer van helm template ook van wat helm install daadwerkelijk toepast.
  • ...maar niet onder GitOps. Argo CD, Flux en helm template | kubectl apply renderen zonder toegang tot het cluster, dus die lookup vindt niets en elke sync genereert een nieuw wachtwoord. PostgreSQL houdt het eerste in zijn volume en de server strandt daarna op password authentication failed; al het andere herstart bij elke commit via de checksum/secrets-annotatie. Zo uitrollen betekent database.internal.password, rabbitmq.auth.password en typesense.apiKey expliciet zetten, of het bijbehorende existingSecret naar een Secret in eigen beheer wijzen.
  • Een Secret roteren herstart de server. Alle credentials worden gehasht in een checksum/secrets-podannotatie, dus een gewijzigd Secret rolt de Deployment.

Databasemigraties​

Flyway draait als init-container op de server-pod (voorafgegaan door een wait-for-db-container), zodat de server nooit tegen een ongemigreerd schema kan starten. Het is bewust geen Helm-hook: met een gebundelde database zou een pre-install-hook wachten op een database die Helm nog niet heeft aangemaakt. De migrations-image publiceert dezelfde versie als de server, dus flyway.image.tag blijft leeg en volgt de serverversie automatisch.

Mediabibliotheken en -volumes​

Twee value-lijsten verbinden de server met je media:

  • server.libraries — de bibliotheken die ister scant; elk met een name en een type (SHOW, MOVIE, MUSIC, BOOK, PODCAST, COMIC).
  • server.mediaVolumes — de volumes die in de server-pod worden gemount, elk gedragen door precies één van hostPath, existingClaim of nfs, en via library gekoppeld aan een bibliotheek (laat dat weg voor alleen een mount). Geen slash aan het eind van mountPath — de scanner slaat de boom dan over.

Twee andere opslagknoppen doen ertoe:

  • cache — een PVC voor de cachemap van de server (transcodes, afbeeldingen). Standaard ReadWriteOnce, en daarom moet server.replicaCount op 1 blijven — de chart weigert meer replica's te renderen tenzij je overschakelt op ReadWriteMany.
  • server.tmp — kladruimte voor transcoderen. Zet dit uit wanneer mountPath binnen een van je mediavolumes valt, anders overschaduwt het aparte volume dat pad.

Serverinstellingen — server.config​

Alles wat de server uit zijn eigen configuratiebestanden leest, is in te stellen onder server.config: een boom van Spring-properties die de chart in een ConfigMap rendert en in elke server-pod (de hoofdserver en alle helpers) mount als /config/application.yaml. Het blok in values.yaml bevat de instelbare properties met de defaults van de server — cache-opruiming, verder kijken, uploadlimieten, RabbitMQ-listener-tuning, de Hikari-pool, transcode-gelijktijdigheid — zodat de values-referentie hieronder meteen de lijst is van wat je kunt wijzigen. Elke andere Spring- of app.ister.*-property mag erbij (zie de serverdocumentatie, hoofdstuk Configuratie); een wijziging rolt de pods via een checksum/config-annotatie.

Voorrang, van laag naar hoog: de ingebouwde defaults van de server, dan server.config, dan omgevingsvariabelen. Alles wat de chart uit andere values afleidt blijft een env-var (database, broker, zoeken, OIDC, servernaam en -URL, cache- en tmp-paden, bibliotheken en mappen, helper-schijven, hardwareversnelling), dus die keys hebben in server.config geen effect; secrets horen er evenmin. server.extraEnv overschrijft nog steeds een key uit server.config, maar alleen onder zijn canonieke Spring-naam (APP_ISTER_SERVER_CACHE_CLEANUP_CRON): de korte aliassen die de defaults van de server zelf accepteren (CACHE_CLEANUP_CRON, HLS_MAX_CONCURRENT_FILES, …) worden overschaduwd zodra server.config die key zet. Helpers lezen dezelfde ConfigMap; een verschil per helper gaat in helpers[].extraEnv. Zet je zelf SPRING_CONFIG_ADDITIONAL_LOCATION, houd dan file:/config/ in de kommagescheiden lijst.

De defaults in het blok zijn die van de serverrelease die de chart pint (server.image.tag), en de chart houdt ze zo: wijzigt een serverrelease een default, dan draagt de volgende chartrelease de nieuwe waarde, en de release notes sommen elke server.config-key op die is toegevoegd, gewijzigd of verwijderd, plus nieuwe serverinstellingen die de chart nog niet spiegelt. Een waarde die je zelf in je eigen values-bestand zet, wordt daardoor nooit aangeraakt.

Eén beperking: de server is een GraalVM-native-image, en Spring bepaalt bij het bouwen van dat image welke beans bestaan. Een property die alleen een waarde verandert (een cron, een poolgrootte, een logniveau, health-details) werkt; een die een bean zou aanmaken die niet in het image zit niet — de Actuator-exposure-lijst kun je inperken maar niet uitbreiden, en enabled-achtige vlaggen werken alleen waar de server ze tijdens runtime controleert.

Naar buiten: Ingress of Gateway API​

Beide publiceren de player op / en de API op server.contextPath (standaard /api) op één hostnaam; kies er één.

  • Ingress — ingress.enabled: true met ingress.host. ingress.className is standaard leeg (de default IngressClass van het cluster); zet hem als je meerdere controllers draait. TLS via cert-manager wanneer ingress.tls.certIssuer is gezet.
  • Gateway API — gateway.enabled: true met gateway.hostnames en gateway.parentRefs (de Gateway en listener om aan te hangen; de Gateway zelf is van jou en moet routes uit de namespace van de chart toelaten). Werkt met Envoy Gateway, Cilium, Istio, de Gateway-provider van Traefik en dergelijke.

Wat er ook vóór ister staat, het moet drie dingen toelaten die de meeste proxies standaard begrenzen: onbegrensde request-bodies (helper-nodes uploaden hele HLS-segmenten en ondertitelbestanden), responses die minuten tot uren lopen (HLS-afspelen, een helper-node die een bron van meerdere GB leest) en websocket-upgrades op /api/graphql. ingress.controller (nginx | traefik | haproxy) rendert de bijbehorende annotaties uit ingress.proxy; de HTTPRoute zet timeouts.request: 0s op de /api-regel (gateway.apiTimeouts). Traefik heeft per Ingress niets nodig, maar zijn leestimeouts zijn entrypoint-instellingen (entryPoints.<naam>.transport.respondingTimeouts).

/.well-known/ister, het document dat clients als eerste ophalen (naam van de instantie, OIDC-issuer, API-URL), wordt door de website-pod zelf geserveerd (website.wellKnown, standaard aan), dus het werkt achter elke controller, een NodePort of een port-forward. De oudere ingress-nginx-snippet (ingress.wellKnown) bestaat nog voor opstellingen die erop leunen.

De Services kennen de gebruikelijke knoppen (server.service, website.service, typesense.service: type, nodePort, annotations, loadBalancerIP, ipFamilies, ...). Alles wat de chart uitrolt luistert dual-stack, dus een ipFamilies-pin is op geen enkel cluster nodig — zie Adresfamilies voor wat je doet als je zelf een image pint dat dat niet doet.

Helper-nodes en hardware-encoding​

Een tweede server-pod kan het CPU-zware werk — HLS-transcoderen, intro-/outro-detectie, ondertitel-extractie en OCR — voor de directories van de hoofdserver overnemen zonder zelf media te bezitten: hij leest de bron via HTTP van de hoofdserver en uploadt het resultaat terug. Declareer ze onder helpers, één regel per pod, elk met de directories van de hoofdserver (mediaVolumes[].name) waarmee hij helpt en optioneel welke jobfamilies; de hoofdserver kan families volledig uit handen geven met server.helper.offloadJobs. Zet server.clusterName zodat alle pods zich als één cluster aan clients presenteren. De helpers delen de database, broker en zoekindex van de chart en hebben verder niets nodig. Zie de serverdocumentatie, hoofdstuk Multi-node, voor hoe het werk wordt verdeeld.

Hardware-encoding is hwaccel op de hoofdserver en op elke helper: type: vaapi (Intel/AMD) of nvdec (NVIDIA), plus een manier om de pod de GPU te geven. Gebruik bij voorkeur een device-plugin (hwaccel.resources, bijvoorbeeld gpu.intel.com/i915: 1, amd.com/gpu: 1, nvidia.com/gpu: 1, of squat.ai/dri: 1 met de generic device plugin) — zonder privileges en planbaar. hwaccel.hostPath: true mount in plaats daarvan het devicebestand van de node, wat de device-cgroup alleen toestaat voor een privileged container (hwaccel.privileged). Zet de group-id's van video/render van de node in hwaccel.supplementalGroups als het device group-eigendom is.

Adresfamilies: dual-stack en IPv6-only clusters​

De chart draait zoals hij is op een IPv4-only, een dual-stack of een IPv6-only cluster. Het blijft de moeite waard te weten wat er misgaat als een container alleen op IPv4 luistert, want dat bijt zodra je een image voor een eigen exemplaar inwisselt — en de twee manieren waarop het bijt lijken in niets op elkaar:

  1. Zijn Service. Zonder expliciete ipFamilies krijgt een Service op een IPv6-primair cluster een IPv6-ClusterIP, en daar antwoordt de container nooit. Dat leest als een gecrashte applicatie, maar het is een netwerkkeuze.
  2. Zijn probes. kubelet richt een httpGet-probe op het eerste pod-IP, en dat is op zo'n cluster het IPv6-adres. De probe faalt dan tegen een pod die zijn Service prima bedient, en een liveness-probe herstart hem eindeloos.

Waar elk onderdeel staat, gemeten op kind met ipFamily: ipv4, kind met ipFamily: ipv6 en een dual-stack cluster:

ComponentIPv4-onlydual-stack, IPv6-primairIPv6-only
serverwerktwerktwerkt
PostgreSQL (internal)werktwerktwerkt
RabbitMQ (AMQP)werktwerktwerkt
Typesensewerktwerktwerkt
websitewerktwerktwerkt
  • Typesense luistert dual-stack doordat typesense.apiAddress standaard :: is. De eigen standaard van het image is 0.0.0.0, en die faalt op beide manieren hierboven. Zet hem alleen terug op 0.0.0.0 op nodes waar IPv6 in de kernel uit staat.

  • De server, PostgreSQL en de AMQP-listener van RabbitMQ binden uit zichzelf al ::. De management-, Prometheus- en Erlang-distributielisteners van RabbitMQ zijn IPv4-only, maar niets in deze chart benadert die over het netwerk: rabbitmq-diagnostics praat met de lokale node, en 127.0.0.1 bestaat in een pod op elk cluster.

  • De nginx van de webplayer luistert dual-stack in het image dat de chart pint. Wijs je website.image naar een eigen image dat alleen op IPv4 bindt, dan heeft zijn Service op een dual-stack cluster dit nodig:

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

    en op een IPv6-only cluster is hij dan helemaal niet te bereiken. De API heeft er geen last van. Zijn readiness-probe loopt over 127.0.0.1 binnen de container, dus zo'n image meldt Ready ook waar zijn Service dood is — kijk naar de Service en niet naar de pod als de player niet laadt.

Netwerkbeleid en podbeveiliging​

networkPolicy.enabled: true rendert NetworkPolicies voor alleen inkomend verkeer: de datastores accepteren alleen verkeer van de pods van deze release, de server, helpers en website ook van networkPolicy.ingressFrom — zet daar de namespace van je ingress-controller of Gateway in, en Prometheus voor de monitorpoort. Uitgaand verkeer blijft open (metadatabronnen, podcastfeeds, je OIDC-issuer). De pods voldoen aan de Pod Security Standard "restricted"; zet op OpenShift runAsUser/fsGroup op null in de podSecurityContext-blokken zodat de SCC de UID toewijst.

Beheer​

  • Upgrades: helm upgrade ister oci://ghcr.io/ister-app/charts/ister --version <v> met je values-bestand. Gegenereerde wachtwoorden blijven behouden (zie hierboven).
  • Rooktest: helm test ister -n ister --logs draait de meegeleverde connectiviteitstest.
  • Monitoring: monitoring.enabled rendert een Prometheus Operator-ServiceMonitor voor de actuator van de server; in cnpg-modus dekt database.cnpg.podMonitor de database.
  • Verwijderen: de PVC's van database, cache en Typesense blijven standaard staan (retain: true), dus een uninstall is niet destructief; zet retain: false waar je ze met de release opgeruimd wilt hebben.

Values-referentie​

Elke value die de chart accepteert, met zijn standaardwaarde. Deze tabel wordt gegenereerd uit de values.yaml van de release waarmee deze documentatie is meegeleverd; values.schema.json dwingt hetzelfde contract af bij elke 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"