Compare commits

...

20 Commits

Author SHA1 Message Date
798a167bb3 helm chart jellyseerr init commit 2025-04-23 16:10:06 +02:00
3df15e3b42 Merge branch 'main' of https://github.com/rtomik/helm-charts 2025-04-22 21:06:27 +02:00
7fa820f284 edited helm chart default values 2025-04-22 21:06:22 +02:00
969cec0318 Update readme.md 2025-04-21 13:01:21 +02:00
64e1db727c Update README.md 2025-04-09 16:09:35 +02:00
a8f7a3fe07 edit artifcact hub-repo 2025-04-06 13:59:13 +02:00
32cefb046b Update artifacthub-repo.yml 2025-04-06 13:04:26 +02:00
567fcd4cd0 Update artifacthub-repo.yml 2025-04-06 13:02:21 +02:00
c33421162d Force rebuild of Helm repository index 2025-04-06 12:53:11 +02:00
ea19e1a6cf Force rebuild of Helm repository index 2025-04-06 12:44:59 +02:00
22353b8049 Force rebuild of Helm repository index 2025-04-06 12:43:10 +02:00
d968f2ae19 Released v 0.0.2 fixed issue with deployment on kubernetes. 2025-04-05 22:56:22 +02:00
4df5dc4384 Merge branch 'main' of https://github.com/rtomik/helm-charts 2025-04-05 18:38:20 +02:00
20d661ef6f added recipya helm chart init commit 2025-04-05 18:38:16 +02:00
e7635ee5a4 Update artifacthub-repo.yml 2025-04-01 10:39:42 +02:00
7cafc6a692 Merge branch 'main' of https://github.com/rtomik/helm-charts 2025-03-31 09:42:52 +02:00
b84d617f76 added Artifact Hub repository metadata file 2025-03-31 09:42:45 +02:00
a89c71d03f Update README.md 2025-03-24 11:01:29 +01:00
24947446e3 Update readme.md 2025-03-23 20:53:07 +01:00
2130a6984d Update readme.md 2025-03-23 20:49:57 +01:00
24 changed files with 1386 additions and 16 deletions

View File

@ -1,2 +1,4 @@
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/rtomik-helm-charts)](https://artifacthub.io/packages/search?repo=rtomik-helm-charts)
# helm-charts
Repo for helm charts
Donetick Helm chart

15
artifacthub-repo.yml Normal file
View File

@ -0,0 +1,15 @@
# Artifact Hub repository metadata file
#
# Some settings like the verified publisher flag or the ignored packages won't
# be applied until the next time the repository is processed. Please keep in
# mind that the repository won't be processed if it has not changed since the
# last time it was processed. Depending on the repository kind, this is checked
# in a different way. For Helm http based repositories, we consider it has
# changed if the `index.yaml` file changes. For git based repositories, it does
# when the hash of the last commit in the branch you set up changes. This does
# NOT apply to ownership claim operations, which are processed immediately.
#
repositoryID: 11743389-27d2-4d03-a271-1dd96844082f
owners: # (optional, used to claim repository ownership)
- name: rtomik
email: n@gmail.com

View File

@ -3,7 +3,7 @@ name: donetick
description: A Helm chart for Donetick application
type: application
version: 1.0.1
appVersion: "latest"
appVersion: "v0.1.38"
maintainers:
- name: Richard Tomik
email: no@m.com

View File

@ -14,7 +14,7 @@ This chart deploys [Donetick](https://github.com/donetick/donetick) on a Kuberne
## Installing the Chart
To install the chart with the release name `my-donetick`:
To install the chart with the release name `donetick`:
```bash
$ helm repo add donetick-chart https://rtomik.github.io/helm-charts
@ -25,10 +25,10 @@ $ helm install donetick donetick-chart/donetick
## Uninstalling the Chart
To uninstall/delete the `my-donetick` deployment:
To uninstall/delete the `donetick` deployment:
```bash
$ helm delete my-donetick
$ helm uninstall donetick
```
## Parameters

View File

@ -5,7 +5,7 @@ fullnameOverride: ""
## Image settings
image:
repository: donetick/donetick
tag: latest
tag: "v0.1.38"
pullPolicy: IfNotPresent
## Deployment settings
@ -41,8 +41,8 @@ service:
## Ingress settings
ingress:
enabled: true
className: "traefik"
enabled: false
className: ""
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
hosts:
@ -58,8 +58,8 @@ ingress:
## Persistence settings
persistence:
enabled: true
storageClass: "longhorn"
enabled: false
storageClass: ""
accessMode: ReadWriteOnce
size: 1Gi
annotations: {}
@ -85,13 +85,13 @@ extraVolumeMounts: []
extraVolumes: []
## Resource limits and requests
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# resources:
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 100m
# memory: 128Mi
## Application health checks
probes:

View File

@ -0,0 +1,16 @@
apiVersion: v2
name: jellyseerr
description: A Helm chart for Jellyseerr - A fork of Overseerr for Jellyfin support
type: application
version: 0.0.1
appVersion: 2.5.2
maintainers:
- name: Richard Tomik
email: no@m.com
keywords:
- jellyseerr
- jellyfin
- media-requests
home: https://github.com/rtomik/helm-charts
sources:
- https://github.com/fallenbagel/jellyseerr

View File

@ -0,0 +1,32 @@
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 }}{{ .path }}
{{- 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 "jellyseerr.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 "jellyseerr.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "jellyseerr.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 "jellyseerr.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
2. Jellyseerr will be available at port {{ .Values.service.port }}
{{- if .Values.persistence.enabled }}
3. Data is persisted using PVC: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{ else }}{{ include "jellyseerr.fullname" . }}-config{{ end }}
{{- else }}
3. WARNING: No persistence enabled. Data will be lost when pods are restarted.
{{- end }}
For more information about using this Helm chart, please refer to the README.md file.

142
charts/jellyseerr/readme.md Normal file
View File

@ -0,0 +1,142 @@
# Jellyseerr Helm Chart
A Helm chart for deploying [Jellyseerr](https://github.com/fallenbagel/jellyseerr) on Kubernetes.
## Introduction
This chart deploys Jellyseerr on a Kubernetes cluster using the Helm package manager. Jellyseerr is a fork of Overseerr for Jellyfin support.
## Prerequisites
- Kubernetes 1.19+
- Helm 3.0+
- PV provisioner support in the underlying infrastructure (if persistence is needed)
## Installing the Chart
To install the chart with the release name `jellyseerr`:
```bash
$ helm repo add rtomik-charts https://rtomik.github.io/helm-charts
$ helm install jellyseerr rtomik-charts/jellyseerr
```
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `jellyseerr` deployment:
```bash
$ helm uninstall jellyseerr
```
## Parameters
### Global parameters
| Name | Description | Value |
|------------------------|---------------------------------------------------------------|--------|
| `nameOverride` | String to partially override the release name | `""` |
| `fullnameOverride` | String to fully override the release name | `""` |
### Image parameters
| Name | Description | Value |
|-------------------------|--------------------------------------------------------------|--------------------------------|
| `image.repository` | Jellyseerr image repository | `ghcr.io/fallenbagel/jellyseerr` |
| `image.tag` | Jellyseerr image tag | `latest` |
| `image.pullPolicy` | Jellyseerr image pull policy | `IfNotPresent` |
| `imagePullSecrets` | Global Docker registry secret names as an array | `[]` |
### Deployment parameters
| Name | Description | Value |
|--------------------------------------|--------------------------------------------------|-----------|
| `replicaCount` | Number of Jellyseerr replicas | `1` |
| `revisionHistoryLimit` | Number of revisions to retain for rollback | `3` |
| `podSecurityContext.runAsNonRoot` | Run containers as non-root user | `true` |
| `podSecurityContext.runAsUser` | User ID for the container | `1000` |
| `podSecurityContext.fsGroup` | Group ID for the container filesystem | `1000` |
| `containerSecurityContext` | Security context for the container | See values.yaml |
| `nodeSelector` | Node labels for pod assignment | `{}` |
| `tolerations` | Tolerations for pod assignment | `[]` |
| `affinity` | Affinity for pod assignment | `{}` |
### Service parameters
| Name | Description | Value |
|----------------------------|----------------------------------------------|-------------|
| `service.type` | Kubernetes Service type | `ClusterIP` |
| `service.port` | Service HTTP port | `5055` |
### Ingress parameters
| Name | Description | Value |
|----------------------------|----------------------------------------------|------------------------|
| `ingress.enabled` | Enable ingress record generation | `false` |
| `ingress.className` | IngressClass name | `""` |
| `ingress.annotations` | Additional annotations for the Ingress resource | `{}` |
| `ingress.hosts` | Array of host and path objects | See values.yaml |
| `ingress.tls` | TLS configuration | `[]` |
### Persistence parameters
| Name | Description | Value |
|-------------------------------|----------------------------------------------|-----------------|
| `persistence.enabled` | Enable persistence using PVC | `true` |
| `persistence.existingClaim` | Use an existing PVC | `""` |
| `persistence.storageClass` | PVC Storage Class | `""` |
| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` |
| `persistence.size` | PVC Storage Size | `1Gi` |
| `persistence.annotations` | Additional custom annotations for the PVC | `{}` |
### Environment variables
| Name | Description | Value |
|--------------------------|----------------------------------------------|-----------------|
| `env` | Environment variables for Jellyseerr | See values.yaml |
| `extraEnv` | Additional environment variables | `[]` |
### Resources parameters
| Name | Description | Value |
|--------------------------|----------------------------------------------|-----------------|
| `resources.limits` | The resources limits for containers | See values.yaml |
| `resources.requests` | The resources requests for containers | See values.yaml |
## Configuration
The following table lists the configurable parameters of the Jellyseerr chart and their default values.
### Environment Variables
You can configure Jellyseerr by setting environment variables:
```yaml
env:
- name: TZ
value: "America/New_York"
- name: LOG_LEVEL
value: "info"
- name: PORT
value: "5055"
```
### Using Persistence
By default, persistence is enabled with a 1Gi volume:
```yaml
persistence:
enabled: true
size: 1Gi
```
You can also use an existing PVC:
```yaml
persistence:
enabled: true
existingClaim: my-jellyseerr-pvc
```

View File

@ -0,0 +1,45 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "jellyseerr.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "jellyseerr.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s" $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "jellyseerr.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "jellyseerr.labels" -}}
helm.sh/chart: {{ include "jellyseerr.chart" . }}
{{ include "jellyseerr.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "jellyseerr.selectorLabels" -}}
app.kubernetes.io/name: {{ include "jellyseerr.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

View File

@ -0,0 +1,107 @@
### templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "jellyseerr.fullname" . }}
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
annotations:
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "jellyseerr.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
{{- include "jellyseerr.selectorLabels" . | nindent 8 }}
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.containerSecurityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.startupArgs }}
args:
{{- range .Values.startupArgs }}
- {{ . | quote }}
{{- end }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{- if .Values.probes.liveness.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.probes.liveness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
successThreshold: {{ .Values.probes.liveness.successThreshold }}
{{- end }}
{{- if .Values.probes.readiness.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.probes.readiness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
successThreshold: {{ .Values.probes.readiness.successThreshold }}
{{- end }}
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: config
mountPath: /app/config
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: config
persistentVolumeClaim:
claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{ else }}{{ include "jellyseerr.fullname" . }}-config{{ end }}
{{- with .Values.extraVolumes }}
{{- 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 }}

View File

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

View File

@ -0,0 +1,21 @@
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "jellyseerr.fullname" . }}-config
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
{{- with .Values.persistence.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
{{- if .Values.persistence.storageClass }}
storageClassName: {{ .Values.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end }}

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "jellyseerr.fullname" . }}
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "jellyseerr.selectorLabels" . | nindent 4 }}

View File

@ -0,0 +1,117 @@
## Global settings
nameOverride: ""
fullnameOverride: ""
## Image settings
image:
repository: ghcr.io/fallenbagel/jellyseerr
tag: 2.5.2
pullPolicy: IfNotPresent
## Deployment settings
replicaCount: 1
revisionHistoryLimit: 3
# Optional startup arguments
startupArgs: []
# Pod security settings
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop:
- ALL
## Pod scheduling
nodeSelector: {}
tolerations: []
affinity: {}
## Pod annotations
podAnnotations: {}
## Service settings
service:
type: ClusterIP
port: 5055
## Ingress settings
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: jellyseerr.domain.com
paths:
- path: /
pathType: Prefix
tls: []
# - hosts:
# - jellyseerr.domain.com
# secretName: jellyseerr-tls
## Persistence settings
persistence:
enabled: true
existingClaim: ""
storageClass: ""
accessMode: ReadWriteOnce
size: 1Gi
annotations: {}
## Environment variables
env:
- name: TZ
value: "UTC"
- name: LOG_LEVEL
value: "info"
- name: PORT
value: "5055"
# Extra environment variables (for advanced use cases)
extraEnv: []
# - name: NODE_ENV
# value: "production"
# Extra volume mounts
extraVolumeMounts: []
# Extra volumes
extraVolumes: []
## Resource limits and requests
# resources:
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 100m
# memory: 128Mi
## Application health checks
probes:
liveness:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
path: /api/v1/status
readiness:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
successThreshold: 1
path: /api/v1/status

15
charts/recipya/Chart.yaml Normal file
View File

@ -0,0 +1,15 @@
apiVersion: v2
name: recipya
description: A Helm chart for Recipya recipe manager application
type: application
version: 0.0.2
appVersion: "v1.2.2"
maintainers:
- name: Richard Tomik
email: no@m.com
keywords:
- recipe-manager
- recipya
home: https://github.com/rtomik/helm-charts
sources:
- https://github.com/reaper47/recipya

196
charts/recipya/readme.md Normal file
View File

@ -0,0 +1,196 @@
# Recipya Helm Chart
A Helm chart for deploying [Recipya](https://github.com/reaper47/recipya) on Kubernetes.
[Source Code](https://github.com/rtomik/helm-charts/tree/main/charts%2Frecipya)
## Introduction
This chart deploys Recipya recipe manager on a Kubernetes cluster using the Helm package manager.
## Prerequisites
- Kubernetes 1.19+
- Helm 3.2.0+
- PV provisioner support in the underlying infrastructure (if persistence is needed)
## Installing the Chart
To install the chart with the release name `recipya`:
```bash
helm repo add recipya-chart https://rtomik.github.io/helm-charts
helm install recipya recipya-chart/recipya -n recipya
```
The command deploys Recipya on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
## Uninstalling the Chart
To uninstall/delete the `recipya` deployment:
```bash
helm uninstall recipya -n recipya
```
## Important Configuration Notes
### Server URL
When deploying with an ingress, it's **critical** to set `config.server.url` to match your ingress URL (including https if you're using TLS). This ensures that redirects after login work correctly:
```yaml
config:
server:
url: "https://your-recipya-domain.com"
```
### Ingress Configuration
This chart includes optimized ingress configurations for Traefik, with support for WebSockets and proper security headers. If you're using a different ingress controller, you may need to adjust annotations accordingly.
## Parameters
### Global parameters
| Name | Description | Value |
|--------------------------|--------------------------------------|-----------------|
| `image.repository` | Recipya image repository | `reaper99/recipya` |
| `image.tag` | Recipya image tag | `v1.2.2` |
| `image.pullPolicy` | Recipya image pull policy | `IfNotPresent` |
| `replicaCount` | Number of Recipya replicas | `1` |
| `revisionHistoryLimit` | Number of revisions to keep | `3` |
### Security parameters
| Name | Description | Value |
|-----------------------------------------|--------------------------------------------------|-----------|
| `podSecurityContext.fsGroup` | Group ID for the Recipya container | `1000` |
| `containerSecurityContext` | Security context for the container | `{}` |
### Recipya configuration parameters
| Name | Description | Value |
|-----------------------------------------|-------------------------------------------------------|---------------------|
| `config.server.port` | Server port | `8078` |
| `config.server.autologin` | Whether to login automatically | `false` |
| `config.server.is_demo` | Whether the app is a demo version | `false` |
| `config.server.is_prod` | Whether the app is in production | `false` |
| `config.server.no_signups` | Whether to disable user account registrations | `false` |
| `config.server.url` | Base URL for the application | `http://0.0.0.0` |
| `config.email.address` | The email address for SendGrid | `""` |
| `config.email.sendgrid` | SendGrid API key | `""` |
| `config.documentIntelligence.endpoint` | Azure Document Intelligence endpoint | `""` |
| `config.documentIntelligence.key` | Azure Document Intelligence key | `""` |
### Service parameters
| Name | Description | Value |
|--------------------------|--------------------------------------------------|-------------|
| `service.type` | Recipya service type | `ClusterIP` |
| `service.port` | Recipya service port | `8078` |
### Ingress parameters
| Name | Description | Value |
|-------------------------------|--------------------------------------------------|------------------------|
| `ingress.enabled` | Enable ingress controller resource | `false` |
| `ingress.className` | IngressClass that will be used | `"traefik"` |
| `ingress.annotations` | Additional ingress annotations | See values.yaml |
| `ingress.hosts[0].host` | Default host for the ingress resource | `chart-example.local` |
| `ingress.tls` | TLS configuration | `[]` |
### Persistence parameters
| Name | Description | Value |
|--------------------------------------|------------------------------------------|------------------|
| `persistence.enabled` | Enable persistence using PVC | `true` |
| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` |
| `persistence.size` | PVC Storage Request | `1Gi` |
| `persistence.storageClass` | Storage class of backing PVC | `""` |
### Resource parameters
| Name | Description | Value |
|-------------------------------|------------------------------------------|-----------|
| `resources.limits.cpu` | CPU limit | `500m` |
| `resources.limits.memory` | Memory limit | `512Mi` |
| `resources.requests.cpu` | CPU request | `100m` |
| `resources.requests.memory` | Memory request | `128Mi` |
### Probe parameters
| Name | Description | Value |
|--------------------------------------|--------------------------------------------|-----------|
| `probes.liveness.enabled` | Enable liveness probe | `true` |
| `probes.liveness.path` | Path for liveness probe | `/` |
| `probes.readiness.enabled` | Enable readiness probe | `true` |
| `probes.readiness.path` | Path for readiness probe | `/` |
## Traefik Ingress Configuration
The chart includes specially configured middlewares for Traefik to ensure proper functioning of Recipya:
```yaml
ingress:
enabled: true
className: "traefik"
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: recipya-recipya-headers@kubernetescrd
traefik.ingress.kubernetes.io/service.sticky: "true"
traefik.ingress.kubernetes.io/session-cookie-name: "recipya_session"
hosts:
- host: recipya.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- hosts:
- recipya.example.com
```
This configuration includes:
1. Custom Content Security Policy allowing essential scripts from unpkg.com
2. Sticky sessions for maintaining authentication
3. Proper headers for proxy operation
## Content Security Policy Configuration
The chart includes a custom middleware that configures the proper Content Security Policy for Recipya. This is particularly important as the application requires access to external scripts from unpkg.com:
```yaml
contentSecurityPolicy: >-
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data: https://unpkg.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob:;
font-src 'self' data:;
connect-src 'self' ws: wss: *;
worker-src 'self' blob:;
frame-src 'self';
media-src 'self' blob:;
object-src 'none';
form-action 'self';
```
## Using Existing Secrets
If you want to use existing secrets for sensitive data:
```yaml
config:
email:
existingSecret: "my-email-secret"
addressKey: "email"
sendgridKey: "sendgrid"
documentIntelligence:
existingSecret: "my-di-secret"
endpointKey: "di_endpoint"
keyKey: "di_key"
```
## Configuration
See the [Recipya documentation](https://recipes.musicavis.ca/docs/installation/docker/#environment-variables) for details on all available configuration options.

View File

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "recipya.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 "recipya.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 "recipya.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "recipya.labels" -}}
helm.sh/chart: {{ include "recipya.chart" . }}
{{ include "recipya.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "recipya.selectorLabels" -}}
app.kubernetes.io/name: {{ include "recipya.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "recipya.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "recipya.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,73 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "recipya.fullname" . }}-init-script
labels:
{{- include "recipya.labels" . | nindent 4 }}
data:
init.sh: |
#!/bin/sh
set -e
CONFIG_DIR="/home/recipya/.config/Recipya"
CONFIG_FILE="$CONFIG_DIR/config.json"
TARGET_PORT={{ .Values.config.server.port }}
echo "Starting initialization with port $TARGET_PORT..."
# Create directories if they don't exist
mkdir -p $CONFIG_DIR/Backup
mkdir -p $CONFIG_DIR/Database
mkdir -p $CONFIG_DIR/Images
mkdir -p $CONFIG_DIR/Logs
mkdir -p $CONFIG_DIR/Videos
echo "Directories created."
# Create config.json if it doesn't exist or update the existing one
if [ -f "$CONFIG_FILE" ]; then
echo "Found existing config.json, updating port to $TARGET_PORT"
# Use jq to modify the port in the existing config file
TMP_FILE=$(mktemp)
cat $CONFIG_FILE | jq ".server.port = $TARGET_PORT" > $TMP_FILE
mv $TMP_FILE $CONFIG_FILE
else
echo "Creating new config.json with port $TARGET_PORT"
# Create a new config.json with default values and the specified port
cat > $CONFIG_FILE << EOF
{
"email": {
"from": "{{ .Values.config.email.address | default "" }}",
"sendGridAPIKey": "{{ .Values.config.email.sendgrid | default "" }}"
},
"integrations": {
"azureDocumentIntelligence": {
"endpoint": "{{ .Values.config.documentIntelligence.endpoint | default "" }}",
"key": "{{ .Values.config.documentIntelligence.key | default "" }}"
}
},
"server": {
"autologin": {{ .Values.config.server.autologin }},
"bypassGuide": false,
"isDemo": {{ .Values.config.server.is_demo }},
"noSignups": {{ .Values.config.server.no_signups }},
"isProduction": {{ .Values.config.server.is_prod }},
"port": $TARGET_PORT,
"url": "{{ .Values.config.server.url }}"
}
}
EOF
fi
# Set permissions using numeric IDs
echo "Setting permissions..."
chmod -R 755 $CONFIG_DIR
find $CONFIG_DIR -type f -exec chmod 644 {} \;
find $CONFIG_DIR -type d -exec chmod 755 {} \;
# Change ownership by numeric ID
echo "Changing ownership to 1000:1000..."
chown -R 1000:1000 $CONFIG_DIR
echo "Configuration completed successfully."
ls -la $CONFIG_DIR

View File

@ -0,0 +1,226 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "recipya.fullname" . }}
labels:
{{- include "recipya.labels" . | nindent 4 }}
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
checksum/init-script: {{ include (print $.Template.BasePath "/configmap-init-script.yaml") . | sha256sum }}
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "recipya.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
{{- include "recipya.selectorLabels" . | nindent 8 }}
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
# Set security context for the pod
securityContext:
fsGroup: 1000
# Init container to configure the application
initContainers:
- name: init-config
image: alpine:3.18
command: ["/bin/sh", "-c"]
args:
- |
echo "Installing jq..."
apk add --no-cache jq
echo "Running initialization script..."
/scripts/init.sh
securityContext:
runAsUser: 0 # Run as root to modify config files
runAsGroup: 0
volumeMounts:
- name: data
mountPath: /home/recipya/.config/Recipya
- name: init-script
mountPath: /scripts
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
# Main application container
containers:
- name: {{ .Chart.Name }}
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
readOnlyRootFilesystem: false
capabilities:
drop:
- ALL
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.startupArgs }}
args:
{{- range .Values.startupArgs }}
- {{ . | quote }}
{{- end }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{- if .Values.probes.liveness.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.probes.liveness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
successThreshold: {{ .Values.probes.liveness.successThreshold }}
{{- end }}
{{- if .Values.probes.readiness.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.probes.readiness.path }}
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
successThreshold: {{ .Values.probes.readiness.successThreshold }}
{{- end }}
env:
# Critical environment variables for proper directory structure
- name: HOME
value: "/home/recipya"
- name: RECIPYA_SERVER_URL
value: {{ .Values.config.server.url | quote }}
- name: RECIPYA_SERVER_AUTOLOGIN
value: {{ .Values.config.server.autologin | quote }}
- name: RECIPYA_SERVER_IS_DEMO
value: {{ .Values.config.server.is_demo | quote }}
- name: RECIPYA_SERVER_IS_PROD
value: {{ .Values.config.server.is_prod | quote }}
- name: RECIPYA_SERVER_NO_SIGNUPS
value: {{ .Values.config.server.no_signups | quote }}
{{- if .Values.config.email.existingSecret }}
- name: RECIPYA_EMAIL
valueFrom:
secretKeyRef:
name: {{ .Values.config.email.existingSecret }}
key: {{ .Values.config.email.addressKey }}
- name: RECIPYA_EMAIL_SENDGRID
valueFrom:
secretKeyRef:
name: {{ .Values.config.email.existingSecret }}
key: {{ .Values.config.email.sendgridKey }}
{{- else }}
{{- if .Values.config.email.address }}
- name: RECIPYA_EMAIL
valueFrom:
secretKeyRef:
name: {{ include "recipya.fullname" . }}-secrets
key: {{ .Values.config.email.addressKey }}
optional: true
{{- end }}
{{- if .Values.config.email.sendgrid }}
- name: RECIPYA_EMAIL_SENDGRID
valueFrom:
secretKeyRef:
name: {{ include "recipya.fullname" . }}-secrets
key: {{ .Values.config.email.sendgridKey }}
optional: true
{{- end }}
{{- end }}
{{- if .Values.config.documentIntelligence.existingSecret }}
- name: RECIPYA_DI_ENDPOINT
valueFrom:
secretKeyRef:
name: {{ .Values.config.documentIntelligence.existingSecret }}
key: {{ .Values.config.documentIntelligence.endpointKey }}
- name: RECIPYA_DI_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.config.documentIntelligence.existingSecret }}
key: {{ .Values.config.documentIntelligence.keyKey }}
{{- else }}
{{- if .Values.config.documentIntelligence.endpoint }}
- name: RECIPYA_DI_ENDPOINT
valueFrom:
secretKeyRef:
name: {{ include "recipya.fullname" . }}-secrets
key: {{ .Values.config.documentIntelligence.endpointKey }}
optional: true
{{- end }}
{{- if .Values.config.documentIntelligence.key }}
- name: RECIPYA_DI_KEY
valueFrom:
secretKeyRef:
name: {{ include "recipya.fullname" . }}-secrets
key: {{ .Values.config.documentIntelligence.keyKey }}
optional: true
{{- end }}
{{- end }}
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: data
mountPath: /home/recipya/.config/Recipya
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ include "recipya.fullname" . }}-data
- name: init-script
configMap:
name: {{ include "recipya.fullname" . }}-init-script
defaultMode: 0755
{{- with .Values.extraVolumes }}
{{- 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 }}

View File

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

View File

@ -0,0 +1,24 @@
{{- if .Values.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "recipya.fullname" . }}-data
labels:
{{- include "recipya.labels" . | nindent 4 }}
annotations:
{{- if .Values.persistence.retain }}
"helm.sh/resource-policy": keep
{{- end }}
{{- with .Values.persistence.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
{{- if .Values.persistence.storageClass }}
storageClassName: {{ .Values.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end }}

View File

@ -0,0 +1,28 @@
{{- $createSecret := or (and (not .Values.config.email.existingSecret) (or .Values.config.email.address .Values.config.email.sendgrid)) (and (not .Values.config.documentIntelligence.existingSecret) (or .Values.config.documentIntelligence.endpoint .Values.config.documentIntelligence.key)) -}}
{{- if $createSecret }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "recipya.fullname" . }}-secrets
labels:
{{- include "recipya.labels" . | nindent 4 }}
type: Opaque
data:
{{- if not .Values.config.email.existingSecret }}
{{- if .Values.config.email.address }}
{{ .Values.config.email.addressKey }}: {{ .Values.config.email.address | b64enc }}
{{- end }}
{{- if .Values.config.email.sendgrid }}
{{ .Values.config.email.sendgridKey }}: {{ .Values.config.email.sendgrid | b64enc }}
{{- end }}
{{- end }}
{{- if not .Values.config.documentIntelligence.existingSecret }}
{{- if .Values.config.documentIntelligence.endpoint }}
{{ .Values.config.documentIntelligence.endpointKey }}: {{ .Values.config.documentIntelligence.endpoint | b64enc }}
{{- end }}
{{- if .Values.config.documentIntelligence.key }}
{{ .Values.config.documentIntelligence.keyKey }}: {{ .Values.config.documentIntelligence.key | b64enc }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "recipya.fullname" . }}
labels:
{{- include "recipya.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "recipya.selectorLabels" . | nindent 4 }}

133
charts/recipya/values.yaml Normal file
View File

@ -0,0 +1,133 @@
# Default values for recipya.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
revisionHistoryLimit: 3
image:
repository: reaper99/recipya
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "v1.2.2"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
# Security context for the pod
podSecurityContext:
fsGroup: 1000
containerSecurityContext: {}
# Service configuration
service:
type: ClusterIP
port: 8078
# Recipya configuration
config:
email:
address: ""
sendgrid: ""
existingSecret: ""
addressKey: "email"
sendgridKey: "sendgrid"
documentIntelligence:
endpoint: ""
key: ""
existingSecret: ""
endpointKey: "di_endpoint"
keyKey: "di_key"
server:
port: 8078
autologin: false
is_demo: false
is_prod: true
no_signups: false
url: "http://0.0.0.0"
# Ingress configuration
ingress:
enabled: false
className: ""
annotations: []
# traefik.ingress.kubernetes.io/router.entrypoints: websecure
# traefik.ingress.kubernetes.io/router.middlewares: default-recipya-headers@kubernetescrd
hosts:
- host: recipya.<domain>
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
# Persistent volume claim
persistence:
enabled: false
accessMode: ReadWriteOnce
size: 5Gi
storageClass: ""
annotations: {}
retain: true
# Resource limits and requests
# resources:
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 100m
# memory: 128Mi
# Node selector
nodeSelector: {}
# Tolerations
tolerations: []
# Affinity
affinity: {}
# Additional pod annotations
podAnnotations: {}
# Startup arguments
startupArgs: []
# Additional environment variables
env: []
# Extra environment variables
extraEnv: []
# Extra volume mounts
extraVolumeMounts: []
# Extra volumes
extraVolumes: []
# Probes configuration
probes:
liveness:
enabled: true
path: /
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
readiness:
enabled: true
path: /
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1