From e673346bb86626f1c0119141f20dff987c33440d Mon Sep 17 00:00:00 2001 From: deepakdeore2004 Date: Thu, 12 Mar 2026 19:12:26 +0000 Subject: [PATCH] Support to read environment variables from file in init containers (#993) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description of the change Gitea supports providing DB and Redis/ValKey secrets via env variables, current chart requires DB and Redis/ ValKey credentials reading from k8s secret as per below values.yaml snippet. This approach requires secret to be created beforehand. ``` - name: GITEA__database__USER valueFrom: secretKeyRef: name: gitea-ha key: db_user - name: GITEA__database__PASSWD valueFrom: secretKeyRef: name: gitea-ha key: db_password ``` Other approach is to provide the credentials in values.yaml which isnt secure. A bash variable file can be created by using vault injector like this, which then can be sourced while running `config_environment.sh` in `init-app-ini` ``` GITEA__database__NAME=gitea GITEA__database__USER=gitea_user ``` Support to read env variables from file Reference: https://developer.hashicorp.com/vault/docs/deploy/kubernetes/injector/examples#environment-variable-example ### Benefits Support to read env variables from file created by vault injector for DB and redis/ valkey credentials Support to set gitea admin user and credentials via env variables from file created by vault injector ### Possible drawbacks N/A ### ⚠ BREAKING No breaking changes ### Checklist - [X] Parameters are documented in the `values.yaml` and added to the `README.md` using [readme-generator-for-helm](https://github.com/bitnami-labs/readme-generator-for-helm) --------- Co-authored-by: techknowlogick Reviewed-on: https://gitea.com/gitea/helm-gitea/pulls/993 Co-authored-by: deepakdeore2004 Co-committed-by: deepakdeore2004 --- README.md | 47 +++++------ templates/gitea/deployment.yaml | 24 ++++++ .../helm/deployment/extraEnvSourceFile.yaml | 82 +++++++++++++++++++ values.yaml | 22 +++++ 4 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 unittests/helm/deployment/extraEnvSourceFile.yaml diff --git a/README.md b/README.md index f8ce6e3..6588ef3 100644 --- a/README.md +++ b/README.md @@ -1098,29 +1098,30 @@ To comply with the Gitea helm chart definition of the digest parameter, a "custo ### Gitea -| Name | Description | Value | -| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------- | -| `gitea.admin.username` | Username for the Gitea admin user | `gitea_admin` | -| `gitea.admin.existingSecret` | Use an existing secret to store admin user credentials | `nil` | -| `gitea.admin.password` | Password for the Gitea admin user | `r8sA8CPHD9!bt6d` | -| `gitea.admin.email` | Email for the Gitea admin user | `gitea@local.domain` | -| `gitea.admin.passwordMode` | Mode for how to set/update the admin user password. Options are: initialOnlyNoReset, initialOnlyRequireReset, and keepUpdated | `keepUpdated` | -| `gitea.metrics.enabled` | Enable Gitea metrics | `false` | -| `gitea.metrics.token` | used for `bearer` token authentication on metrics endpoint. If not specified or empty metrics endpoint is public. | `nil` | -| `gitea.metrics.serviceMonitor.enabled` | Enable Gitea metrics service monitor. Requires, that `gitea.metrics.enabled` is also set to true, to enable metrics generally. | `false` | -| `gitea.metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. | `""` | -| `gitea.metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | -| `gitea.metrics.serviceMonitor.scheme` | HTTP scheme to use for scraping. For example `http` or `https`. Default is http. | `""` | -| `gitea.metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. | `""` | -| `gitea.metrics.serviceMonitor.tlsConfig` | TLS configuration to use when scraping the metric endpoint by Prometheus. | `{}` | -| `gitea.ldap` | LDAP configuration | `[]` | -| `gitea.oauth` | OAuth configuration | `[]` | -| `gitea.config.server.SSH_PORT` | SSH port for rootlful Gitea image | `22` | -| `gitea.config.server.SSH_LISTEN_PORT` | SSH port for rootless Gitea image | `2222` | -| `gitea.additionalConfigSources` | Additional configuration from secret or configmap | `[]` | -| `gitea.additionalConfigFromEnvs` | Additional configuration sources from environment variables | `[]` | -| `gitea.podAnnotations` | Annotations for the Gitea pod | `{}` | -| `gitea.ssh.logLevel` | Configure OpenSSH's log level. Only available for root-based Gitea image. | `INFO` | +| Name | Description | Value | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `gitea.admin.username` | Username for the Gitea admin user | `gitea_admin` | +| `gitea.admin.existingSecret` | Use an existing secret to store admin user credentials | `nil` | +| `gitea.admin.password` | Password for the Gitea admin user | `r8sA8CPHD9!bt6d` | +| `gitea.admin.email` | Email for the Gitea admin user | `gitea@local.domain` | +| `gitea.admin.passwordMode` | Mode for how to set/update the admin user password. Options are: initialOnlyNoReset, initialOnlyRequireReset, and keepUpdated | `keepUpdated` | +| `gitea.metrics.enabled` | Enable Gitea metrics | `false` | +| `gitea.metrics.token` | used for `bearer` token authentication on metrics endpoint. If not specified or empty metrics endpoint is public. | `nil` | +| `gitea.metrics.serviceMonitor.enabled` | Enable Gitea metrics service monitor. Requires, that `gitea.metrics.enabled` is also set to true, to enable metrics generally. | `false` | +| `gitea.metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. If not specified Prometheus' global scrape interval is used. | `""` | +| `gitea.metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `gitea.metrics.serviceMonitor.scheme` | HTTP scheme to use for scraping. For example `http` or `https`. Default is http. | `""` | +| `gitea.metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended. If not specified, global Prometheus scrape timeout is used. | `""` | +| `gitea.metrics.serviceMonitor.tlsConfig` | TLS configuration to use when scraping the metric endpoint by Prometheus. | `{}` | +| `gitea.ldap` | LDAP configuration | `[]` | +| `gitea.oauth` | OAuth configuration | `[]` | +| `gitea.config.server.SSH_PORT` | SSH port for rootlful Gitea image | `22` | +| `gitea.config.server.SSH_LISTEN_PORT` | SSH port for rootless Gitea image | `2222` | +| `gitea.additionalConfigSources` | Additional configuration from secret or configmap | `[]` | +| `gitea.additionalConfigFromEnvs` | Additional configuration sources from environment variables | `[]` | +| `gitea.extraEnvSourceFile` | Source environment variables from a file during init container startup. This is especially useful for reading environment variable files generated by the Vault agent-injector. | `nil` | +| `gitea.podAnnotations` | Annotations for the Gitea pod | `{}` | +| `gitea.ssh.logLevel` | Configure OpenSSH's log level. Only available for root-based Gitea image. | `INFO` | ### LivenessProbe diff --git a/templates/gitea/deployment.yaml b/templates/gitea/deployment.yaml index 8871323..8372313 100644 --- a/templates/gitea/deployment.yaml +++ b/templates/gitea/deployment.yaml @@ -98,8 +98,16 @@ spec: - name: init-app-ini image: "{{ include "gitea.image" . }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.gitea.extraEnvSourceFile }} + command: + - "/bin/bash" + - "-c" + args: + - "test -f {{ .Values.gitea.extraEnvSourceFile }} && source {{ .Values.gitea.extraEnvSourceFile }} || { echo 'ERROR: Failed to source {{ .Values.gitea.extraEnvSourceFile }}'; exit 1; } && {{ .Values.initContainersScriptsVolumeMountPath }}/config_environment.sh" + {{- else }} command: - "{{ .Values.initContainersScriptsVolumeMountPath }}/config_environment.sh" + {{- end }} env: - name: GITEA_APP_INI value: /data/gitea/conf/app.ini @@ -143,8 +151,16 @@ spec: {{- if .Values.signing.enabled }} - name: configure-gpg image: "{{ include "gitea.image" . }}" + {{- if .Values.gitea.extraEnvSourceFile }} + command: + - "/bin/bash" + - "-c" + args: + - "test -f {{ .Values.gitea.extraEnvSourceFile }} && source {{ .Values.gitea.extraEnvSourceFile }} || { echo 'ERROR: Failed to source {{ .Values.gitea.extraEnvSourceFile }}'; exit 1; } && {{ .Values.initContainersScriptsVolumeMountPath }}/configure_gpg_environment.sh" + {{- else }} command: - "{{ .Values.initContainersScriptsVolumeMountPath }}/configure_gpg_environment.sh" + {{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} securityContext: {{- /* By default this container runs as user 1000 unless otherwise stated */ -}} @@ -177,8 +193,16 @@ spec: {{- end }} - name: configure-gitea image: "{{ include "gitea.image" . }}" + {{- if .Values.gitea.extraEnvSourceFile }} + command: + - "/bin/bash" + - "-c" + args: + - "test -f {{ .Values.gitea.extraEnvSourceFile }} && source {{ .Values.gitea.extraEnvSourceFile }} || { echo 'ERROR: Failed to source {{ .Values.gitea.extraEnvSourceFile }}'; exit 1; } && {{ .Values.initContainersScriptsVolumeMountPath }}/configure_gitea.sh" + {{- else }} command: - "{{ .Values.initContainersScriptsVolumeMountPath }}/configure_gitea.sh" + {{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} securityContext: {{- /* By default this container runs as user 1000 unless otherwise stated */ -}} diff --git a/unittests/helm/deployment/extraEnvSourceFile.yaml b/unittests/helm/deployment/extraEnvSourceFile.yaml new file mode 100644 index 0000000..57969e7 --- /dev/null +++ b/unittests/helm/deployment/extraEnvSourceFile.yaml @@ -0,0 +1,82 @@ +suite: deployment template (extraEnvSourceFile) +release: + name: gitea-unittests + namespace: testing +templates: + - templates/gitea/deployment.yaml + - templates/gitea/config.yaml +tests: + - it: uses direct execution when extraEnvSourceFile is not set + template: templates/gitea/deployment.yaml + asserts: + - equal: + path: spec.template.spec.initContainers[1].command + value: ["/usr/sbinx/config_environment.sh"] + - notExists: + path: spec.template.spec.initContainers[1].args + - equal: + path: spec.template.spec.initContainers[2].command + value: ["/usr/sbinx/configure_gitea.sh"] + - notExists: + path: spec.template.spec.initContainers[2].args + + - it: sources env file in init-app-ini when extraEnvSourceFile is set + template: templates/gitea/deployment.yaml + set: + gitea: + extraEnvSourceFile: /vault/secrets/gitea + asserts: + - equal: + path: spec.template.spec.initContainers[1].command + value: ["/bin/bash", "-c"] + - matchRegex: + path: spec.template.spec.initContainers[1].args[0] + pattern: source /vault/secrets/gitea + - matchRegex: + path: spec.template.spec.initContainers[1].args[0] + pattern: config_environment\.sh + + - it: sources env file in configure-gitea when extraEnvSourceFile is set + template: templates/gitea/deployment.yaml + set: + gitea: + extraEnvSourceFile: /vault/secrets/gitea + asserts: + - equal: + path: spec.template.spec.initContainers[2].command + value: ["/bin/bash", "-c"] + - matchRegex: + path: spec.template.spec.initContainers[2].args[0] + pattern: source /vault/secrets/gitea + - matchRegex: + path: spec.template.spec.initContainers[2].args[0] + pattern: configure_gitea\.sh + + - it: sources env file in configure-gpg when extraEnvSourceFile is set with signing enabled + template: templates/gitea/deployment.yaml + set: + signing: + enabled: true + existingSecret: "custom-gpg-secret" + gitea: + extraEnvSourceFile: /vault/secrets/gitea + asserts: + - equal: + path: spec.template.spec.initContainers[2].command + value: ["/bin/bash", "-c"] + - matchRegex: + path: spec.template.spec.initContainers[2].args[0] + pattern: source /vault/secrets/gitea + - matchRegex: + path: spec.template.spec.initContainers[2].args[0] + pattern: configure_gpg_environment\.sh + + - it: includes file existence check in source command + template: templates/gitea/deployment.yaml + set: + gitea: + extraEnvSourceFile: /vault/secrets/gitea + asserts: + - matchRegex: + path: spec.template.spec.initContainers[1].args[0] + pattern: "test -f /vault/secrets/gitea" diff --git a/values.yaml b/values.yaml index 2dc53bf..313edd8 100644 --- a/values.yaml +++ b/values.yaml @@ -446,6 +446,28 @@ gitea: ## @param gitea.additionalConfigFromEnvs Additional configuration sources from environment variables additionalConfigFromEnvs: [] + ## @param gitea.extraEnvSourceFile Source environment variables from a file during init container startup. This is especially useful for reading environment variable files generated by the Vault agent-injector. + ## See the sample annotations below for reference. + ## podAnnotations: + ## vault.hashicorp.com/agent-inject: "true" + ## vault.hashicorp.com/agent-init-first: "true" + ## vault.hashicorp.com/agent-inject-secret-gitea: + ## vault.hashicorp.com/agent-inject-template-gitea: | + ## {{- with secret "path/to/secret" -}} + ## export GITEA__database__HOST="{{ .Data.data.db_host }}" + ## export GITEA__database__NAME="{{ .Data.data.db_name }}" + ## export GITEA__database__USER="{{ .Data.data.db_user }}" + ## export GITEA__database__PASSWD="{{ .Data.data.db_password }}" + ## export GITEA__queue__CONN_STR="{{ .Data.data.kv_conn_string }}" + ## export GITEA__session__PROVIDER_CONFIG="{{ .Data.data.kv_conn_string }}" + ## export GITEA__cache__HOST="{{ .Data.data.kv_conn_string }}" + ## export GITEA_ADMIN_USERNAME="{{ .Data.data.gitea_admin_user }}" + ## export GITEA_ADMIN_PASSWORD="{{ .Data.data.gitea_admin_password }}" + ## {{- end }} + + # extraEnvSourceFile: /vault/secrets/gitea + extraEnvSourceFile: + ## @param gitea.podAnnotations Annotations for the Gitea pod podAnnotations: {}