diff --git a/docs/src/usage/helm.md b/docs/src/usage/helm.md index f637f5d..0d9df38 100644 --- a/docs/src/usage/helm.md +++ b/docs/src/usage/helm.md @@ -5,56 +5,127 @@ A Helm chart is available for deploying taskchampion-sync-server on Kubernetes. ## Adding the Repository ```sh -helm repo add taskchampion https://gothenburgbitfactory.org/taskchampion-sync-server/helm-chart +helm repo add taskchampion https://gothenburgbitfactory.org/taskchampion-sync-server helm repo update ``` -## Installing the Chart - -The chart requires exactly one storage backend to be enabled. To install with -the SQLite backend: +## Installing ```sh +# SQLite backend helm install taskchampion-sync-server taskchampion/taskchampion-sync-server \ --set sqlite.enabled=true -``` -To install with the Postgres backend, provide the connection details: - -```sh +# PostgreSQL backend helm install taskchampion-sync-server taskchampion/taskchampion-sync-server \ --set postgres.enabled=true \ --set postgres.host=my-postgres \ - --set postgres.database=taskchampion \ + --set postgres.db=taskchampion \ --set postgres.username=myuser \ --set postgres.password=mypassword ``` -Alternatively, pass an existing Secret name via `postgres.existingSecret`. The -secret must contain a `connection` key holding a [LibPQ-style connection -URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS). +## Storage Backends -## Configuration +Exactly one storage backend must be enabled. The chart fails validation if +neither or both are enabled. -The chart does not implement TLS. The expectation is that a Kubernetes ingress -or gateway will terminate TLS and proxy HTTP traffic to the server container. -Enable one of the built-in options or configure your own: +### SQLite -```sh -# NGINX ingress ---set ingress.enabled=true --set ingress.hosts[0]=taskchampion.example.com +Mounts a volume at `sqlite.dataDir` (default `/var/lib/taskchampion-sync-server/data`). +The volume defaults to `emptyDir` but can be backed by a PVC or +existing PersistentVolumeClaim: -# Gateway API HTTPRoute ---set httpRoute.enabled=true \ ---set httpRoute.gateway=my-gateway \ ---set httpRoute.host=taskchampion.example.com +| Value | Description | +|-------|-------------| +| `sqlite.persistence.enabled` | Create a PVC (default: `false`) | +| `sqlite.existingPV` | Use an existing PVC by name | +| `sqlite.emptyDir` | emptyDir volume settings (default fallback) | + +### PostgreSQL + +Creates a Deployment with optional replicas, an auto-generated or existing +secret for the connection string, and an init container that waits for +PostgreSQL, applies the schema, and optionally seeds client IDs. + +**Secret handling** — When `postgres.existingSecret` is empty (default), the +chart creates a secret named `{release-name}-connection` with a `conn` key. +When set, the chart reads the named secret. It accepts either a `conn` key +with a full [LibPQ-style URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS) +or individual fields (`host`, `port`, `username`, `password`, `database`) that +override the corresponding `postgres.*` values. + +**Init container** — Enabled by default. Waits for PG readiness, downloads +the schema from `https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/v0.7.0/postgres/schema.sql`, +applies it, and seeds client IDs if `clientIdSecret` is set. Override the +schema URL with `postgres.initContainer.schemaUrl`. + +**Replicas** — Replicas only apply with PostgreSQL: +`replicas.enabled=true`, `replicas.count=N`. SQLite is always single-replica. + +## Secrets + +### Client ID Secret + +Optional. Restrict which client IDs the server accepts. Create a Secret with +comma-separated UUIDs (base64-encoded) under a `client-ids` key: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: my-client-ids +type: Opaque +data: + client-ids: ``` -To restrict which client IDs the server accepts, create a Secret containing a -newline-separated list of UUIDs and reference it: +Reference it via `clientIdSecret: "my-client-ids"`. The value is available to +the server as `CLIENT_ID` and to the init container as `CLIENT_IDS`. -```sh ---set clientIdSecret=my-client-ids-secret +## Networking + +The chart does not implement TLS. Terminate TLS at the ingress or gateway and +proxy HTTP to port 8080. + +### Ingress (NGINX) + +```yaml +ingress: + enabled: true + hosts: + - taskchampion.example.com ``` -See the chart's `values.yaml` for the full set of configuration options. +### HTTPRoute (Kubernetes Gateway API) + +Use `parentRefs`, `hostnames`, and `rules`: + +```yaml +httpRoute: + enabled: true + parentRefs: + - name: my-gateway + hostnames: + - tasks.example.com + rules: + - path: + type: PathPrefix + value: / + backendPort: 8080 +``` + +The deprecated fields `httpRoute.gateway`, `httpRoute.host`, +`httpRoute.path`, and `httpRoute.port` are used as a fallback when the +structured arrays are empty. + +### ServiceAccount and RBAC + +When `serviceAccount.create` is `true` (default), the chart creates a +ServiceAccount, a Role with `get`/`create`/`update`/`patch` on secrets, and +a RoleBinding. Set `serviceAccount.name` to use an existing SA. + +## Reference + +See the chart's [values.yaml](https://github.com/GothenburgBitFactory/taskchampion-sync-server/blob/main/helm/taskchampion-sync-server/values.yaml) +for all configurable options. diff --git a/helm/taskchampion-sync-server/README.md b/helm/taskchampion-sync-server/README.md index 4ec516a..890411e 100644 --- a/helm/taskchampion-sync-server/README.md +++ b/helm/taskchampion-sync-server/README.md @@ -7,28 +7,55 @@ Deploy the [TaskChampion Sync Server](https://github.com/GothenburgBitFactory/ta - Kubernetes 1.23+ - Helm 3+ +## Installing + +```console +helm repo add taskchampion https://gothenburgbitfactory.org/taskchampion-sync-server +helm repo update +helm install my-release taskchampion/taskchampion-sync-server --set sqlite.enabled=true +``` + ## Storage Backends -Exactly one storage backend must be enabled. The chart will fail validation if both or neither are enabled. +Exactly one storage backend must be enabled. The chart fails validation if neither or both are enabled. ### SQLite -```console -helm install my-release ./helm/taskchampion-sync-server -f helm/taskchampion-sync-server/examples/sqlite-values.yaml -``` +| Parameter | Default | Description | +|-----------|---------|-------------| +| `sqlite.enabled` | `false` | Enable SQLite backend | +| `sqlite.dataDir` | `/var/lib/taskchampion-sync-server/data` | Data directory path | +| `sqlite.existingPV` | `""` | Use an existing PVC name | +| `sqlite.persistence.enabled` | `false` | Create a PVC | +| `sqlite.persistence.size` | `1Gi` | PVC size | +| `sqlite.persistence.accessMode` | `ReadWriteOnce` | PVC access mode | +| `sqlite.emptyDir` | — | emptyDir volume settings | ### PostgreSQL -```console -helm install my-release ./helm/taskchampion-sync-server -f helm/taskchampion-sync-server/examples/postgres-values.yaml -``` +| Parameter | Default | Description | +|-----------|---------|-------------| +| `postgres.enabled` | `false` | Enable PostgreSQL backend | +| `postgres.host` | `""` | PostgreSQL host | +| `postgres.port` | `5432` | PostgreSQL port | +| `postgres.db` | `taskchampion` | Database name | +| `postgres.username` | `""` | Database user | +| `postgres.password` | `""` | Database password | +| `postgres.sslMode` | `disable` | SSL mode | +| `postgres.existingSecret` | `""` | Use existing secret by name | + +**Secret** — When `existingSecret` is empty (default), a secret named `{release-name}-connection` is created with a `conn` key. When set, the chart reads that secret. It accepts either a `conn` key with a full URI or individual keys (`host`, `port`, `username`, `password`, `database`) that override `postgres.*` values. + +**Init container** — Enabled by default. Waits for PG readiness, downloads and applies the schema (from the chart's `appVersion` URL), and seeds client IDs if `clientIdSecret` is set. Override with `postgres.initContainer.schemaUrl`. + +**Replicas** — Only apply with PostgreSQL (`replicas.enabled=true`, `replicas.count=N`). SQLite is single-replica. ## Secrets -The chart expects pre-created secrets referenced by name: - ### Client ID Secret +Restrict which client IDs the server accepts. Create a Secret with comma-separated UUIDs (base64-encoded) under a `client-ids` key: + ```yaml apiVersion: v1 kind: Secret @@ -39,22 +66,73 @@ data: client-ids: ``` -Reference it via `clientIdSecret: "my-client-ids"`. +Reference via `clientIdSecret: "my-client-ids"`. -### PostgreSQL Secret +## Networking -For PostgreSQL, the chart can automatically create a secret with the connection string, or use an existing secret. +The chart does not implement TLS. Terminate TLS at the ingress or gateway. -**Automatic Secret Creation**: -- When `postgres.existingSecret` is empty (default), the chart automatically creates a secret -- Secret is named using Helm naming convention: `release-name-taskchampion-sync-server` -- Secret contains only a `connection` key with the built connection string +### Service -**Existing Secret Usage**: -- When `postgres.existingSecret` is provided, the chart uses that secret -- The secret **must** contain a `connection` key with the PostgreSQL connection string -- If the secret doesn't have a `connection` key, the deployment will fail with a clear error +| Parameter | Default | Description | +|-----------|---------|-------------| +| `service.type` | `ClusterIP` | Service type | +| `service.port` | `8080` | Service port | +| `service.targetPort` | `8080` | Container port | -## Configuration +### Ingress (NGINX) -See [values.yaml](values.yaml) for all configurable options. +| Parameter | Default | Description | +|-----------|---------|-------------| +| `ingress.enabled` | `false` | Enable NGINX ingress | +| `ingress.className` | `""` | Ingress class name | +| `ingress.annotations` | `{}` | Ingress annotations | +| `ingress.hosts` | `[]` | Host list | +| `ingress.tls` | `[]` | TLS configuration | + +### HTTPRoute (Kubernetes Gateway API) + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `httpRoute.enabled` | `false` | Enable HTTPRoute | +| `httpRoute.parentRefs` | `[]` | Parent gateway references (primary) | +| `httpRoute.hostnames` | `[]` | Hostnames | +| `httpRoute.rules` | `[]` | Routing rules | +| `httpRoute.gateway` | `""` | (Deprecated) Single gateway name | +| `httpRoute.host` | `""` | (Deprecated) Single hostname | +| `httpRoute.path` | `"/"` | (Deprecated) Single path | +| `httpRoute.port` | `8080` | (Deprecated) Single port | + +**Recommended** — use `parentRefs`, `hostnames`, `rules`. The deprecated +single-value fields (`gateway`, `host`, `path`, `port`) are used as a fallback +when the arrays are empty. + +## ServiceAccount and RBAC + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `serviceAccount.create` | `true` | Create SA, Role, and RoleBinding | +| `serviceAccount.name` | `""` | Use existing SA name | + +When created, the chart provisions a ServiceAccount, a Role with +`get`/`create`/`update`/`patch` on secrets, and a RoleBinding. + +## Image Configuration + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `image.repo` | `ghcr.io/gothenburgbitfactory/taskchampion-sync-server` | Image repository | +| `image.tag` | `"0.7.0"` | Image tag | +| `image.pullPolicy` | `IfNotPresent` | Pull policy | +| `image.pullSecrets` | `[]` | Pull secrets | + +PostgreSQL appends `-postgres` to the image repo automatically. + +## Environment Variables + +Custom env vars are passed via `env`. `DATA_DIR` (SQLite) and `conn` +(PostgreSQL) are set automatically and must not be set manually. + +## Full Configuration + +See [values.yaml](values.yaml).