|
| 1 | +# Installing ister with Helm |
| 2 | + |
| 3 | +This chapter explains how the ister Helm chart works and how to install it. The chart |
| 4 | +deploys the full ister media server: the API server, the web player, and — unless you |
| 5 | +bring your own — PostgreSQL, RabbitMQ and Typesense. |
| 6 | + |
| 7 | +## What the chart deploys |
| 8 | + |
| 9 | +| Component | What it is | Bundled by default? | |
| 10 | +|---|---|---| |
| 11 | +| server | The Spring Boot backend (`ghcr.io/ister-app/server`) | always | |
| 12 | +| website | The web player (`ghcr.io/ister-app/player`) | always | |
| 13 | +| PostgreSQL | The database | yes (`database.mode: internal`) | |
| 14 | +| RabbitMQ | The message broker (Bitnami subchart) | yes (`rabbitmq.enabled: true`) | |
| 15 | +| Typesense | The search engine | yes (`typesense.enabled: true`) | |
| 16 | +| Flyway | Database migrations (`ghcr.io/ister-app/migrations`) | runs as an init container | |
| 17 | + |
| 18 | +The defaults deploy a self-contained ister with no ingress and no media volumes — enough |
| 19 | +to try it out, not a production setup. |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | + |
| 23 | +- A Kubernetes cluster and Helm 3. |
| 24 | +- A [TMDB API key](https://www.themoviedb.org/settings/api) for movie/show metadata. |
| 25 | +- An OIDC issuer (for example Keycloak) — ister does not manage users itself. |
| 26 | +- For `database.mode: cnpg`: the [CloudNativePG](https://cloudnative-pg.io/) operator. |
| 27 | +- For ingress with TLS: an ingress controller and, optionally, cert-manager. |
| 28 | + |
| 29 | +## Installing |
| 30 | + |
| 31 | +The chart is published as an OCI artifact: |
| 32 | + |
| 33 | +```sh |
| 34 | +helm install ister oci://ghcr.io/ister-app/charts/ister \ |
| 35 | + --namespace ister --create-namespace \ |
| 36 | + --set server.tmdbApiKey=<your-key> \ |
| 37 | + --set server.oidc.url=https://keycloak.example.com/realms/auth |
| 38 | +``` |
| 39 | + |
| 40 | +For anything beyond a first try, start from `values-production.example.yaml` in the |
| 41 | +[chart repository](https://github.com/ister-app/chart) and install with `-f`. Pin a chart |
| 42 | +version with `--version`; a GitHub Release exists for every chart version with release |
| 43 | +notes listing the exact image versions it deploys. |
| 44 | + |
| 45 | +## Bundled or external datastores |
| 46 | + |
| 47 | +Everything backing the server can either be deployed by the chart or pointed at an |
| 48 | +existing service. Whatever you choose, the templates downstream never notice the |
| 49 | +difference — that is the chart's central design rule. |
| 50 | + |
| 51 | +### PostgreSQL — `database.mode` |
| 52 | + |
| 53 | +- `internal` — a single postgres Deployment + PVC. Development only: one instance, no |
| 54 | + backups. |
| 55 | +- `cnpg` — a CloudNativePG `Cluster` (3 instances by default, anti-affinity, optional |
| 56 | + Barman Cloud backups to S3 under `database.cnpg.backup`). Requires the CNPG operator. |
| 57 | +- `external` — an existing PostgreSQL, configured under `database.external`. |
| 58 | + |
| 59 | +All three modes converge on **one Secret with the keys `host`, `port`, `dbname`, `user`, |
| 60 | +`password`** — the shape CNPG generates for its `<cluster>-app` Secret, which the other |
| 61 | +two modes hand-write to match. If you bring your own Secret (`existingSecret`), it must |
| 62 | +have exactly those keys; for a CNPG cluster managed outside this chart, its `<cluster>-app` |
| 63 | +Secret already does. |
| 64 | + |
| 65 | +### RabbitMQ — `rabbitmq.enabled` |
| 66 | + |
| 67 | +`true` deploys the Bitnami RabbitMQ subchart (everything under `rabbitmq:` is passed |
| 68 | +straight to it). `false` uses the `externalRabbitmq` block instead — its `existingSecret` |
| 69 | +needs the key `rabbitmq-password`. |
| 70 | + |
| 71 | +### Typesense — `typesense.enabled` |
| 72 | + |
| 73 | +`true` deploys Typesense with its own PVC. `false` uses `typesense.external` — its |
| 74 | +`existingSecret` needs the key `api-key`. |
| 75 | + |
| 76 | +## Secrets and passwords |
| 77 | + |
| 78 | +- **Nothing secret belongs in a values file.** Every credential has an `existingSecret` |
| 79 | + escape hatch; use it (or a secret manager) anywhere that matters. |
| 80 | +- **Generated passwords survive upgrades.** When you let the chart generate a password, |
| 81 | + it looks up the live Secret on upgrade and keeps the existing value — otherwise every |
| 82 | + `helm upgrade` would lock the server out of its own database. This is also why |
| 83 | + `helm template` output differs from what `helm install` actually applies. |
| 84 | +- **Rotating a Secret restarts the server.** All credentials are hashed into a |
| 85 | + `checksum/secrets` pod annotation, so a changed Secret rolls the Deployment. |
| 86 | + |
| 87 | +## Database migrations |
| 88 | + |
| 89 | +Flyway runs as an **init container on the server pod** (preceded by a `wait-for-db` |
| 90 | +container), so the server can never start against an unmigrated schema. It is not a Helm |
| 91 | +hook on purpose: with a bundled database, a pre-install hook would wait for a database |
| 92 | +that Helm has not created yet. The migrations image publishes the same version as the |
| 93 | +server, so `flyway.image.tag` stays empty and follows the server version automatically. |
| 94 | + |
| 95 | +## Media libraries and volumes |
| 96 | + |
| 97 | +Two value lists connect the server to your media: |
| 98 | + |
| 99 | +- `server.libraries` — the libraries ister scans; each has a `name` and a `type` |
| 100 | + (`SHOW`, `MOVIE`, `MUSIC`, `BOOK`, `PODCAST`, `COMIC`). |
| 101 | +- `server.mediaVolumes` — the volumes mounted into the server pod, each backed by exactly |
| 102 | + one of `hostPath`, `existingClaim` or `nfs`, and linked to a library via `library` |
| 103 | + (omit it for a mount-only volume). **No trailing slash on `mountPath`** — the scanner |
| 104 | + skips the tree if there is one. |
| 105 | + |
| 106 | +Two more storage knobs matter: |
| 107 | + |
| 108 | +- `cache` — a PVC for the server's cache directory (transcodes, images). It is |
| 109 | + `ReadWriteOnce` by default, which is why `server.replicaCount` must stay at 1 — the |
| 110 | + chart refuses to render more replicas unless you switch to `ReadWriteMany`. |
| 111 | +- `server.tmp` — scratch space for transcoding. Disable it when `mountPath` falls inside |
| 112 | + one of your media volumes, or the dedicated volume shadows that path. |
| 113 | + |
| 114 | +## Ingress |
| 115 | + |
| 116 | +`ingress.enabled: true` publishes the player at `/` and the API at `server.contextPath` |
| 117 | +(default `/api`) on `ingress.host`, with TLS via cert-manager when |
| 118 | +`ingress.tls.certIssuer` is set. `ingress.wellKnown.enabled` additionally serves |
| 119 | +`/.well-known/ister` for client discovery — implemented as an ingress-nginx |
| 120 | +server-snippet, which modern ingress-nginx disables by default |
| 121 | +(`allow-snippet-annotations`); enable that on the controller first. |
| 122 | + |
| 123 | +## Operations |
| 124 | + |
| 125 | +- **Upgrades**: `helm upgrade ister oci://ghcr.io/ister-app/charts/ister --version <v>` |
| 126 | + with your values file. Generated passwords are preserved (see above). |
| 127 | +- **Smoke test**: `helm test ister -n ister --logs` runs the shipped connectivity test. |
| 128 | +- **Monitoring**: `monitoring.enabled` renders a Prometheus Operator ServiceMonitor for |
| 129 | + the server's actuator; in `cnpg` mode, `database.cnpg.podMonitor` covers the database. |
| 130 | +- **Uninstall**: the database, cache and Typesense PVCs are kept by default |
| 131 | + (`retain: true`) so an uninstall is not destructive; set `retain: false` where you |
| 132 | + want them purged with the release. |
| 133 | + |
| 134 | +## Values reference |
| 135 | + |
| 136 | +Every value the chart accepts, with its default. This table is generated from the |
| 137 | +`values.yaml` of the release this documentation shipped with; `values.schema.json` |
| 138 | +enforces the same contract on every render. |
| 139 | + |
| 140 | +<!-- VALUES:BEGIN (generated by ci/build-docs.sh — do not edit between the markers) --> |
| 141 | +<!-- VALUES:END --> |
0 commit comments