---
url: https://flip-chart.ru/developers/en/on-premise/installation/kubernetes/helm.md
description: >-
  Installing flip on-premise on Kubernetes with a Helm chart: requirements,
  chart components, values.yaml parameters, and how to upgrade and uninstall the
  release.
---

# Kubernetes (Helm)

## Requirements

* A Kubernetes cluster and [Helm 3](https://helm.sh/docs/intro/install/)
* The [ingress-nginx](https://kubernetes.github.io/ingress-nginx/) Ingress controller; the annotations in the example `values.yaml` are specific to it
* PostgreSQL 15 (14 is supported), Valkey 9 (standalone mode) and S3-compatible storage, deployed separately and reachable from the cluster
* Two DNS names and TLS certificates: the application (`example.flip-chart.ru`) and the MCP server (`mcp.example.flip-chart.ru`)
* SMTP server credentials

::: tip Configuration changes
After you update a configuration secret, restart the corresponding Deployment: `kubectl -n flip rollout restart deployment/backend`.
:::

## Chart components

| Subchart | Image | Port | Ingress |
|---|---|---|---|
| `backend` | `flip-backend` | 9000 | `/app/api`, `/app/api/v1/ws`, `/app/api/v1/flip/backup/upload`, `/` redirect |
| `file-handlers` | `flip-file-handlers` | 8080 | — |
| `frontend` | `flip-frontend` | 80 | `/app`, `/app/s3/` → S3 storage |
| `mcp-server` | `flip-mcp-server` | 8090 | `mcp.example.flip-chart.ru/` |

## Delivery files

```
├── credentials
│   ├── authorized_key.json      — Docker image registry access key
│   └── License_key.txt          — application license key
└── deploy
    ├── docker-compose
    │   └── config               — example service configuration files
    └── kubernetes
        ├── flip-chart-1.0.0.tgz — Helm chart
        └── values.yaml          — example values
```

Example: [values.yaml](/en/deploy/values.yaml).

## Installation steps

### 1. Namespace and registry access

```bash
kubectl create namespace flip
kubectl -n flip create secret docker-registry registrykey \
  --docker-server=cr.yandex \
  --docker-username=json_key \
  --docker-password="$(cat credentials/authorized_key.json)"
```

### 2. TLS certificates

```bash
kubectl -n flip create secret tls flip-tls     --cert=crt.pem     --key=key.pem
kubectl -n flip create secret tls flip-mcp-tls --cert=mcp-crt.pem --key=mcp-key.pem
```

If you use cert-manager, specify its annotations in the `ingress` section of the corresponding subcharts; the secret names stay the same.

### 3. Configuration files

Fill in the configuration files as described in [backend](/en/on-premise/config/backend), [file-handlers](/en/on-premise/config/file-handlers), [frontend](/en/on-premise/config/frontend) and [mcp-server](/en/on-premise/config/mcp).

::: danger In-cluster addresses
The example configurations are written for docker-compose. In Kubernetes, services are addressed by the chart's Service names:

| Field | docker-compose | Kubernetes |
|---|---|---|
| backend → `FileHandlerServiceConfig.Address` | `http://flip-file-handlers:8080/api` | `http://file-handlers.flip.svc.cluster.local:8080/api` |
| mcp-server → `flipApi.internalUrl` | `http://flip-backend:9000` | `http://backend.flip.svc.cluster.local:9000` |

`flip` in the address is the installation namespace (`global.namespace`). The PostgreSQL, Valkey and S3 addresses are those of the external services.
:::

Create the configuration secrets (the secret and key names must match `volumes`/`volumeMounts` in values):

```bash
kubectl -n flip create secret generic backend-config       --from-file=config.yaml=config/backend/config.yaml
kubectl -n flip create secret generic file-handlers-config --from-file=config.yaml=config/file-handlers/config.yaml
kubectl -n flip create secret generic frontend-config       --from-file=config.js=config/frontend/config.js
kubectl -n flip create secret generic mcp-server-config    --from-file=config.yaml=config/mcp-server/config.yaml
```

::: tip Updating the configuration

```bash
kubectl -n flip create secret generic backend-config --from-file=config.yaml=config/backend/config.yaml \
  --dry-run=client -o yaml | kubectl apply -f -
```

:::

### 4. S3 storage

* Create a bucket and allow anonymous read access to its objects.
* Upload the media assets: unpack `sources/gifs.tar` and copy the `gifs` directory to the root of the bucket.
* In `values.yaml`, set the storage host in `frontend.service.s3.storageurl`. The chart creates a Service of type `ExternalName` and an Ingress for `/app/s3/(.*)` that proxies requests to the storage through the application domain.

### 5. values.yaml

Edit `values.yaml`: domains (`tlshosts`, `permanent-redirect`), TLS secret names, the S3 host, the image version (`image.tag`, the same for all components) and resources. The parameters are described in [values.yaml parameters](#values-yaml-parameters).

### 6. Installation

```bash
helm install flip ./flip-chart-1.0.0.tgz -f values.yaml -n flip
```

### 7. Verification

```bash
kubectl -n flip get pods
kubectl -n flip get ingress
```

All pods must be in the `Running` state. The application is available at `https://example.flip-chart.ru/app`. Then proceed to the [first launch](/en/on-premise/installation/first-boot).

## values.yaml parameters

### global

| Parameter | Description |
|---|---|
| `global.namespace` | Installation namespace. |
| `global.imagePullSecrets` | List of image registry access secrets. |

### Common subchart parameters

The same for `backend`, `file-handlers`, `frontend` and `mcp-server`.

| Parameter | Description |
|---|---|
| `enabled` | Enables the component. |
| `replicaCount` | Number of replicas. |
| `image.repository`, `image.tag`, `image.pullPolicy` | Component image. |
| `annotations` | Deployment and pod annotations. |
| `affinity`, `tolerations`, `nodeSelector` | Pod placement. |
| `containers.containerPort` | Container ports. |
| `containers.readinessProbe` | Readiness probe. |
| `env`, `envFrom` | Environment variables. |
| `service.enabled`, `service.type`, `service.ports` | Kubernetes Service. |
| `resources` | CPU/memory requests and limits. |
| `volumes`, `volumeMounts` | Mounting of the configuration secret. The path inside the container is fixed (see [configuration files](/en/on-premise/config/summary)). |
| `securityContext` | Container security context (`backend`). |
| `serviceMonitor.enabled` | ServiceMonitor for Prometheus Operator (`backend`, `file-handlers`). |

### Ingress

| Parameter | Description |
|---|---|
| `backend.ingress.ingressClassName` | Ingress controller class. |
| `backend.ingress.tlshosts`, `backend.ingress.tlssecret` | Application domain and TLS secret. |
| `backend.ingress.external` | REST API at `/app/api`. |
| `backend.ingress.websocket` | WebSocket at `/app/api/v1/ws`, 86400s timeouts. |
| `backend.ingress.upload` | Board import at `/app/api/v1/flip/backup/upload`, 6G body size limit, 3600s timeouts. |
| `backend.ingress.redirect` | Redirect `/` → `/app`; the domain is set in the `permanent-redirect` annotation. |
| `backend.ingress.internal` | Internal service endpoints at `/app/api/v1/internal`; disabled. |
| `frontend.ingress.ui` | User interface at `/app`. |
| `frontend.ingress.s3` | S3 proxying from `/app/s3/(.*)` to the `frontend-s3` Service; storage served over HTTPS requires the `backend-protocol: "HTTPS"` and `upstream-vhost` annotations. |
| `frontend.service.s3.storageurl` | S3 storage host for the `ExternalName` Service. |
| `mcp-server.ingress` | MCP server on a separate domain (`tlshosts`/`tlssecret`). |

## Upgrading

```bash
helm upgrade flip ./flip-chart-1.0.0.tgz -f values.yaml -n flip
kubectl -n flip get pods
```

For the version update procedure, see [Updates](/en/on-premise/updates/instruction).

## Uninstalling

```bash
helm uninstall flip -n flip
kubectl delete namespace flip
```
