mirror of
https://github.com/hcengineering/huly-selfhost.git
synced 2026-10-01 22:15:08 +02:00
feat(helm): support externally managed secret via secrets.existingSecret (#323)
The chart preserves generated secrets across upgrades with a cluster lookup, which is only populated when Helm has a live cluster connection. GitOps tools render manifests without one, so every sync regenerates SERVER_SECRET and friends and invalidates all sessions. Setting secrets.existingSecret makes the chart skip its own Secret and point every service at the named one, so it can come from External Secrets Operator, Sealed Secrets, Vault, or kubectl.
This commit is contained in:
+48
-1
@@ -104,6 +104,50 @@ helm install huly ./helm/huly \
|
||||
--set external.elastic=https://es.example.com:9200
|
||||
```
|
||||
|
||||
## Externally Managed Secrets (GitOps)
|
||||
|
||||
By default the chart generates its own Secret and preserves the values across `helm upgrade`
|
||||
by looking up the Secret already in the cluster.
|
||||
|
||||
That lookup only works when Helm has a live cluster connection. Tools that render manifests
|
||||
without one — ArgoCD, Flux, `helm template`, `--dry-run` — always see an empty lookup, so every
|
||||
render regenerates `SERVER_SECRET`, `COCKROACH_PASSWORD` and the rest, which invalidates all
|
||||
sessions on each sync.
|
||||
|
||||
Set `secrets.existingSecret` to a Secret you manage yourself. The chart then renders no Secret
|
||||
of its own and points every service at the named one, so it can be produced by External Secrets
|
||||
Operator, Sealed Secrets, Vault, or `kubectl create secret`.
|
||||
|
||||
```bash
|
||||
kubectl create secret generic huly-secrets -n <namespace> \
|
||||
--from-literal=SERVER_SECRET="$(openssl rand -hex 16)" \
|
||||
--from-literal=COCKROACH_PASSWORD="$(openssl rand -hex 12)" \
|
||||
--from-literal=REDPANDA_SUPERUSER_PASSWORD="$(openssl rand -hex 12)" \
|
||||
--from-literal=AIBOT_PASSWORD="$(openssl rand -hex 12)" \
|
||||
--from-literal=CR_DB_URL='postgres://selfhost:<password>@cockroach:26257/defaultdb' \
|
||||
--from-literal=STORAGE_CONFIG='minio|minio?accessKey=<key>&secretKey=<secret>'
|
||||
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set secrets.existingSecret=huly-secrets
|
||||
```
|
||||
|
||||
| Key | Required when |
|
||||
|-----|---------------|
|
||||
| `SERVER_SECRET` | always |
|
||||
| `CR_DB_URL` | always |
|
||||
| `STORAGE_CONFIG` | always |
|
||||
| `COCKROACH_PASSWORD` | `cockroach.enabled=true` |
|
||||
| `REDPANDA_SUPERUSER_PASSWORD` | `redpanda.enabled=true` |
|
||||
| `AIBOT_PASSWORD`, `OPENAI_API_KEY` | `aibot.enabled=true` |
|
||||
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | `auth.google.clientId` is set |
|
||||
| `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | `auth.github.clientId` is set |
|
||||
| `OPENID_CLIENT_ID`, `OPENID_CLIENT_SECRET`, `OPENID_ISSUER` | `auth.oidc.clientId` is set |
|
||||
| `GITHUB_APP_ID`, `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_SECRET`, `GITHUB_APP_PRIVATE_KEY`, `GITHUB_APP_WEBHOOK_SECRET` | `githubIntegration.enabled=true` |
|
||||
|
||||
The `auth.*.clientId` values still gate whether a provider is wired into the account service, so
|
||||
keep setting them in values even though the credentials come from the external Secret.
|
||||
|
||||
## GitHub Integration
|
||||
|
||||
Bidirectional sync of issues, PRs, and comments between Huly and GitHub. Requires a [GitHub App](https://docs.github.com/en/apps/creating-github-apps).
|
||||
@@ -244,10 +288,13 @@ kubectl logs deployment/<service> -n <namespace> --tail=20
|
||||
|
||||
### Secrets
|
||||
|
||||
All secrets are auto-generated if left empty. They persist across `helm upgrade` via Kubernetes secret lookup.
|
||||
All secrets are auto-generated if left empty. They persist across `helm upgrade` via Kubernetes
|
||||
secret lookup, which requires a live cluster connection — see
|
||||
[Externally Managed Secrets (GitOps)](#externally-managed-secrets-gitops) for ArgoCD and Flux.
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `secrets.existingSecret` | Use a Secret you manage; disables the chart-managed Secret | `""` |
|
||||
| `secrets.serverSecret` | Shared JWT signing secret | auto |
|
||||
| `secrets.storageConfig` | Full storage connection string override | auto |
|
||||
| `secrets.cockroachPassword` | CockroachDB password | auto |
|
||||
|
||||
@@ -25,7 +25,11 @@ Create a default fully qualified app name.
|
||||
Secret resource name.
|
||||
*/}}
|
||||
{{- define "huly.secretName" -}}
|
||||
{{- printf "%s-secret" (include "huly.fullname" .) }}
|
||||
{{- if .Values.secrets.existingSecret -}}
|
||||
{{- .Values.secrets.existingSecret -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-secret" (include "huly.fullname" .) -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{{- if not .Values.secrets.existingSecret }}
|
||||
{{- $secretName := include "huly.secretName" . -}}
|
||||
{{- $existing := lookup "v1" "Secret" .Release.Namespace $secretName -}}
|
||||
{{- $hasExisting := not (empty $existing) -}}
|
||||
@@ -122,3 +123,4 @@ data:
|
||||
GITHUB_APP_PRIVATE_KEY: {{ .Values.githubIntegration.privateKey | b64enc | quote }}
|
||||
GITHUB_APP_WEBHOOK_SECRET: {{ .Values.githubIntegration.webhookSecret | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -21,6 +21,21 @@ hulyRegistry: hardcoreeng
|
||||
# Secrets — leave empty to auto-generate (persists across upgrades)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
secrets:
|
||||
# Use a Secret you manage instead of the chart-managed one.
|
||||
# When set, the chart renders no Secret of its own and every service reads
|
||||
# from the named Secret — required for GitOps tools (ArgoCD, Flux) that
|
||||
# render manifests without cluster access, and for External Secrets
|
||||
# Operator / Sealed Secrets / Vault.
|
||||
#
|
||||
# Required keys: SERVER_SECRET, CR_DB_URL, STORAGE_CONFIG,
|
||||
# COCKROACH_PASSWORD (when cockroach.enabled=true),
|
||||
# REDPANDA_SUPERUSER_PASSWORD (when redpanda.enabled=true),
|
||||
# AIBOT_PASSWORD and OPENAI_API_KEY (when aibot.enabled=true),
|
||||
# GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID/
|
||||
# GITHUB_CLIENT_SECRET, OPENID_CLIENT_ID/OPENID_CLIENT_SECRET/
|
||||
# OPENID_ISSUER (per configured auth provider),
|
||||
# GITHUB_APP_* (when githubIntegration.enabled=true)
|
||||
existingSecret: ""
|
||||
# Shared JWT signing secret (auto-generated if empty)
|
||||
serverSecret: ""
|
||||
# Full storage config string override.
|
||||
|
||||
Reference in New Issue
Block a user