ci: add helm chart

scarlett
NGPixel 1 day ago
parent 44188e8f10
commit e4e5762032
No known key found for this signature in database

@ -29,6 +29,7 @@ jobs:
run: |
yq -iP '.version = strenv(REL_VERSION)' backend/package.json -o json
yq -iP '.version = strenv(REL_VERSION)' frontend/package.json -o json
yq -i '.version = strenv(REL_VERSION) | .appVersion = strenv(REL_VERSION)' dev/chart/Chart.yaml
- name: Upload translations source file
uses: crowdin/github-action@v3
@ -99,6 +100,19 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
# After the image push, so that no published chart ever names an image that is not there
- name: Set up Helm
uses: azure/setup-helm@v4
- name: Package and push Helm chart
env:
REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
helm lint --strict dev/chart
helm package dev/chart --destination _chart
echo "$REGISTRY_TOKEN" | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
helm push "_chart/wiki-${REL_VERSION}.tgz" oci://ghcr.io/requarks/charts
- name: Prepare build archive
run: |
mkdir -p _dist/blocks

@ -33,8 +33,9 @@ The backend is **TypeScript 7**; `frontend/` and `blocks/` are JavaScript. See
`frontend/vite.config.js` in dev mode to learn the proxy target port.
- `assets/` — **build output** of the frontend (`vite build` writes here), plus static assets under
`assets/_assets/`. Served by the backend. Don't hand-edit.
- `dev/` — deployment/packaging artifacts: `dev/build/Dockerfile` (production image), `dev/helm/`,
`dev/packer/`.
- `dev/` — deployment/packaging artifacts: `dev/build/Dockerfile` (production image), `dev/chart/`
(the 3.x Helm chart, published as an OCI artifact — its `README.md` is the reference), `dev/packer/`.
`dev/helm/` is the 2.x chart and nothing for 3.x should be built on it.
- `.devcontainer/` — VS Code dev container (app + postgres + pgAdmin + mailpit via docker-compose).
Mailpit is the mail server for development: it accepts everything and delivers nothing, so a
confirmation link or a password reset lands in a web inbox at `http://localhost:8025` rather than a

@ -78,9 +78,12 @@ export default {
tasks: null as Record<string, SimpleTask> | null,
completionPromises: [] as CompletionPromise[],
async init() {
// -> `availableParallelism` rather than `cpus().length`, which counts every core of the host: in a
// container that is the whole node, while this is capped by the cgroup CPU quota (a pod's
// `limits.cpu`, rounded down) and the CPU affinity mask
this.maxWorkers =
WIKI.config.scheduler.workers === 'auto'
? os.cpus().length - 1
? os.availableParallelism() - 1
: WIKI.config.scheduler.workers
if (this.maxWorkers < 1) {
this.maxWorkers = 1

@ -97,7 +97,8 @@ bodyParserLimit: 5242880
scheduler:
# Maximum number of workers to run background cpu-intensive jobs.
# Leave 'auto' to use number of CPU cores as maximum.
# Leave 'auto' for one fewer than the CPUs available to the process (at
# least 1), which respects a container's CPU limit.
workers: auto
# ---------------------------------------------------------------------

@ -0,0 +1,11 @@
.DS_Store
.git/
.gitignore
*.swp
*.bak
*.tmp
*.orig
*~
.idea/
.vscode/
*.tgz

@ -0,0 +1,25 @@
apiVersion: v2
name: wiki
description: Wiki.js 3.x, the next-generation open source wiki
type: application
# Both overwritten by the build workflow with the release version (`3.0.0-beta.<run>`) before the
# chart is published, so that every chart version pins exactly the image built alongside it and
# upgrading the wiki is `helm upgrade --version <newer>`. Placeholders here, never bumped by hand.
version: 3.0.0-beta
# The image tag deployed when `image.tag` is left empty.
appVersion: 3.0.0-beta
# `lifecycle.preStop.sleep` (the default drain delay) is a native action from 1.30 on.
kubeVersion: '>=1.30.0-0'
home: https://js.wiki
icon: https://cdn.js.wiki/images/wikijs-butterfly.svg
sources:
- https://github.com/requarks/wiki
keywords:
- wiki
- documentation
- knowledge base
maintainers:
- name: Nicolas Giard
url: https://github.com/NGPixel
annotations:
licenses: AGPL-3.0-only

@ -0,0 +1,159 @@
# Wiki.js Helm chart
Deploys Wiki.js 3.x, with a bundled PostgreSQL 18 or an existing PostgreSQL 16+ server.
## Installing
The chart is published as an OCI artifact, so no `helm repo add` is needed:
```sh
helm install wiki oci://ghcr.io/requarks/charts/wiki --version 3.0.0-beta.<build>
```
Pass `--version` explicitly while the chart is a pre-release, because Helm skips pre-release
versions unless you name one or pass `--devel`. With no values set, you get one wiki replica
reachable inside the cluster only, backed by a bundled PostgreSQL on an 8 GiB claim. The first
start runs the database migrations; `kubectl rollout status deployment/wiki` shows when it is done.
Unless `admin.password` is set, the first login is `admin@example.com` / `12345678`, and it has to be
changed.
## Database
### Bundled
`postgresql.enabled: true` (the default) runs the official `postgres:18` image as a single
StatefulSet replica. The wiki connects as `postgresql.auth.username`, an ordinary role that owns its
own database. The `postgres` superuser is never handed to the wiki.
- **Passwords** are generated on first install and kept in the `<release>-postgresql` Secret, which
survives `helm uninstall`. Tools that render without cluster access, Argo CD among them, would
generate new passwords on every sync, so set `postgresql.auth.password` and `postgresPassword`, or
point `postgresql.auth.existingSecret` at a Secret with `password` and `postgres-password` keys.
- **Everything under `postgresql.auth` is applied once**, when the data directory is initialised.
Changing it afterwards changes what the wiki is told, not the database; alter the role to match.
- **Server settings** go in `postgresql.parameters` (passed as `-c key=value`), first-run SQL or
shell in `postgresql.initdbScripts`.
- **Major upgrades** (18 → 19) need a dump and restore, as they would anywhere. Pin a minor tag
(`postgresql.image.tag: "18.4"`) if you want upgrades to happen only when you choose.
For replication, backups and failover, run PostgreSQL with an operator (CloudNativePG, for example)
and use it as an external database.
### External
Set `postgresql.enabled: false`, then say where the server is in **one** of two ways. Fill in
`externalDatabase.connectionString` or `externalDatabase.parameters` and leave the other empty; the
chart refuses to render with both. `externalDatabase.schema` (`wiki` by default) and
`externalDatabase.ssl` apply to either.
The database user needs to own the database, or at least be allowed to create a schema in it.
#### Option 1: a connection string
Passed to the wiki as `DATABASE_URL`, so an operator's generated Secret can be used as it is. For
CloudNativePG:
```yaml
postgresql:
enabled: false
externalDatabase:
connectionString:
existingSecret: mycluster-app # created by CloudNativePG for the cluster's app database
existingSecretKey: uri
ssl:
enabled: true
existingSecret: mycluster-ca # key: ca.crt
```
`connectionString.value` takes the string itself instead, and the chart stores it in a Secret.
Either way, percent-encode special characters in the password. TLS parameters in the string
(`sslmode`, `sslrootcert`, …) replace everything under `externalDatabase.ssl`. CloudNativePG's
`uri` has none, which is why it is paired with `ssl` and the cluster's CA above.
#### Option 2: individual parameters
```yaml
postgresql:
enabled: false
externalDatabase:
parameters:
host: pg.databases.svc
database: wiki
user: wiki
existingSecret: wiki-db # key: password
ssl:
enabled: true
existingSecret: pg-ca # key: ca.crt, and optionally tls.crt / tls.key
```
## Exposing it
Both can be on at once, which is useful while moving from one to the other.
- **Gateway API**: `httpRoute.enabled`, with `parentRefs` naming your Gateway and `hostnames`.
`rules` are passed through as written, and the chart adds the `backendRefs`.
- **Ingress**: `ingress.enabled`, `className`, `hosts`, `tls`. Most controllers cap request body
size, which also caps uploads; raise the limit with the controller's own annotation
(`nginx.ingress.kubernetes.io/proxy-body-size` for ingress-nginx).
Behind either one, turn on **Admin → Security → Trust Proxy**, so the wiki records the visitor's
address rather than the proxy's.
## Replicas
`replicaCount` can be raised freely. Replicas coordinate through the database, collaborative editing
included, so no sticky sessions are needed.
The data directory (`/wiki/data`) is per replica unless `persistence` points every replica at one
ReadWriteMany claim. That does not matter for the caches it normally holds, which are rebuilt from
the database. It does matter for a **Local Disk** or **Git** storage target left at its default
location under `data/`, which would otherwise be a separate copy on each replica.
With one replica on a ReadWriteOnce claim, set `strategy.type: Recreate`. Otherwise a rolling
update's new pod may land on a node the volume cannot be attached to.
## Hardening
Both workloads run as non-root, with a read-only root filesystem, every capability dropped, no
privilege escalation, `RuntimeDefault` seccomp and no service account token. The wiki writes only to
`/wiki/data`, `/tmp` and `/home/node`; PostgreSQL writes only to its data volume,
`/var/run/postgresql`, `/tmp` and `/dev/shm`.
The one thing the read-only root filesystem rules out is installing an extension from
**Admin → Extensions**, which runs `npm install` inside the image. Puppeteer is already in the
image; to add anything else, build an image `FROM` this one.
## Health and shutdown
`/_live` backs the startup and liveness probes, `/_ready` the readiness probe. The startup probe
allows five minutes for migrations before liveness takes over. `KUBERNETES_SERVICE_HOST` is set on
the container. It switches the wiki's shutdown to Kubernetes semantics: on SIGTERM `/_ready` turns
503 while in-flight and still-routed requests keep being served. The default `preStop` sleep gives
load balancers five seconds to drop the pod first.
## Upgrading
Every build of the wiki publishes a chart of the same version, `3.0.0-beta.<build>`, whose
`appVersion` is that build's image. Upgrading the wiki is therefore upgrading the chart:
```sh
helm upgrade wiki oci://ghcr.io/requarks/charts/wiki --version 3.0.0-beta.<newer> -f my-values.yaml
```
`helm rollback` returns to the previous image along with everything else. Leave `image.tag` unset,
since setting it pins the image no matter which chart version is installed.
## Publishing
The build workflow (`.github/workflows/build.yml`) publishes the chart. It writes the release
version into `version` and `appVersion` in `Chart.yaml`, and pushes the chart to
`oci://ghcr.io/requarks/charts` once the image is up. The two values committed in `Chart.yaml` are
placeholders, so nothing is bumped by hand.
To try a change locally:
```sh
helm lint --strict dev/chart
helm template wiki dev/chart -f my-values.yaml
```

@ -0,0 +1,54 @@
Wiki.js {{ .Values.image.tag | default .Chart.AppVersion }} is being deployed as {{ include "wiki.fullname" . }}.
{{- if .Values.httpRoute.enabled }}
It is routed through {{ range $i, $p := .Values.httpRoute.parentRefs }}{{ if $i }}, {{ end }}Gateway {{ $p.name }}{{ end }} for:
{{- range .Values.httpRoute.hostnames }}
{{ . }}
{{- end }}
{{- end }}
{{- if .Values.ingress.enabled }}
It is served through the Ingress at:
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- end }}
{{- if not (or .Values.httpRoute.enabled .Values.ingress.enabled) }}
It is reachable inside the cluster only. To open it from this machine:
kubectl --namespace {{ .Release.Namespace }} port-forward service/{{ include "wiki.fullname" . }} 8080:{{ .Values.service.port }}
and browse to http://localhost:8080.
{{- end }}
The first start runs the database migrations, which takes a little while:
kubectl --namespace {{ .Release.Namespace }} rollout status deployment/{{ include "wiki.fullname" . }}
{{- if not (or .Values.admin.password .Values.admin.existingSecret) }}
Sign in as {{ .Values.admin.email | default "admin@example.com" }} with the password 12345678; you will be asked to change it.
{{- end }}
{{- if or .Values.httpRoute.enabled .Values.ingress.enabled }}
Behind a Gateway or an Ingress, turn on Admin → Security → Trust Proxy, so that the wiki sees the
visitor's address rather than the proxy's.
{{- end }}
{{- if and .Values.postgresql.enabled (not .Values.postgresql.auth.existingSecret) (not .Values.postgresql.auth.password) }}
The database passwords were generated and are kept in Secret {{ include "wiki.postgresql.fullname" . }}.
{{- end }}
{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled (not (has "ReadWriteMany" .Values.persistence.accessModes)) }}
WARNING: {{ .Values.replicaCount }} replicas share a data claim that is not ReadWriteMany. Replicas scheduled
on different nodes will not be able to mount it.
{{- end }}
{{- if and (gt (int .Values.replicaCount) 1) (not .Values.persistence.enabled) }}
Note: each of the {{ .Values.replicaCount }} replicas has a data directory of its own. That is fine for the caches it
holds, but a Local Disk or Git storage target would be a separate copy on each replica.
{{- end }}

@ -0,0 +1,253 @@
{{/* Chart name, truncated to fit a DNS label. */}}
{{- define "wiki.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Fully qualified app name. Truncated to 49 rather than 63 so that the longest suffix added to it
(`-postgresql-hl`) still fits in a DNS label.
*/}}
{{- define "wiki.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 49 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 49 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 49 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "wiki.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "wiki.commonLabels" -}}
helm.sh/chart: {{ include "wiki.chart" . }}
app.kubernetes.io/name: {{ include "wiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: wiki
{{- end }}
{{/*
The component is part of both selectors on purpose: without it, the wiki's Service and Deployment
would select the PostgreSQL pod too, which carries the same name and instance labels.
*/}}
{{- define "wiki.selectorLabels" -}}
app.kubernetes.io/name: {{ include "wiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: wiki
{{- end }}
{{- define "wiki.labels" -}}
{{ include "wiki.commonLabels" . }}
app.kubernetes.io/component: wiki
{{- end }}
{{- define "wiki.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "wiki.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/* `repository:tag`, or `repository@digest` when a digest is given. Takes the image dict and a default tag. */}}
{{- define "wiki.imageRef" -}}
{{- $img := index . 0 }}
{{- if $img.digest }}
{{- printf "%s@%s" $img.repository $img.digest }}
{{- else }}
{{- printf "%s:%s" $img.repository (toString (index . 1)) }}
{{- end }}
{{- end }}
{{- define "wiki.image" -}}
{{- include "wiki.imageRef" (list .Values.image (.Values.image.tag | default .Chart.AppVersion)) }}
{{- end }}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{/* PostgreSQL */}}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{- define "wiki.postgresql.fullname" -}}
{{- printf "%s-postgresql" (include "wiki.fullname" .) }}
{{- end }}
{{- define "wiki.postgresql.selectorLabels" -}}
app.kubernetes.io/name: {{ include "wiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: postgresql
{{- end }}
{{- define "wiki.postgresql.labels" -}}
helm.sh/chart: {{ include "wiki.chart" . }}
app.kubernetes.io/name: {{ include "wiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Values.postgresql.image.tag | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: wiki
app.kubernetes.io/component: postgresql
{{- end }}
{{- define "wiki.postgresql.image" -}}
{{- include "wiki.imageRef" (list .Values.postgresql.image .Values.postgresql.image.tag) }}
{{- end }}
{{- define "wiki.postgresql.secretName" -}}
{{- .Values.postgresql.auth.existingSecret | default (include "wiki.postgresql.fullname" .) }}
{{- end }}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{/* The database the wiki connects to, bundled or external */}}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{- define "wiki.db.host" -}}
{{- if .Values.postgresql.enabled }}
{{- include "wiki.postgresql.fullname" . }}
{{- else }}
{{- .Values.externalDatabase.parameters.host }}
{{- end }}
{{- end }}
{{- define "wiki.db.port" -}}
{{- if .Values.postgresql.enabled }}
{{- .Values.postgresql.service.port }}
{{- else }}
{{- .Values.externalDatabase.parameters.port }}
{{- end }}
{{- end }}
{{- define "wiki.db.name" -}}
{{- ternary .Values.postgresql.auth.database .Values.externalDatabase.parameters.database .Values.postgresql.enabled }}
{{- end }}
{{- define "wiki.db.user" -}}
{{- ternary .Values.postgresql.auth.username .Values.externalDatabase.parameters.user .Values.postgresql.enabled }}
{{- end }}
{{- define "wiki.db.schema" -}}
{{- ternary .Values.postgresql.schema .Values.externalDatabase.schema .Values.postgresql.enabled }}
{{- end }}
{{/* The Secret and key the wiki reads its database password from. */}}
{{- define "wiki.db.secretName" -}}
{{- if .Values.postgresql.enabled }}
{{- include "wiki.postgresql.secretName" . }}
{{- else if .Values.externalDatabase.parameters.existingSecret }}
{{- .Values.externalDatabase.parameters.existingSecret }}
{{- else }}
{{- printf "%s-db" (include "wiki.fullname" .) }}
{{- end }}
{{- end }}
{{- define "wiki.db.secretKey" -}}
{{- if .Values.postgresql.enabled }}
{{- .Values.postgresql.auth.secretKeys.userPasswordKey }}
{{- else if .Values.externalDatabase.parameters.existingSecret }}
{{- .Values.externalDatabase.parameters.existingSecretPasswordKey }}
{{- else -}}
password
{{- end }}
{{- end }}
{{/*
Whether the wiki is handed a connection string (DATABASE_URL) rather than individual parameters.
Truthy or empty, for `if`.
*/}}
{{- define "wiki.db.useUrl" -}}
{{- $url := .Values.externalDatabase.connectionString }}
{{- if and (not .Values.postgresql.enabled) (or $url.value $url.existingSecret) }}true{{ end }}
{{- end }}
{{/* The Secret and key the connection string is read from. */}}
{{- define "wiki.db.urlSecretName" -}}
{{- .Values.externalDatabase.connectionString.existingSecret | default (printf "%s-db" (include "wiki.fullname" .)) }}
{{- end }}
{{- define "wiki.db.urlSecretKey" -}}
{{- if .Values.externalDatabase.connectionString.existingSecret }}
{{- .Values.externalDatabase.connectionString.existingSecretKey }}
{{- else -}}
url
{{- end }}
{{- end }}
{{- define "wiki.db.tlsEnabled" -}}
{{- if and (not .Values.postgresql.enabled) .Values.externalDatabase.ssl.enabled }}true{{ end }}
{{- end }}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{/* Generated secrets */}}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{/*
A password: the value given, else the one already stored in the Secret, else a new random one. The
lookup is what keeps a generated password across `helm upgrade`; it returns nothing to a render that
has no cluster access (`helm template`, Argo CD), which is why those should be given passwords.
Takes (list $ secretName key value).
*/}}
{{- define "wiki.secretValue" -}}
{{- $ctx := index . 0 }}
{{- $name := index . 1 }}
{{- $key := index . 2 }}
{{- $given := index . 3 }}
{{- if $given }}
{{- $given | b64enc }}
{{- else }}
{{- $existing := lookup "v1" "Secret" $ctx.Release.Namespace $name }}
{{- if and $existing (hasKey (default dict $existing.data) $key) }}
{{- index $existing.data $key }}
{{- else }}
{{- randAlphaNum 32 | b64enc }}
{{- end }}
{{- end }}
{{- end }}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{/* Validation */}}
{{/* ---------------------------------------------------------------------------------------------- */}}
{{- define "wiki.validate" -}}
{{- if hasKey .Values.config "db" }}
{{- fail "config.db is set by the chart: configure the database under postgresql or externalDatabase instead" }}
{{- end }}
{{- range $key := list "port" "bindIP" "dataPath" }}
{{- if hasKey $.Values.config $key }}
{{- fail (printf "config.%s is set by the chart and cannot be overridden" $key) }}
{{- end }}
{{- end }}
{{- if and .Values.postgresql.enabled (eq .Values.postgresql.auth.username "postgres") }}
{{- fail "postgresql.auth.username must not be \"postgres\": the wiki connects as its own role, not as the superuser" }}
{{- end }}
{{- if not .Values.postgresql.enabled }}
{{- $url := .Values.externalDatabase.connectionString }}
{{- $params := .Values.externalDatabase.parameters }}
{{- if and $url.value $url.existingSecret }}
{{- fail "externalDatabase.connectionString: set value or existingSecret, not both" }}
{{- end }}
{{- $hasUrl := or $url.value $url.existingSecret }}
{{- $hasParams := or $params.host $params.password $params.existingSecret }}
{{- if and $hasUrl $hasParams }}
{{- fail "externalDatabase: use connectionString or parameters, not both — empty the one you are not using" }}
{{- end }}
{{- if not (or $hasUrl $hasParams) }}
{{- fail "externalDatabase: set either connectionString or parameters when postgresql.enabled is false" }}
{{- end }}
{{- if $hasParams }}
{{- if not $params.host }}
{{- fail "externalDatabase.parameters.host is required" }}
{{- end }}
{{- if not (or $params.password $params.existingSecret) }}
{{- fail "externalDatabase.parameters: password or existingSecret is required" }}
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.externalDatabase.ssl.existingSecret (ne (empty .Values.externalDatabase.ssl.certKey) (empty .Values.externalDatabase.ssl.keyKey)) }}
{{- fail "externalDatabase.ssl.certKey and externalDatabase.ssl.keyKey go together: set both for a client certificate, or neither" }}
{{- end }}
{{- end }}

@ -0,0 +1,48 @@
{{- include "wiki.validate" . }}
{{- $config := deepCopy .Values.config }}
{{- $_ := set $config "port" 3000 }}
{{- $_ := set $config "bindIP" "0.0.0.0" }}
{{- $_ := set $config "dataPath" "/wiki/data" }}
{{- $ssl := .Values.externalDatabase.ssl }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "wiki.fullname" . }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
data:
config.yml: |
{{- toYaml $config | nindent 4 }}
db:
{{- if include "wiki.db.useUrl" . }}
# Connecting through DATABASE_URL, which takes the place of host, port, user, pass and db.
{{- else }}
host: {{ include "wiki.db.host" . | toJson }}
port: {{ include "wiki.db.port" . }}
user: {{ include "wiki.db.user" . | toJson }}
# Substituted from the environment when the file is read. A block scalar rather than a quoted
# string, so that no character a password may contain can end it early.
pass: |2-
$(DB_PASS)
db: {{ include "wiki.db.name" . | toJson }}
{{- end }}
schema: {{ include "wiki.db.schema" . | toJson }}
{{- if include "wiki.db.tlsEnabled" . }}
ssl: true
sslOptions:
{{- if or $ssl.existingSecret (not $ssl.rejectUnauthorized) }}
auto: false
rejectUnauthorized: {{ $ssl.rejectUnauthorized }}
{{- if $ssl.existingSecret }}
ca: /etc/wiki/db-tls/{{ $ssl.caKey }}
{{- if $ssl.certKey }}
cert: /etc/wiki/db-tls/{{ $ssl.certKey }}
key: /etc/wiki/db-tls/{{ $ssl.keyKey }}
{{- end }}
{{- end }}
{{- else }}
auto: true
{{- end }}
{{- else }}
ssl: false
{{- end }}

@ -0,0 +1,228 @@
{{- $ssl := .Values.externalDatabase.ssl }}
{{- $adminSecret := .Values.admin.existingSecret | default (printf "%s-admin" (include "wiki.fullname" .)) }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "wiki.fullname" . }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
{{- with .Values.strategy }}
strategy:
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "wiki.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
# Rolls the pods when config.yml changes, since nothing in the pod spec would otherwise.
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "wiki.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
serviceAccountName: {{ include "wiki.serviceAccountName" . }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
# Load-bearing, not tidiness: service links put `<SERVICE>_PORT=tcp://…` in the environment of
# every pod for every service in the namespace, and the wiki reads `WIKI_PORT` as the port to
# listen on — so a Service named `wiki` would take the whole pod down.
enableServiceLinks: false
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
{{- if .Values.waitForDatabase.enabled }}
initContainers:
# The wiki image is used rather than a second one, and asked only whether the port accepts a
# connection: a bundled server opens it only once initialisation is over.
- name: wait-for-db
image: {{ include "wiki.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- node
- -e
- |
const net = require('node:net')
// Only the host and port of a connection string are ever read or printed; it carries the password.
const url = process.env.DATABASE_URL ? new URL(process.env.DATABASE_URL) : null
const host = url ? url.hostname.replace(/^\[|\]$/g, '') : process.env.DB_HOST
const port = Number(url ? url.port || 5432 : process.env.DB_PORT)
const attempt = () => {
const socket = net.connect({ host, port, timeout: 3000 })
socket.once('connect', () => { console.info(`${host}:${port} is accepting connections`); socket.destroy(); process.exit(0) })
const retry = (err) => { console.info(`Waiting for ${host}:${port}... (${err?.code ?? 'timeout'})`); socket.destroy(); setTimeout(attempt, 2000) }
socket.once('error', retry)
socket.once('timeout', retry)
}
attempt()
env:
{{- if include "wiki.db.useUrl" . }}
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "wiki.db.urlSecretName" . }}
key: {{ include "wiki.db.urlSecretKey" . }}
{{- else }}
- name: DB_HOST
value: {{ include "wiki.db.host" . | quote }}
- name: DB_PORT
value: {{ include "wiki.db.port" . | quote }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- with .Values.waitForDatabase.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
containers:
- name: wiki
image: {{ include "wiki.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 3000
protocol: TCP
env:
- name: CONFIG_FILE
value: /etc/wiki/config.yml
# Switches the health endpoints to Kubernetes semantics: a replica shutting down reports
# not ready but keeps serving what is still routed to it. The kubelet normally provides this
# variable already; it is set here so the behaviour does not rest on that, and to a name
# that still reaches the API server should anything in the pod ever use it.
- name: KUBERNETES_SERVICE_HOST
value: kubernetes.default.svc
{{- if include "wiki.db.useUrl" . }}
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "wiki.db.urlSecretName" . }}
key: {{ include "wiki.db.urlSecretKey" . }}
{{- else }}
- name: DB_PASS
valueFrom:
secretKeyRef:
name: {{ include "wiki.db.secretName" . }}
key: {{ include "wiki.db.secretKey" . }}
{{- end }}
{{- with .Values.admin.email }}
- name: ADMIN_EMAIL
value: {{ . | quote }}
{{- end }}
{{- if or .Values.admin.password .Values.admin.existingSecret }}
- name: ADMIN_PASS
valueFrom:
secretKeyRef:
name: {{ $adminSecret }}
key: {{ ternary .Values.admin.existingSecretPasswordKey "password" (not (empty .Values.admin.existingSecret)) }}
{{- end }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.extraEnvFrom }}
envFrom:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.startupProbe }}
startupProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.lifecycle }}
lifecycle:
{{- toYaml . | nindent 12 }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: config
mountPath: /etc/wiki
readOnly: true
- name: data
mountPath: /wiki/data
# The root filesystem is read-only; these are what the wiki, git, ssh and Chromium write to
# besides the data directory.
- name: tmp
mountPath: /tmp
- name: home
mountPath: /home/node
{{- if and (include "wiki.db.tlsEnabled" .) $ssl.existingSecret }}
- name: db-tls
mountPath: /etc/wiki/db-tls
readOnly: true
{{- end }}
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "wiki.fullname" . }}
- name: data
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim | default (printf "%s-data" (include "wiki.fullname" .)) }}
{{- else }}
{{- with .Values.persistence.sizeLimit }}
emptyDir:
sizeLimit: {{ . }}
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
- name: tmp
emptyDir: {}
- name: home
emptyDir: {}
{{- if and (include "wiki.db.tlsEnabled" .) $ssl.existingSecret }}
- name: db-tls
secret:
secretName: {{ $ssl.existingSecret }}
# Owned by root and readable through fsGroup, which 0400 would shut out.
defaultMode: 0440
{{- end }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -0,0 +1,29 @@
{{- if .Values.httpRoute.enabled }}
{{- $fullname := include "wiki.fullname" . }}
{{- $port := .Values.service.port }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ $fullname }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
{{- with .Values.httpRoute.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.httpRoute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
parentRefs:
{{- toYaml (required "httpRoute.parentRefs needs at least one Gateway" .Values.httpRoute.parentRefs) | nindent 4 }}
{{- with .Values.httpRoute.hostnames }}
hostnames:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
{{- range .Values.httpRoute.rules }}
{{- $rule := merge (dict "backendRefs" (list (dict "name" $fullname "port" $port))) (omit (default dict .) "backendRefs") }}
- {{ toYaml $rule | nindent 6 | trim }}
{{- end }}
{{- end }}

@ -0,0 +1,41 @@
{{- if .Values.ingress.enabled }}
{{- $fullname := include "wiki.fullname" . }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullname }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
{{- with .Values.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- with .Values.ingress.tls }}
tls:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $fullname }}
port:
name: http
{{- end }}
{{- with .host }}
host: {{ . | quote }}
{{- end }}
{{- end }}
{{- end }}

@ -0,0 +1,17 @@
{{- if .Values.podDisruptionBudget.enabled }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "wiki.fullname" . }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
spec:
{{- if .Values.podDisruptionBudget.maxUnavailable }}
maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }}
{{- else }}
minAvailable: {{ .Values.podDisruptionBudget.minAvailable }}
{{- end }}
selector:
matchLabels:
{{- include "wiki.selectorLabels" . | nindent 6 }}
{{- end }}

@ -0,0 +1,26 @@
{{- if .Values.postgresql.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "wiki.postgresql.fullname" . }}-initdb
labels:
{{- include "wiki.postgresql.labels" . | nindent 4 }}
data:
# The wiki's own role and database, owned by it so that it can create its schema — and nothing more.
# Values reach psql as variables, quoted by psql itself, so none of them is ever spliced into SQL.
00-wiki.sh: |
#!/bin/bash
set -Eeo pipefail
psql -v ON_ERROR_STOP=1 --no-psqlrc --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
--set app_user="$WIKI_DB_USER" \
--set app_password="$WIKI_DB_PASSWORD" \
--set app_db="$WIKI_DB_NAME" <<'EOSQL'
CREATE ROLE :"app_user" LOGIN PASSWORD :'app_password';
CREATE DATABASE :"app_db" OWNER :"app_user";
REVOKE ALL ON DATABASE :"app_db" FROM PUBLIC;
EOSQL
{{- range $file, $content := .Values.postgresql.initdbScripts }}
{{ $file }}: |
{{- $content | nindent 4 }}
{{- end }}
{{- end }}

@ -0,0 +1,18 @@
{{- if and .Values.postgresql.enabled (not .Values.postgresql.auth.existingSecret) }}
{{- $name := include "wiki.postgresql.fullname" . }}
{{- $keys := .Values.postgresql.auth.secretKeys }}
apiVersion: v1
kind: Secret
metadata:
name: {{ $name }}
labels:
{{- include "wiki.postgresql.labels" . | nindent 4 }}
annotations:
# Deleting this with the release would lose the only record of a generated password, for a
# database whose claim outlives the release.
helm.sh/resource-policy: keep
type: Opaque
data:
{{ $keys.userPasswordKey }}: {{ include "wiki.secretValue" (list . $name $keys.userPasswordKey .Values.postgresql.auth.password) | quote }}
{{ $keys.adminPasswordKey }}: {{ include "wiki.secretValue" (list . $name $keys.adminPasswordKey .Values.postgresql.auth.postgresPassword) | quote }}
{{- end }}

@ -0,0 +1,44 @@
{{- if .Values.postgresql.enabled }}
{{- $svc := .Values.postgresql.service }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "wiki.postgresql.fullname" . }}
labels:
{{- include "wiki.postgresql.labels" . | nindent 4 }}
{{- with $svc.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with $svc.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ $svc.type }}
ports:
- name: postgresql
port: {{ $svc.port }}
targetPort: postgresql
protocol: TCP
selector:
{{- include "wiki.postgresql.selectorLabels" . | nindent 4 }}
---
# The StatefulSet's governing service, which gives the pod its stable DNS name.
apiVersion: v1
kind: Service
metadata:
name: {{ include "wiki.postgresql.fullname" . }}-hl
labels:
{{- include "wiki.postgresql.labels" . | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: postgresql
port: {{ $svc.port }}
targetPort: postgresql
protocol: TCP
selector:
{{- include "wiki.postgresql.selectorLabels" . | nindent 4 }}
{{- end }}

@ -0,0 +1,195 @@
{{- if .Values.postgresql.enabled }}
{{- $pg := .Values.postgresql }}
{{- $secret := include "wiki.postgresql.secretName" . }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "wiki.postgresql.fullname" . }}
labels:
{{- include "wiki.postgresql.labels" . | nindent 4 }}
spec:
# One server. A replicated PostgreSQL is a job for an operator (CloudNativePG and the like), used
# through `externalDatabase`.
replicas: 1
serviceName: {{ include "wiki.postgresql.fullname" . }}-hl
{{- with $pg.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if and $pg.persistence.enabled (not $pg.persistence.existingClaim) }}
persistentVolumeClaimRetentionPolicy:
{{- toYaml $pg.persistence.retentionPolicy | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "wiki.postgresql.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/initdb: {{ include (print $.Template.BasePath "/postgresql/configmap.yaml") . | sha256sum }}
{{- with $pg.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "wiki.postgresql.labels" . | nindent 8 }}
{{- with $pg.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
automountServiceAccountToken: false
enableServiceLinks: false
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $pg.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
securityContext:
{{- toYaml $pg.podSecurityContext | nindent 8 }}
# The official image declares SIGINT as its stop signal, which the container runtime sends in
# place of SIGTERM: a fast shutdown, where SIGTERM would wait for every client to disconnect.
terminationGracePeriodSeconds: {{ $pg.terminationGracePeriodSeconds }}
containers:
- name: postgresql
image: {{ include "wiki.postgresql.image" . }}
imagePullPolicy: {{ $pg.image.pullPolicy }}
args:
- postgres
{{- range $key, $value := $pg.parameters }}
- -c
- {{ printf "%s=%v" $key $value | quote }}
{{- end }}
{{- range $pg.extraArgs }}
- {{ . | quote }}
{{- end }}
ports:
- name: postgresql
containerPort: 5432
protocol: TCP
env:
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ $secret }}
key: {{ $pg.auth.secretKeys.adminPasswordKey }}
{{- with $pg.initdbArgs }}
- name: POSTGRES_INITDB_ARGS
value: {{ . | quote }}
{{- end }}
# Read by the first-run script that creates the wiki's role and database.
- name: WIKI_DB_USER
value: {{ $pg.auth.username | quote }}
- name: WIKI_DB_NAME
value: {{ $pg.auth.database | quote }}
- name: WIKI_DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ $secret }}
key: {{ $pg.auth.secretKeys.userPasswordKey }}
{{- with $pg.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with $pg.startupProbe }}
startupProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with $pg.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with $pg.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
securityContext:
{{- toYaml $pg.securityContext | nindent 12 }}
{{- with $pg.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
# The parent of PGDATA rather than PGDATA itself, as the image expects from 18 on
# (/var/lib/postgresql/18/docker): the version is part of the path, and the data directory
# is never the root of the volume, where a lost+found would make initdb refuse it.
- name: data
mountPath: /var/lib/postgresql
- name: run
mountPath: /var/run/postgresql
- name: tmp
mountPath: /tmp
- name: initdb
mountPath: /docker-entrypoint-initdb.d
readOnly: true
{{- if $pg.shm.enabled }}
- name: shm
mountPath: /dev/shm
{{- end }}
{{- with $pg.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: run
emptyDir: {}
- name: tmp
emptyDir: {}
- name: initdb
configMap:
name: {{ include "wiki.postgresql.fullname" . }}-initdb
defaultMode: 0555
{{- if $pg.shm.enabled }}
- name: shm
emptyDir:
medium: Memory
{{- with $pg.shm.sizeLimit }}
sizeLimit: {{ . }}
{{- end }}
{{- end }}
{{- if not $pg.persistence.enabled }}
- name: data
emptyDir: {}
{{- else if $pg.persistence.existingClaim }}
- name: data
persistentVolumeClaim:
claimName: {{ $pg.persistence.existingClaim }}
{{- end }}
{{- with $pg.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $pg.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $pg.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $pg.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if and $pg.persistence.enabled (not $pg.persistence.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{- include "wiki.postgresql.selectorLabels" . | nindent 10 }}
{{- with $pg.persistence.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes:
{{- toYaml $pg.persistence.accessModes | nindent 10 }}
{{- if $pg.persistence.storageClass }}
storageClassName: {{ ternary "" $pg.persistence.storageClass (eq $pg.persistence.storageClass "-") | quote }}
{{- end }}
resources:
requests:
storage: {{ $pg.persistence.size }}
{{- end }}
{{- end }}

@ -0,0 +1,25 @@
{{- $p := .Values.persistence }}
{{- if and $p.enabled (not $p.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "wiki.fullname" . }}-data
labels:
{{- include "wiki.labels" . | nindent 4 }}
annotations:
# Uninstalling the release leaves the claim behind, since it may be the only copy of a Local Disk
# or Git storage target.
helm.sh/resource-policy: keep
{{- with $p.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
{{- toYaml $p.accessModes | nindent 4 }}
{{- if $p.storageClass }}
storageClassName: {{ ternary "" $p.storageClass (eq $p.storageClass "-") | quote }}
{{- end }}
resources:
requests:
storage: {{ $p.size }}
{{- end }}

@ -0,0 +1,32 @@
{{- $ext := .Values.externalDatabase }}
{{- $useUrl := include "wiki.db.useUrl" . }}
{{- $dbUrl := and $useUrl $ext.connectionString.value }}
{{- $dbPassword := and (not .Values.postgresql.enabled) (not $useUrl) (not $ext.parameters.existingSecret) }}
{{- $adminPassword := and .Values.admin.password (not .Values.admin.existingSecret) }}
{{- if or $dbUrl $dbPassword }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "wiki.fullname" . }}-db
labels:
{{- include "wiki.labels" . | nindent 4 }}
type: Opaque
data:
{{- if $dbUrl }}
url: {{ $ext.connectionString.value | b64enc | quote }}
{{- else }}
password: {{ $ext.parameters.password | b64enc | quote }}
{{- end }}
{{- end }}
{{- if $adminPassword }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "wiki.fullname" . }}-admin
labels:
{{- include "wiki.labels" . | nindent 4 }}
type: Opaque
data:
password: {{ .Values.admin.password | b64enc | quote }}
{{- end }}

@ -0,0 +1,39 @@
{{- $svc := .Values.service }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "wiki.fullname" . }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
{{- with $svc.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with $svc.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ $svc.type }}
{{- if and (eq $svc.type "LoadBalancer") $svc.loadBalancerClass }}
loadBalancerClass: {{ $svc.loadBalancerClass }}
{{- end }}
{{- if and (eq $svc.type "LoadBalancer") $svc.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- toYaml $svc.loadBalancerSourceRanges | nindent 4 }}
{{- end }}
{{- if and (has $svc.type (list "NodePort" "LoadBalancer")) $svc.externalTrafficPolicy }}
externalTrafficPolicy: {{ $svc.externalTrafficPolicy }}
{{- end }}
{{- with $svc.sessionAffinity }}
sessionAffinity: {{ . }}
{{- end }}
ports:
- name: http
port: {{ $svc.port }}
targetPort: http
protocol: TCP
{{- if and (has $svc.type (list "NodePort" "LoadBalancer")) $svc.nodePort }}
nodePort: {{ $svc.nodePort }}
{{- end }}
selector:
{{- include "wiki.selectorLabels" . | nindent 4 }}

@ -1,4 +1,4 @@
{{- if .Values.serviceAccount.create -}}
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
@ -9,4 +9,5 @@ metadata:
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end -}}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}

@ -0,0 +1,39 @@
apiVersion: v1
kind: Pod
metadata:
name: {{ include "wiki.fullname" . }}-test
labels:
{{- include "wiki.commonLabels" . | nindent 4 }}
app.kubernetes.io/component: test
annotations:
helm.sh/hook: test
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
spec:
restartPolicy: Never
automountServiceAccountToken: false
enableServiceLinks: false
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 4 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 4 }}
containers:
# Asked through the Service, so that it tests the selector as well as the wiki.
- name: ready
image: {{ include "wiki.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- node
- -e
- |
const url = 'http://{{ include "wiki.fullname" . }}:{{ .Values.service.port }}/_ready'
fetch(url).then((res) => {
console.info(`${url} → ${res.status}`)
process.exit(res.ok ? 0 : 1)
}, (err) => {
console.error(`${url} → ${err.cause?.code ?? err.message}`)
process.exit(1)
})
securityContext:
{{- toYaml .Values.securityContext | nindent 8 }}

@ -0,0 +1,462 @@
# Wiki.js 3.x
#
# Every key below is optional. With none of them set, the chart runs one wiki replica against a
# bundled PostgreSQL 18, reachable inside the cluster only — turn on `ingress` or `httpRoute` to
# expose it.
nameOverride: ''
fullnameOverride: ''
image:
repository: ghcr.io/requarks/wiki
# Defaults to the chart's appVersion.
tag: ''
# Pins the image by digest (`sha256:…`), taking precedence over the tag.
digest: ''
pullPolicy: IfNotPresent
imagePullSecrets: []
# Replicas share the database and find each other through it (LISTEN/NOTIFY), collaborative editing
# included, so no sticky sessions are needed. Anything kept on the data volume is per replica unless
# `persistence` points them all at one ReadWriteMany claim.
replicaCount: 1
revisionHistoryLimit: 10
# Deployment strategy. Leave empty for the default RollingUpdate; use `{ type: Recreate }` with a
# single replica on a ReadWriteOnce `persistence` claim, which a second pod on another node could
# not attach while the old one still holds it.
strategy: {}
# ---------------------------------------------------------------------------------------------------
# Wiki.js configuration
# ---------------------------------------------------------------------------------------------------
# Rendered as the instance's config.yml. Any key the file accepts can be added here (see
# config.sample.yml), except the ones the chart owns: `port`, `bindIP` and `dataPath` follow the
# container, and `db` is built from `postgresql` / `externalDatabase` below.
#
# Everything else about the wiki is configured in its administration area and kept in the database.
config:
# error, warn, info or debug
logLevel: info
# default or json
logFormat: default
# Stops every outbound request the wiki would otherwise make (Iconify, update checks, …).
offline: false
# Largest API request body accepted, in bytes. File uploads are not bound by it.
bodyParserLimit: 5242880
icons:
apiUrl: https://api.iconify.design
scheduler:
# Most worker threads for CPU-heavy background jobs. `auto` is one fewer than the CPUs the pod
# may use: its `limits.cpu`, rounded down, or every core of the node when no limit is set.
workers: auto
# The administrator account created the first time the wiki starts against an empty database. Never
# read again afterwards. Left empty, the account is admin@example.com / 12345678 and must change its
# password on first login.
admin:
email: ''
password: ''
# A Secret holding the password, in place of `password`.
existingSecret: ''
existingSecretPasswordKey: password
# Waits for the database port to open before the wiki starts. The wiki itself gives up after ~30s of
# failed connections, which a bundled PostgreSQL initialising its data directory can outlast.
waitForDatabase:
enabled: true
resources: {}
extraEnv: []
# - name: FOO
# value: bar
extraEnvFrom: []
# - secretRef:
# name: wiki-extra-env
# ---------------------------------------------------------------------------------------------------
# Pod
# ---------------------------------------------------------------------------------------------------
serviceAccount:
create: true
# Generated from the release name when empty.
name: ''
annotations: {}
# The wiki never talks to the Kubernetes API, so the pod gets no token unless asked for.
automount: false
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
# `readOnlyRootFilesystem` holds everything except installing an extension from Admin → Extensions,
# which runs `npm install` inside the image. The image already carries Puppeteer, the extension that
# needs it most; anything else would be added by building an image FROM this one.
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
privileged: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources: {}
# requests:
# cpu: 250m
# memory: 512Mi
# limits:
# memory: 2Gi
# The probes are merged with what is given here, so a single field can be overridden. To swap the
# handler, null the default one out: `livenessProbe: { httpGet: null, exec: { … } }`.
#
# `/_live` answers only once the HTTP server is listening, which is after migrations have run — the
# startup probe is what covers that, and allows 5 minutes by default.
startupProbe:
httpGet:
path: /_live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
livenessProbe:
httpGet:
path: /_live
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
# `/_ready` turns 503 as soon as a replica starts shutting down, while it goes on serving the requests
# still reaching it until the endpoint removal has propagated.
readinessProbe:
httpGet:
path: /_ready
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
# The pause before SIGTERM, so a replica being replaced is out of every load balancer before it stops
# accepting connections.
lifecycle:
preStop:
sleep:
seconds: 5
terminationGracePeriodSeconds: 30
priorityClassName: ''
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
# Added to the pod, next to the chart's own (config, data, tmp, home).
volumes: []
# - name: git-known-hosts
# configMap:
# name: git-known-hosts
# Added to the wiki container.
volumeMounts: []
# - name: git-known-hosts
# mountPath: /home/node/.ssh/known_hosts
# subPath: known_hosts
# readOnly: true
# The wiki's data directory, /wiki/data. Holds the caches (icons, served files, blocks), which rebuild
# themselves from the database, plus the default locations of the Local Disk (`data/content`) and Git
# (`data/repo`) storage targets. An emptyDir is enough unless one of those two is in use.
persistence:
enabled: false
# Use an existing claim instead of creating one.
existingClaim: ''
# `-` for the cluster's default class, empty to leave it unset.
storageClass: ''
# ReadWriteMany is what lets several replicas share one Local Disk or Git storage target.
accessModes:
- ReadWriteOnce
size: 10Gi
annotations: {}
# Caps the emptyDir used while persistence is off.
sizeLimit: ''
podDisruptionBudget:
enabled: false
minAvailable: 1
# Used instead of `minAvailable` when set.
maxUnavailable: ''
# ---------------------------------------------------------------------------------------------------
# Networking
# ---------------------------------------------------------------------------------------------------
service:
type: ClusterIP
port: 80
# For NodePort / LoadBalancer.
nodePort: ''
annotations: {}
labels: {}
loadBalancerClass: ''
loadBalancerSourceRanges: []
# Cluster or Local, for NodePort / LoadBalancer.
externalTrafficPolicy: ''
sessionAffinity: ''
# Behind either of these, turn on Admin → Security → Trust Proxy so the wiki sees the visitor's
# address rather than the proxy's.
# Gateway API. The recommended way in; it needs a Gateway to attach to.
httpRoute:
enabled: false
annotations: {}
labels: {}
parentRefs:
- name: gateway
# namespace: gateway-system
# sectionName: https
hostnames:
- wiki.example.com
# HTTPRoute rules, passed through as given (matches, filters, timeouts, …) except for `backendRefs`,
# which the chart fills in with the wiki's Service.
rules:
- matches:
- path:
type: PathPrefix
value: /
# filters: []
# timeouts:
# request: 300s
# networking.k8s.io/v1 Ingress. Most controllers cap request bodies (ingress-nginx at 1m by default),
# which is also the ceiling for uploads — raise it with the controller's own annotation.
ingress:
enabled: false
className: ''
annotations: {}
labels: {}
hosts:
- host: wiki.example.com
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: wiki-tls
# hosts:
# - wiki.example.com
# ---------------------------------------------------------------------------------------------------
# Database
# ---------------------------------------------------------------------------------------------------
# A PostgreSQL server of the chart's own: one StatefulSet replica, the official image. Turn it off to
# use `externalDatabase` instead.
postgresql:
enabled: true
image:
repository: docker.io/library/postgres
# Pin a minor release (e.g. `18.4`) for reproducible upgrades. Moving to a new MAJOR needs a
# dump and restore, as it would anywhere — the data directory is per major.
tag: '18'
digest: ''
pullPolicy: IfNotPresent
# The wiki connects as `username`, an ordinary role owning `database`; the `postgres` superuser is
# kept for administration and never handed to the wiki. Both passwords are generated and kept across
# upgrades when left empty — except under a tool that renders without cluster access (Argo CD), which
# would generate new ones on every sync: set them, or use `existingSecret`, there.
#
# All of this is applied when the data directory is first initialised. Changing it afterwards
# changes what the wiki is told, not the database: alter the role by hand to match.
auth:
username: wiki
database: wiki
password: ''
postgresPassword: ''
existingSecret: ''
secretKeys:
userPasswordKey: password
adminPasswordKey: postgres-password
# The schema the wiki creates its tables in.
schema: wiki
# Server settings, passed as `-c key=value`.
parameters: {}
# max_connections: 200
# shared_buffers: 256MB
extraArgs: []
# Extra arguments for `initdb`, used on first start only.
initdbArgs: ''
# Scripts run once, after the data directory is initialised and the wiki's role and database exist,
# in file name order. `.sh`, `.sql` and `.sql.gz` are understood.
initdbScripts: {}
# 10-extensions.sql: |
# \connect wiki
# CREATE EXTENSION IF NOT EXISTS pg_trgm;
extraEnv: []
podAnnotations: {}
podLabels: {}
# 999 is the `postgres` user of the official Debian image (70 on -alpine tags).
podSecurityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
fsGroup: 999
# Anything else lets the kubelet re-own the data directory on every start, with group write,
# which PostgreSQL refuses to start on.
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
privileged: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources: {}
# requests:
# cpu: 250m
# memory: 256Mi
# limits:
# memory: 1Gi
startupProbe:
exec:
command: ['pg_isready', '-h', '127.0.0.1', '-p', '5432']
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
livenessProbe:
exec:
command: ['pg_isready', '-h', '127.0.0.1', '-p', '5432']
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
readinessProbe:
exec:
command: ['pg_isready', '-h', '127.0.0.1', '-p', '5432']
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
# A shutdown checkpoint on a busy server takes a while; SIGKILL before it finishes means crash
# recovery on the next start.
terminationGracePeriodSeconds: 60
updateStrategy:
type: RollingUpdate
priorityClassName: ''
nodeSelector: {}
tolerations: []
affinity: {}
volumes: []
volumeMounts: []
persistence:
enabled: true
existingClaim: ''
# `-` for the cluster's default class, empty to leave it unset.
storageClass: ''
accessModes:
- ReadWriteOnce
size: 8Gi
annotations: {}
# What happens to the claim when the StatefulSet is deleted or scaled down.
retentionPolicy:
whenDeleted: Retain
whenScaled: Retain
# /dev/shm, which parallel queries use for shared memory; a container's default is 64 MiB. Counted
# against the pod's memory.
shm:
enabled: true
sizeLimit: 256Mi
service:
type: ClusterIP
port: 5432
annotations: {}
labels: {}
# An existing PostgreSQL 16+ server, used when `postgresql.enabled` is false. The user needs to own the
# database, or at least be able to create a schema in it.
#
# Say where it is in ONE of two ways — `connectionString` or `parameters` — and leave the other empty.
# `schema` and `ssl` apply to both.
externalDatabase:
# ── Option 1: a connection string ───────────────────────────────────────────────────────────────
# `postgresql://user:password@host:5432/database`, with special characters in the password
# percent-encoded as in any URL. Give it inline or, better, as a Secret: CloudNativePG's
# `<cluster>-app` Secret carries one under `uri`.
#
# TLS parameters in the string (`sslmode`, `sslrootcert`, …) replace everything under `ssl` below.
# CloudNativePG's has none, so pair it with `ssl` and the `<cluster>-ca` Secret to verify the server.
connectionString:
value: ''
existingSecret: ''
existingSecretKey: uri
# ── Option 2: individual parameters ─────────────────────────────────────────────────────────────
parameters:
host: ''
port: 5432
database: wiki
user: wiki
password: ''
# A Secret holding the password, in place of `password`.
existingSecret: ''
existingSecretPasswordKey: password
# ── Either way ──────────────────────────────────────────────────────────────────────────────────
# The schema the wiki creates its tables in.
schema: wiki
ssl:
enabled: false
# Verify the server's certificate. Only for testing when off.
rejectUnauthorized: true
# A Secret with the CA to verify against and, for client certificate authentication, a
# certificate and key. Without one, the system CAs are used.
existingSecret: ''
caKey: ca.crt
# Both empty unless the server asks for a client certificate.
certKey: ''
keyKey: ''

@ -1,23 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

@ -1,6 +0,0 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 8.10.14
digest: sha256:db7c1e0bc9ec0ed45520521bd76bb390d04711fd0f04affaadafa1dc498ce68b
generated: "2020-07-21T20:34:41.41180748-04:00"

@ -1,42 +0,0 @@
apiVersion: v2
name: wiki
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 2.2.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
AppVersion: latest
description: The most powerful and extensible open source Wiki software.
keywords:
- wiki
- documentation
- knowledge base
- docs
- reference
- editor
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
dependencies:
- name: postgresql
version: 8.10.14
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
home: https://wiki.js.org
icon: https://cdn.js.wiki/images/wikijs-butterfly.svg
sources:
- https://github.com/Requarks/wiki
maintainers:
- name: Nicolas Giard
email: github@ngpixel.com
url: https://github.com/NGPixel
- name: James Greenhill
email: james@fuziontech.net
url: https://github.com/fuziontech
engine: gotpl

@ -1,177 +0,0 @@
<div align="center">
<img src="https://static.requarks.io/logo/wikijs-full.svg" alt="Wiki.js" width="600" />
[![Release](https://img.shields.io/github/release/Requarks/wiki.svg?style=flat&maxAge=3600)](https://github.com/Requarks/wiki/releases)
[![License](https://img.shields.io/badge/license-AGPLv3-blue.svg?style=flat)](https://github.com/requarks/wiki/blob/master/LICENSE)
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-green.svg?style=flat&logo=javascript&logoColor=white)](http://standardjs.com/)
[![Downloads](https://img.shields.io/github/downloads/Requarks/wiki/total.svg?style=flat&logo=github)](https://github.com/Requarks/wiki/releases)
[![Docker Pulls](https://img.shields.io/docker/pulls/requarks/wiki.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/requarks/wiki/)
[![Build + Publish](https://github.com/Requarks/wiki/actions/workflows/build.yml/badge.svg)](https://github.com/Requarks/wiki/actions/workflows/build.yml)
[![Huntr](https://img.shields.io/badge/security%20bounty-disclose-brightgreen.svg?style=flat&logo=cachet&logoColor=white)](https://huntr.dev/bounties/disclose)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/ngpixel?logo=github&color=ea4aaa)](https://github.com/users/NGPixel/sponsorship)
[![Open Collective backers and sponsors](https://img.shields.io/opencollective/all/wikijs?label=backers&color=218bff&logo=opencollective&logoColor=white)](https://opencollective.com/wikijs)
[![Chat on Slack](https://img.shields.io/badge/slack-requarks-CC2B5E.svg?style=flat&logo=slack)](https://wiki.requarks.io/slack)
[![Twitter Follow](https://img.shields.io/badge/follow-%40requarks-blue.svg?style=flat&logo=twitter)](https://twitter.com/requarks)
[![Reddit](https://img.shields.io/badge/reddit-%2Fr%2Fwikijs-orange?logo=reddit&logoColor=white)](https://www.reddit.com/r/wikijs/)
[![Subscribe to Newsletter](https://img.shields.io/badge/newsletter-subscribe-yellow.svg?style=flat&logo=mailchimp)](https://blog.js.wiki/subscribe)
##### A modern, lightweight and powerful wiki app built on NodeJS
</div>
- **[Official Website](https://wiki.js.org/)**
- **[Documentation](https://docs.requarks.io/)**
<h2 align="center">Donate</h2>
<div align="center">
Wiki.js is an open source project that has been made possible due to the generous contributions by community [backers](https://wiki.js.org/about). If you are interested in supporting this project, please consider [becoming a sponsor](https://github.com/users/NGPixel/sponsorship), [becoming a patron](https://www.patreon.com/requarks), donating to our [OpenCollective](https://opencollective.com/wikijs), via [Paypal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FLV5X255Z9CJU&source=url) or via Ethereum (`0xe1d55c19ae86f6bcbfb17e7f06ace96bdbb22cb5`).
[![Become a Sponsor](https://img.shields.io/badge/donate-github-ea4aaa.svg?style=popout&logo=github)](https://github.com/users/NGPixel/sponsorship)
[![Become a Patron](https://img.shields.io/badge/donate-patreon-orange.svg?style=popout&logo=patreon)](https://www.patreon.com/requarks)
[![Donate on OpenCollective](https://img.shields.io/badge/donate-open%20collective-blue.svg?style=popout&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNTZweCIgaGVpZ2h0PSIyNTZweCIgdmlld0JveD0iMCAwIDI1NiAyNTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiPjxnPjxwYXRoIGQ9Ik0yMDkuNzY1MTQ0LDEyOC4xNDk5NzkgQzIwOS43NjUxNDQsMTQ0LjE2MzMgMjA0Ljg2NDM4MSwxNTkuNDg5ODkgMTk2LjQ5ODc0NywxNzIuNzI1MDcyIEwyMjkuOTQ1Njc1LDIwNi4xNzE5OTkgQzI0Ni42ODIxMDUsMTgzLjg1Njc1OSAyNTUuNzI5MzA3LDE1Ni43MTUxNTIgMjU1LjcyOTMwNywxMjguODIxMTAyIEMyNTUuNzI5MzA3LDk5LjU1Njk5MTcgMjQ1Ljk3NDYwMyw3My4wNzEwMjA3IDIyOS4yNTg5NDQsNTEuNDg1ODEyOCBMMTk2LjQ4MzE0LDg0LjIxNDc5NCBDMjA1LjEyMjU2MSw5Ny4yMjI0NjgzIDIwOS43MzY5MDcsMTEyLjQ4NzgxIDIwOS43NDk1MzcsMTI4LjEwMzE1NiBMMjA5Ljc2NTE0NCwxMjguMTQ5OTc5IFoiIGZpbGw9IiNCOEQzRjQiPjwvcGF0aD48cGF0aCBkPSJNMTI3LjUxMzQ4NCwyMTAuMzU0ODE2IEM4Mi4xNDYwODcyLDIxMC4yNjg5NTggNDUuMzg3NTA5NCwxNzMuNTE3MzU4IDQ1LjI5MzAzOTMsMTI4LjE0OTk3OSBDNDUuMzYxNzUwMiw4Mi43NjQzMTM4IDgyLjEyNzg0ODcsNDUuOTg0MjU3IDEyNy41MTM0ODQsNDUuODk4MzE4NiBDMTQ0LjI0NDc1Miw0NS44OTgzMTg2IDE1OS41NzEzNDIsNTAuNzk5MDgxNyAxNzIuMTE5NzkyLDU5LjE2NDcxNTQgTDIwNC44NjQzODEsMjYuMzg4OTExNiBDMTgyLjU0MzY1LDkuNjY2NjUxMjkgMTU1LjQwMzQyOSwwLjYzMDg2MzI5OCAxMjcuNTEzNDg0LDAuNjM2NDk0NDAzIEM1Ny4xMjM1NDM3LDAuNjM2NDk0NDAzIDAsNTcuNzYwMDM4MSAwLDEyOC4xNDk5NzkgQzAsMTk4LjUwODcwNCA1Ny4xMjM1NDM3LDI1NS42NjM0NjMgMTI3LjUxMzQ4NCwyNTUuNjYzNDYzIEMxNTUuNTM3MzUyLDI1NS43NDA4NzYgMTgyLjc3NTk4OSwyNDYuNDA4NTEgMjA0Ljg2NDM4MSwyMjkuMTYxODg0IEwxNzEuNDE3NDU0LDE5NS43MzA1NjQgQzE1OS41NTU3MzQsMjA1LjQ4NTI2OCAxNDQuMjYwMzU5LDIxMC4zNTQ4MTYgMTI3LjUxMzQ4NCwyMTAuMzU0ODE2IEwxMjcuNTEzNDg0LDIxMC4zNTQ4MTYgWiIgZmlsbD0iIzdGQURGMiI+PC9wYXRoPjwvZz48L3N2Zz4=)](https://opencollective.com/wikijs)
[![Donate via Paypal](https://img.shields.io/badge/donate-paypal-blue.svg?style=popout&logo=paypal)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FLV5X255Z9CJU&source=url)
[![Donate via Ethereum](https://img.shields.io/badge/donate-ethereum-999.svg?style=popout&logo=ethereum&logoColor=CCC)](https://etherscan.io/address/0xe1d55c19ae86f6bcbfb17e7f06ace96bdbb22cb5)
[![Donate via Bitcoin](https://img.shields.io/badge/donate-bitcoin-ff9900.svg?style=popout&logo=bitcoin&logoColor=CCC)](https://checkout.opennode.com/p/2553c612-f863-4407-82b3-1a7685268747)
[![Buy a T-Shirt](https://img.shields.io/badge/buy-t--shirts-teal.svg?style=popout&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Igp3aWR0aD0iMjQiIGhlaWdodD0iMjQiCnZpZXdCb3g9IjAgMCAxOTIgMTkyIgpzdHlsZT0iIGZpbGw6IzAwMDAwMDsiPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZS1saW5lY2FwPSJidXR0IiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IiIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAiIGZvbnQtZmFtaWx5PSJub25lIiBmb250LXdlaWdodD0ibm9uZSIgZm9udC1zaXplPSJub25lIiB0ZXh0LWFuY2hvcj0ibm9uZSIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjxwYXRoIGQ9Ik0wLDE5MnYtMTkyaDE5MnYxOTJ6IiBmaWxsPSJub25lIj48L3BhdGg+PGcgZmlsbD0iIzFhYmM5YyI+PGcgaWQ9InN1cmZhY2UxIj48cGF0aCBkPSJNOTYsMGMtMTUuMjE4NzUsMCAtMjQuNjg3NSwzLjY1NjI1IC0yNS41LDRsLTIyLjUsNy4yNWMtMTAuNDA2MjUsMy4xODc1IC0xOS4wOTM3NSw5LjQzNzUgLTI1LjUsMTguMjVsLTIyLjUsNDIuNWwyNy4yNSwxNi43NWwxMi43NSwtMjR2MTE5LjI1YzAsNC40MDYyNSAyNS4wNjI1LDggNTYsOGMzMC45Mzc1LDAgNTYsLTMuNTkzNzUgNTYsLTh2LTExOS4yNWwxMi43NSwyNGwyNy4yNSwtMTYuNzVsLTIyLjUsLTQyLjVjLTYuNDA2MjUsLTguODEyNSAtMTUuMTU2MjUsLTE1LjA2MjUgLTI0Ljc1LC0xOC4yNWwtMjIuMjUsLTcuMjVjLTAuMTg3NSwwIC0xLjAzMTI1LDEuMzEyNSAtMiwyLjc1bDEuMjUsLTIuNWMwLDAgLTkuODQzNzUsLTQuMjUgLTI1Ljc1LC00LjI1ek05Niw4YzExLjQwNjI1LDAgMTguNDM3NSwyLjI1IDIxLDMuMjVjLTQuNDY4NzUsNS43NSAtMTEuNDA2MjUsMTIuNzUgLTIxLDEyLjc1Yy05LjQwNjI1LDAgLTE2LjQwNjI1LC03LjA2MjUgLTIwLjc1LC0xMi43NWMyLjg3NSwtMS4wNjI1IDkuODc1LC0zLjI1IDIwLjc1LC0zLjI1eiI+PC9wYXRoPjwvZz48L2c+PC9nPjwvc3ZnPg==)](https://wikijs.threadless.com)
</div>
## Introduction
This chart bootstraps a Wiki.js deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
It also optionally packages the [PostgreSQL](https://github.com/kubernetes/charts/tree/master/stable/postgresql) as the database but you are free to bring your own.
## Prerequisites
- PV provisioner support in the underlying infrastructure (with persistence storage enabled) if you want data persistance
## Adding the Wiki.js Helm Repository
```console
$ helm repo add requarks https://charts.js.wiki
```
## Installing the Chart
To install the chart with the release name `my-release` run the following:
### Using Helm 3:
```console
$ helm install my-release requarks/wiki
```
### Using Helm 2:
```console
$ helm install --name my-release requarks/wiki
```
The command deploys Wiki.js on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
> **Warning**: Persistant Volume Claims for the database are not deleted automatically. They need to be manually deleted
```console
$ kubectl delete pvc/data-wiki-postgresql-0
```
## Configuration
The following table lists the configurable parameters of the Wiki.js chart and their default values.
| Parameter | Description | Default |
| ------------------------------- | ------------------------------- | ---------------------------------------------------------- |
| `image.repository` | Wiki.js image | `requarks/wiki` |
| `image.tag` | Wiki.js image tag | `latest` |
| `imagePullPolicy` | Image pull policy | `IfNotPresent` |
| `replicacount` | Amount of wiki.js service pods to run | `1` |
| `revisionHistoryLimit` | Total amount of revision history points | `10` |
| `resources.limits` | wiki.js service resource limits | `nil` |
| `resources.requests` | wiki.js service resource requests | `nil` |
| `nodeSelector` | Node labels for wiki.js pod assignment | `{}` |
| `affinity` | Affinity settings for wiki.js pod assignment | `{}` |
| `schedulerName` | Name of an alternate scheduler for wiki.js pod | `nil` |
| `tolerations` | Toleration labels for wiki.jsk pod assignment | `[]` |
| `volumeMounts` | Volume mounts for Wiki.js container | `[]` |
| `volumes` | Volumes for Wiki.js Pod | `[]` |
| `ingress.enabled` | Enable ingress controller resource | `false` |
| `ingress.className` | Ingress class name | `""` |
| `ingress.annotations` | Ingress annotations | `{}` |
| `ingress.hosts` | List of ingress rules | `[{"host": "wiki.local", "paths": ["/"]}]` |
| `ingress.tls` | Ingress TLS configuration | `[]` |
| `sideload.enabled` | Enable sideloading of locale files from git | `false` |
| `sideload.repoURL` | Git repository URL containing locale files | `https://github.com/Requarks/wiki-localization` |
| `sideload.env` | Environment variables for sideload Container | `{}` |
| `postgresql.enabled` | Deploy postgres server (see below) | `true` |
| `postgresql.postgresqlDatabase` | Postgres database name | `wiki` |
| `postgresql.postgresqlUser` | Postgres username | `postgres` |
| `postgresql.postgresqlHost` | External postgres host | `nil` |
| `postgresql.postgresqlPassword` | External postgres password | `nil` |
| `postgresql.existingSecret` | Provide an existing `Secret` for postgres | `nil` |
| `postgresql.existingSecretKey` | The postgres password key in the existing `Secret` | `postgresql-password` |
| `postgresql.postgresqlPort` | External postgres port | `5432` |
| `postgresql.ssl` | Enable external postgres SSL connection | `false` |
| `postgresql.ca` | Certificate of Authority content for postgres | `nil` |
| `postgresql.persistence.enabled` | Enable postgres persistence using PVC | `true` |
| `postgresql.persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` for postgres | `nil` |
| `postgresql.persistence.storageClass` | Postgres PVC Storage Class (example: `nfs`) | `nil` |
| `postgresql.persistence.size` | Postgers PVC Storage Request | `8Gi` |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
$ helm install --name my-release \
--set postgresql.persistence.enabled=false \
requarks/wiki
```
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
```console
$ helm install --name my-release -f values.yaml requarks/wiki
```
> **Tip**: You can use the default [values.yaml](values.yaml)
## PostgresSQL
By default, PostgreSQL is installed as part of the chart.
### Using an external PostgreSQL server
To use an external PostgreSQL server, set `postgresql.enabled` to `false` and then set `postgresql.postgresqlHost` and `postgresql.postgresqlPassword`. To use an existing `Secret`, set `postgresql.existingSecret`. The other options (`postgresql.postgresqlDatabase`, `postgresql.postgresqlUser`, `postgresql.postgresqlPort` and `postgresql.existingSecretKey`) may also want changing from their default values.
To use an SSL connection you can set `postgresql.ssl` to `true` and if needed the path to a Certificate of Authority can be set using `postgresql.ca` to `/path/to/ca`. Default `postgresql.ssl` value is `false`.
If `postgresql.existingSecret` is not specified, you also need to add the following Helm template to your deployment in order to create the postgresql `Secret`:
```yaml
kind: Secret
apiVersion: v1
metadata:
name: {{ template "wiki.postgresql.secret" . }}
data:
{{ template "wiki.postgresql.secretKey" . }}: "{{ .Values.postgresql.postgresqlPassword | b64enc }}"
```
## Persistence
Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube.
See the [Configuration](#configuration) section to configure the PVC or to disable persistence.
## Ingress
This chart provides support for Ingress resource. If you have an available Ingress Controller such as Nginx or Traefik you maybe want to set `ingress.enabled` to true and add `ingress.hosts` for the URL. Then, you should be able to access the installation using that address.

@ -1,21 +0,0 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "wiki.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "wiki.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "wiki.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "wiki.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80
{{- end }}

@ -1,108 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "wiki.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "wiki.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "wiki.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Common labels
*/}}
{{- define "wiki.labels" -}}
helm.sh/chart: {{ include "wiki.chart" . }}
{{ include "wiki.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
{{/*
Selector labels
*/}}
{{- define "wiki.selectorLabels" -}}
app.kubernetes.io/name: {{ include "wiki.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "wiki.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "wiki.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "wiki.postgresql.fullname" -}}
{{- if .Values.postgresql.fullnameOverride -}}
{{- .Values.postgresql.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{ printf "%s-%s" .Release.Name "postgresql"}}
{{- end -}}
{{- end -}}
{{/*
Set postgres host
*/}}
{{- define "wiki.postgresql.host" -}}
{{- if .Values.postgresql.enabled -}}
{{- template "wiki.postgresql.fullname" . -}}
{{- else -}}
{{- .Values.postgresql.postgresqlHost | quote -}}
{{- end -}}
{{- end -}}
{{/*
Set postgres secret
*/}}
{{- define "wiki.postgresql.secret" -}}
{{- if .Values.postgresql.enabled -}}
{{- template "wiki.postgresql.fullname" . -}}
{{- else -}}
{{- template "wiki.fullname" . -}}
{{- end -}}
{{- end -}}
{{/*
Set postgres secretKey
*/}}
{{- define "wiki.postgresql.secretKey" -}}
{{- if .Values.postgresql.enabled -}}
"postgresql-password"
{{- else -}}
{{- default "postgresql-password" .Values.postgresql.existingSecretKey | quote -}}
{{- end -}}
{{- end -}}

@ -1,96 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "wiki.fullname" . }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "wiki.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "wiki.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "wiki.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- if .Values.sideload.enabled }}
initContainers:
- name: {{ .Chart.Name }}-sideload
image: "{{ .Values.image.repository }}:{{ default "latest" .Values.image.tag }}"
imagePullPolicy: {{ default "IfNotPresent" .Values.image.imagePullPolicy }}
env:
{{- toYaml .Values.sideload.env | nindent 12 }}
command: [ "sh", "-c" ]
args: [ "mkdir -p /wiki/data/sideload && git clone --depth=1 {{ .Values.sideload.repoURL }} /wiki/data/sideload/" ]
{{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ default "latest" .Values.image.tag }}"
imagePullPolicy: {{ default "IfNotPresent" .Values.image.imagePullPolicy }}
env:
- name: DB_TYPE
value: postgres
- name: DB_HOST
value: {{ template "wiki.postgresql.host" . }}
- name: DB_PORT
value: "{{ default "5432" .Values.postgresql.postgresqlPort }}"
- name: DB_NAME
value: {{ default "wiki" .Values.postgresql.postgresqlDatabase }}
- name: DB_USER
value: {{ default "wiki" .Values.postgresql.postgresqlUser }}
- name: DB_SSL
value: "{{ default "false" .Values.postgresql.ssl }}"
- name: DB_SSL_CA
value: "{{ default "" .Values.postgresql.ca }}"
- name: DB_PASS
valueFrom:
secretKeyRef:
{{- if .Values.postgresql.existingSecret }}
name: {{ .Values.postgresql.existingSecret }}
{{- else }}
name: {{ template "wiki.postgresql.secret" . }}
{{- end }}
key: {{ template "wiki.postgresql.secretKey" . }}
- name: HA_ACTIVE
value: {{ .Values.replicaCount | int | le 2 | quote }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- name: http
containerPort: 3000
protocol: TCP
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -1,61 +0,0 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "wiki.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "wiki.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

@ -1,23 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{include "wiki.fullname" .}}
labels: {{- include "wiki.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{- range $key, $value := . }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
spec:
type: {{.Values.service.type}}
ports:
- port: {{ default "80" .Values.service.port}}
targetPort: http
protocol: TCP
name: http
- port: {{ default "443" .Values.service.httpsPort}}
targetPort: http
protocol: TCP
name: https
selector: {{- include "wiki.selectorLabels" . | nindent 4}}

@ -1,15 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "wiki.fullname" . }}-test-connection"
labels:
{{- include "wiki.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test-success
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "wiki.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

@ -1,163 +0,0 @@
# Default values for wiki.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
revisionHistoryLimit: 10
image:
repository: requarks/wiki
imagePullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /healthz
port: http
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 80
# Annotations applied for services such as externalDNS or
# service type LoadBalancer
# type: LoadBalancer
# httpsPort: 443
# annotations: {}
ingress:
enabled: true
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: wiki.minikube.local
paths:
- path: "/"
pathType: Prefix
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
volumeMounts: []
volumes: []
# This will allow us to install locales even without internet access using a initContainer & wikjs "sideloading"
sideload:
enabled: false
# Git-Repo containing all locales.json-files you need:
repoURL: https://github.com/Requarks/wiki-localization
## This can be helpfull if you have internet access over a http proxy:
env: []
# - name: HTTPS_PROXY
# value: http://my.proxy.com:3128
## Configuration values for the postgresql dependency.
## ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md
##
postgresql:
## Use the PostgreSQL chart dependency.
## Set to false if bringing your own PostgreSQL, and set secret value postgresql-uri.
##
enabled: true
## ssl enforce SSL communication with PostgresSQL
## Default to false
##
# ssl: false
## ca Certificate of Authority
## Default to empty, point to location of CA
##
# ca: "path to ca"
## postgresqlHost override postgres database host
## Default to postgres
##
# postgresqlHost: postgres
## postgresqlPort port for postgres
## Default to 5432
##
# postgresqlPort: 5432
## PostgreSQL fullname Override
## Default to wiki-postgresql unless fullname override is set for Chart
##
fullnameOverride: ""
## PostgreSQL User to create.
##
postgresqlUser: postgres
## PostgreSQL Database to create.
##
postgresqlDatabase: wiki
## Persistent Volume Storage configuration.
## ref: https://kubernetes.io/docs/user-guide/persistent-volumes
##
replication:
## Enable PostgreSQL replication (primary/secondary)
##
enabled: false
persistence:
## Enable PostgreSQL persistence using Persistent Volume Claims.
##
enabled: true
## concourse data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
## Persistent Volume Access Mode.
##
accessMode: ReadWriteOnce
## Persistent Volume Storage Size.
##
size: 8Gi
Loading…
Cancel
Save