add tandoor

This commit is contained in:
Morten Olsen
2026-01-19 05:02:42 +01:00
parent e604e03831
commit 46753fba60
6 changed files with 265 additions and 41 deletions

View File

@@ -0,0 +1,7 @@
apiVersion: v2
version: 1.0.0
name: tandoor
dependencies:
- name: common
version: 1.0.0
repository: file://../../common

View File

@@ -0,0 +1 @@
{{ include "common.all" . }}

View File

@@ -0,0 +1,21 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "common.fullname" . }}-social-providers-template
labels:
{{- include "common.labels" . | nindent 4 }}
data:
socialaccount_providers.json.template: |
{
"authentik": {
"APPS": [
{
"client_id": "${CLIENT_ID}",
"secret": "${CLIENT_SECRET}",
"settings": {
"server_url": "${ISSUER}/.well-known/openid-configuration"
}
}
]
}
}

View File

@@ -0,0 +1,142 @@
image:
repository: vabene1111/recipes
tag: latest
pullPolicy: IfNotPresent
subdomain: recipes
deployment:
strategy: Recreate
replicas: 1
container:
port: 80
service:
port: 80
type: ClusterIP
volumes:
- name: media
mountPath: /opt/recipes/mediafiles
persistentVolumeClaim: tandoor-media
- name: static
mountPath: /opt/recipes/staticfiles
persistentVolumeClaim: tandoor-static
- name: social-providers-vol
mountPath: /run/secrets
emptyDir: {}
- name: config-template
mountPath: /config-template
configMap: "{release}-social-providers-template"
initContainers:
- name: create-social-providers
image: alpine:latest
command: ["/bin/sh", "-c"]
args:
- |
sed -e "s|\${CLIENT_ID}|$CLIENT_ID|g" \
-e "s|\${CLIENT_SECRET}|$CLIENT_SECRET|g" \
-e "s|\${ISSUER}|$ISSUER|g" \
/config-template/socialaccount_providers.json.template > /run/secrets/socialaccount_providers.txt
env:
- name: CLIENT_ID
valueFrom:
secretKeyRef:
name: "{release}-oidc-credentials"
key: clientId
- name: CLIENT_SECRET
valueFrom:
secretKeyRef:
name: "{release}-oidc-credentials"
key: clientSecret
- name: ISSUER
valueFrom:
secretKeyRef:
name: "{release}-oidc-credentials"
key: issuer
volumeMounts:
- name: social-providers-vol
mountPath: /run/secrets
- name: config-template
mountPath: /config-template
persistentVolumeClaims:
- name: media
size: 10Gi
- name: static
size: 1Gi
virtualService:
enabled: true
gateways:
public: true
private: true
oidc:
enabled: true
redirectUris:
- "/accounts/authentik/login/callback/"
subjectMode: user_username
database:
enabled: true
externalSecrets:
- name: "{release}-secrets"
passwords:
- name: secret-key
length: 64
encoding: base64
allowRepeat: true
secretKeys:
- secret-key
env:
TZ:
value: "{timezone}"
DEBUG: "0"
TANDOOR_PORT: "80"
# ALLOWED_HOSTS: "*"
SECRET_KEY:
valueFrom:
secretKeyRef:
name: "{release}-secrets"
key: secret-key
# Database
POSTGRES_HOST:
valueFrom:
secretKeyRef:
name: "{release}-connection"
key: host
POSTGRES_PORT:
valueFrom:
secretKeyRef:
name: "{release}-connection"
key: port
POSTGRES_DB:
valueFrom:
secretKeyRef:
name: "{release}-connection"
key: database
POSTGRES_USER:
valueFrom:
secretKeyRef:
name: "{release}-connection"
key: user
POSTGRES_PASSWORD:
valueFrom:
secretKeyRef:
name: "{release}-connection"
key: password
# Authentication
SOCIALACCOUNT_PROVIDERS_FILE: "/run/secrets/socialaccount_providers.txt"
ENABLE_OIDC: "1"
# Gunicorn configuration to serve files without nginx
TANDOOR_GUNICORN_MEDIA: "1"
TANDOOR_GUNICORN_STATIC: "1"

View File

@@ -525,54 +525,66 @@ externalSecrets:
The secret will contain a key named `mySecretKey` (not `my-password-generator`). The secret will contain a key named `mySecretKey` (not `my-password-generator`).
## Secret-based Configurations ## Secret-based Configurations (via Init Container)
When an application requires a configuration file (like `config.yaml` or `.env`) that contains sensitive data, you should generate a `Secret` using External Secrets templating instead of a `ConfigMap`. This keeps the sensitive data encrypted in ETCD while allowing you to merge static and dynamic values. When an application requires a configuration file (like `config.yaml` or `.env`) that contains sensitive data from multiple sources (e.g., merging static config with secrets), you can use an `initContainer` to generate the file from a template. This is especially useful when a `SecretStore` is not available for External Secrets templating.
### 1. Create an External Secret with a Template ### 1. Create a ConfigMap Template
Create a custom template in your chart (e.g., `templates/external-config.yaml`): Create a custom template in your chart (e.g., `templates/config-template.yaml`):
```yaml ```yaml
apiVersion: external-secrets.io/v1beta1 apiVersion: v1
kind: ExternalSecret kind: ConfigMap
metadata: metadata:
name: {{ include "common.fullname" . }}-config name: {{ include "common.fullname" . }}-config-template
spec: labels:
refreshInterval: 1h {{- include "common.labels" . | nindent 4 }}
secretStoreRef: data:
name: vault-backend # Replace with your SecretStore name config.yaml.template: |
kind: SecretStore server:
target: port: 8080
name: {{ include "common.fullname" . }}-config database:
template: user: "${DB_USER}"
engineVersion: v2 password: "${DB_PASS}"
data:
config.yaml: |
server:
port: 8080
database:
user: {{ "{{" }} .db_user | toString {{ "}}" }}
password: {{ "{{" }} .db_pass | toString {{ "}}" }}
data:
- secretKey: db_user
remoteRef:
key: database/credentials
property: username
- secretKey: db_pass
remoteRef:
key: database/credentials
property: password
``` ```
### 2. Mount the Secret in values.yaml ### 2. Configure Init Container and Volumes in values.yaml
Reference the generated secret in your `volumes` configuration using the `{release}` placeholder: Reference the template and secrets in your `values.yaml`:
```yaml ```yaml
volumes: volumes:
- name: config - name: config-vol
mountPath: /app/config.yaml mountPath: /app/config
subPath: config.yaml emptyDir: {}
secret: "{release}-config" - name: config-template
mountPath: /config-template
configMap: "{release}-config-template"
initContainers:
- name: generate-config
image: alpine:latest
command: ["/bin/sh", "-c"]
args:
- |
sed -e "s|\${DB_USER}|$DB_USER|g" \
-e "s|\${DB_PASS}|$DB_PASS|g" \
/config-template/config.yaml.template > /app/config/config.yaml
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: "{release}-db-credentials"
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: "{release}-db-credentials"
key: password
volumeMounts:
- name: config-vol
mountPath: /app/config
- name: config-template
mountPath: /config-template
``` ```
## Placeholders ## Placeholders

View File

@@ -347,17 +347,58 @@ spec:
{{- include "common.dnsConfig" . | nindent 6 }} {{- include "common.dnsConfig" . | nindent 6 }}
{{- if .Values.initContainers }} {{- if .Values.initContainers }}
initContainers: initContainers:
{{- toYaml .Values.initContainers | nindent 8 }} {{- $initContainers := toYaml .Values.initContainers -}}
{{- $initContainers = $initContainers | replace "{release}" .Release.Name -}}
{{- $initContainers = $initContainers | replace "{namespace}" .Release.Namespace -}}
{{- $initContainers = $initContainers | replace "{fullname}" (include "common.fullname" .) -}}
{{- if .Values.subdomain -}}
{{- $initContainers = $initContainers | replace "{subdomain}" .Values.subdomain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.domain -}}
{{- $initContainers = $initContainers | replace "{domain}" .Values.globals.domain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.timezone -}}
{{- $initContainers = $initContainers | replace "{timezone}" .Values.globals.timezone -}}
{{- end -}}
{{- $initContainers | nindent 8 }}
{{- end }} {{- end }}
containers: containers:
- name: {{ .Chart.Name }} - name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
{{- if .Values.command }} {{- if .Values.command }}
command: {{- toYaml .Values.command | nindent 12 }} command:
{{- $command := toYaml .Values.command -}}
{{- $command = $command | replace "{release}" .Release.Name -}}
{{- $command = $command | replace "{namespace}" .Release.Namespace -}}
{{- $command = $command | replace "{fullname}" (include "common.fullname" .) -}}
{{- if .Values.subdomain -}}
{{- $command = $command | replace "{subdomain}" .Values.subdomain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.domain -}}
{{- $command = $command | replace "{domain}" .Values.globals.domain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.timezone -}}
{{- $command = $command | replace "{timezone}" .Values.globals.timezone -}}
{{- end -}}
{{- $command | nindent 12 }}
{{- end }} {{- end }}
{{- if .Values.args }} {{- if .Values.args }}
args: {{- toYaml .Values.args | nindent 12 }} args:
{{- $args := toYaml .Values.args -}}
{{- $args = $args | replace "{release}" .Release.Name -}}
{{- $args = $args | replace "{namespace}" .Release.Namespace -}}
{{- $args = $args | replace "{fullname}" (include "common.fullname" .) -}}
{{- if .Values.subdomain -}}
{{- $args = $args | replace "{subdomain}" .Values.subdomain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.domain -}}
{{- $args = $args | replace "{domain}" .Values.globals.domain -}}
{{- end -}}
{{- if and .Values.globals .Values.globals.timezone -}}
{{- $args = $args | replace "{timezone}" .Values.globals.timezone -}}
{{- end -}}
{{- $args | nindent 12 }}
{{- end }} {{- end }}
ports: ports:
{{ include "common.containerPorts" . | indent 12 }} {{ include "common.containerPorts" . | indent 12 }}