mirror of
https://github.com/hcengineering/huly-selfhost.git
synced 2026-09-07 18:27:50 +02:00
feat: add Helm chart for Kubernetes deployment (#280)
* feat: add Helm chart for Kubernetes deployment Comprehensive Helm chart for deploying Huly to Kubernetes: - All core services (front, account, transactor, collaborator, etc.) - Infrastructure (CockroachDB, Redpanda, Elasticsearch, MinIO) - Optional AI bot with MongoDB - Automated backup CronJobs to S3-compatible storage - Configurable image registry and version pinning - Auto-generated secrets with persistence across upgrades - NGINX ingress with TLS via cert-manager - CI workflow for lint, template validation, and OCI publish Chart lives at helm/ (outside kube/) to avoid conflict with the existing kubectl-based CI that recursively applies kube/*.yaml. Signed-off-by: Daniel Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * feat(helm): add optional GitHub integration service Deploy pod-github for bidirectional sync of issues, PRs, and comments between Huly and GitHub. Gated behind githubIntegration.enabled (false by default). Adds: - templates/github/deployment.yaml + service.yaml - GITHUB_URL to configmap and front deployment - GitHub App credentials to shared secret - /_github ingress backend - README documentation for GitHub integration and AI bot Signed-off-by: Daniel Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> --------- Signed-off-by: Don Kendall <kendall@donkendall.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
8e8dce93b7
commit
5dc03d01aa
@@ -0,0 +1,52 @@
|
||||
name: Helm Chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "helm/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "helm/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
CHART_PATH: helm/huly
|
||||
OCI_REGISTRY: oci://ghcr.io/${{ github.repository_owner }}/charts
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint & Template
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: azure/setup-helm@v4
|
||||
- run: helm lint ${{ env.CHART_PATH }}
|
||||
- run: helm template huly ${{ env.CHART_PATH }} --set domain=ci.example.com
|
||||
|
||||
publish:
|
||||
name: Package & Push OCI
|
||||
needs: lint
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: azure/setup-helm@v4
|
||||
|
||||
- name: Extract chart version
|
||||
id: chart
|
||||
run: |
|
||||
version=$(grep '^version:' ${{ env.CHART_PATH }}/Chart.yaml | awk '{print $2}')
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Login to GHCR
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Package chart
|
||||
run: helm package ${{ env.CHART_PATH }} -d /tmp/charts
|
||||
|
||||
- name: Push to OCI registry
|
||||
run: helm push /tmp/charts/huly-${{ steps.chart.outputs.version }}.tgz ${{ env.OCI_REGISTRY }}
|
||||
@@ -0,0 +1 @@
|
||||
values-ledoweb.yaml
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: v2
|
||||
name: huly
|
||||
description: Huly — open-source project management platform
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "0.7.382"
|
||||
home: https://huly.io
|
||||
sources:
|
||||
- https://github.com/hcengineering/huly-selfhost
|
||||
keywords:
|
||||
- huly
|
||||
- project-management
|
||||
- collaboration
|
||||
@@ -0,0 +1,393 @@
|
||||
# Huly Helm Chart
|
||||
|
||||
Deploy [Huly](https://huly.io) — an open-source project management platform — on Kubernetes with a single command.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.25+
|
||||
- Helm 3.10+
|
||||
- [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)
|
||||
- [cert-manager](https://cert-manager.io/) (if using TLS)
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com
|
||||
```
|
||||
|
||||
All secrets (server secret, CockroachDB password, MinIO credentials) are auto-generated on first install and preserved across `helm upgrade`.
|
||||
|
||||
## Authentication
|
||||
|
||||
At least one auth provider should be configured. Without one, users cannot sign in.
|
||||
|
||||
### Google OAuth
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set auth.google.clientId=YOUR_CLIENT_ID \
|
||||
--set auth.google.clientSecret=YOUR_CLIENT_SECRET
|
||||
```
|
||||
|
||||
### GitHub OAuth
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set auth.github.clientId=YOUR_CLIENT_ID \
|
||||
--set auth.github.clientSecret=YOUR_CLIENT_SECRET
|
||||
```
|
||||
|
||||
### OpenID Connect (OIDC)
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set auth.oidc.clientId=YOUR_CLIENT_ID \
|
||||
--set auth.oidc.clientSecret=YOUR_CLIENT_SECRET \
|
||||
--set auth.oidc.issuer=https://accounts.google.com
|
||||
```
|
||||
|
||||
### Disable Public Signup
|
||||
|
||||
```bash
|
||||
--set auth.disableSignup=true
|
||||
```
|
||||
|
||||
## External S3 Storage
|
||||
|
||||
By default, the chart deploys a built-in MinIO instance. To use external S3-compatible storage instead:
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set storage.type=s3 \
|
||||
--set storage.s3.endpoint=https://s3.amazonaws.com \
|
||||
--set storage.s3.region=us-east-1 \
|
||||
--set storage.s3.accessKey=YOUR_ACCESS_KEY \
|
||||
--set storage.s3.secretKey=YOUR_SECRET_KEY \
|
||||
--set storage.s3.rootBucket=huly-data
|
||||
```
|
||||
|
||||
Setting `storage.type=s3` automatically disables the built-in MinIO deployment and PVC.
|
||||
|
||||
**Bucket modes:**
|
||||
- `rootBucket` — all workspaces share one bucket, isolated by workspace-ID prefix (recommended)
|
||||
- `bucketPrefix` — each workspace gets its own bucket, prefixed with this string
|
||||
|
||||
## External Infrastructure
|
||||
|
||||
Each built-in infra service (CockroachDB, Redpanda, Elasticsearch) can be replaced with an external instance.
|
||||
|
||||
### External CockroachDB / PostgreSQL
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set cockroach.enabled=false \
|
||||
--set secrets.crDbUrl='postgres://user:pass@db.example.com:26257/huly'
|
||||
```
|
||||
|
||||
### External Redpanda / Kafka
|
||||
|
||||
```bash
|
||||
--set redpanda.enabled=false \
|
||||
--set external.redpanda=kafka.example.com:9092
|
||||
```
|
||||
|
||||
### External Elasticsearch
|
||||
|
||||
```bash
|
||||
--set elastic.enabled=false \
|
||||
--set external.elastic=https://es.example.com:9200
|
||||
```
|
||||
|
||||
## 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).
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set githubIntegration.enabled=true \
|
||||
--set githubIntegration.appId=123456 \
|
||||
--set githubIntegration.clientId=Iv1.abc123 \
|
||||
--set githubIntegration.clientSecret=YOUR_SECRET \
|
||||
--set-file githubIntegration.privateKey=path/to/private-key.pem \
|
||||
--set githubIntegration.webhookSecret=YOUR_WEBHOOK_SECRET \
|
||||
--set githubIntegration.botName="your-app-name[bot]"
|
||||
```
|
||||
|
||||
**GitHub App settings:**
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Callback URL | `https://<domain>/github` |
|
||||
| Setup URL | `https://<domain>/github?op=installation` |
|
||||
| Webhook URL | `https://<domain>/_github/api/webhook` |
|
||||
| Permissions | Issues R/W, PRs R/W, Contents R, Metadata R |
|
||||
| Events | Issues, Issue comment, Pull request, PR review, PR review comment, PR review thread |
|
||||
|
||||
## AI Bot
|
||||
|
||||
Optional AI assistant powered by OpenAI. Requires an OpenAI API key.
|
||||
|
||||
```bash
|
||||
helm install huly ./helm/huly \
|
||||
--set domain=huly.mysite.com \
|
||||
--set aibot.enabled=true \
|
||||
--set secrets.openaiApiKey=sk-...
|
||||
```
|
||||
|
||||
## Admin Configuration
|
||||
|
||||
```bash
|
||||
--set appSettings.adminEmails="admin@example.com,ops@example.com"
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Version bumps
|
||||
|
||||
Update `hulyVersion` to the desired release tag:
|
||||
|
||||
```bash
|
||||
helm upgrade huly ./helm/huly \
|
||||
--reuse-values \
|
||||
--set hulyVersion=v0.7.400
|
||||
```
|
||||
|
||||
All app service pods restart automatically (via checksum annotations) when the chart version or config changes. Infrastructure services (CockroachDB, Redpanda, Elasticsearch) are **not** restarted on config changes to avoid data-layer disruption.
|
||||
|
||||
### From MinIO to S3
|
||||
|
||||
When switching storage backends, set the new storage type explicitly — it overrides any previously persisted config:
|
||||
|
||||
```bash
|
||||
helm upgrade huly ./helm/huly \
|
||||
--reuse-values \
|
||||
--set storage.type=s3 \
|
||||
--set storage.s3.endpoint=https://s3.example.com \
|
||||
--set storage.s3.region=us-east-1 \
|
||||
--set storage.s3.accessKey=KEY \
|
||||
--set storage.s3.secretKey=SECRET \
|
||||
--set storage.s3.rootBucket=huly-data
|
||||
```
|
||||
|
||||
After confirming S3 works, clean up the orphaned MinIO PVC:
|
||||
|
||||
```bash
|
||||
kubectl delete pvc minio-data -n <namespace>
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Services fail to start with connection errors
|
||||
|
||||
App services (account, transactor, workspace, fulltext) depend on CockroachDB and Redpanda. The chart includes init containers that wait for these services to accept connections before starting. If you see `ECONNREFUSED` or `ENOTFOUND` errors in logs, restart the affected deployments:
|
||||
|
||||
```bash
|
||||
kubectl rollout restart deployment/account deployment/transactor \
|
||||
deployment/workspace deployment/fulltext -n <namespace>
|
||||
```
|
||||
|
||||
### CockroachDB user/password issues
|
||||
|
||||
When running CockroachDB with `--insecure` (the default), authentication is disabled. The `COCKROACH_PASSWORD` env var creates the user during init but is not enforced for connections. If using the `root` user, set:
|
||||
|
||||
```bash
|
||||
--set cockroach.username=root \
|
||||
--set secrets.crDbUrl='postgres://root@cockroach:26257/defaultdb?sslmode=disable'
|
||||
```
|
||||
|
||||
### Checking pod health
|
||||
|
||||
```bash
|
||||
kubectl get pods -l app.kubernetes.io/part-of=huly -n <namespace>
|
||||
kubectl logs deployment/<service> -n <namespace> --tail=20
|
||||
```
|
||||
|
||||
## Values Reference
|
||||
|
||||
### Required
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `domain` | Your Huly domain (e.g. `huly.mysite.com`) | `huly.example` |
|
||||
|
||||
### Authentication
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `auth.google.clientId` | Google OAuth client ID | `""` |
|
||||
| `auth.google.clientSecret` | Google OAuth client secret | `""` |
|
||||
| `auth.github.clientId` | GitHub OAuth client ID | `""` |
|
||||
| `auth.github.clientSecret` | GitHub OAuth client secret | `""` |
|
||||
| `auth.oidc.clientId` | OIDC client ID | `""` |
|
||||
| `auth.oidc.clientSecret` | OIDC client secret | `""` |
|
||||
| `auth.oidc.issuer` | OIDC issuer URL | `""` |
|
||||
| `auth.disableSignup` | Prevent new user registration | `false` |
|
||||
|
||||
### Storage
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `storage.type` | `minio` (built-in) or `s3` (external) | `minio` |
|
||||
| `storage.s3.endpoint` | S3 endpoint URL | `""` |
|
||||
| `storage.s3.region` | S3 region | `""` |
|
||||
| `storage.s3.accessKey` | S3 access key | `""` |
|
||||
| `storage.s3.secretKey` | S3 secret key | `""` |
|
||||
| `storage.s3.rootBucket` | Single bucket for all workspaces (prefixed by workspace ID) | `""` |
|
||||
| `storage.s3.bucketPrefix` | Prefix for per-workspace bucket names (if rootBucket empty) | `""` |
|
||||
|
||||
### Secrets
|
||||
|
||||
All secrets are auto-generated if left empty. They persist across `helm upgrade` via Kubernetes secret lookup.
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `secrets.serverSecret` | Shared JWT signing secret | auto |
|
||||
| `secrets.storageConfig` | Full storage connection string override | auto |
|
||||
| `secrets.cockroachPassword` | CockroachDB password | auto |
|
||||
| `secrets.redpandaPassword` | Redpanda superuser password | auto |
|
||||
| `secrets.crDbUrl` | CockroachDB connection URL | auto |
|
||||
|
||||
### Ingress
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `ingress.enabled` | Enable ingress resources | `true` |
|
||||
| `ingress.className` | Ingress class | `nginx` |
|
||||
| `ingress.annotations` | Extra annotations for all ingress resources | `{}` |
|
||||
| `ingress.tls.enabled` | Enable TLS via cert-manager | `true` |
|
||||
| `ingress.tls.clusterIssuer` | cert-manager ClusterIssuer name | `letsencrypt-prod` |
|
||||
|
||||
### App Settings
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `appSettings.title` | Browser title | `Huly Self Host` |
|
||||
| `appSettings.defaultLanguage` | Default UI language | `en` |
|
||||
| `appSettings.lastNameFirst` | Display last name first | `true` |
|
||||
| `appSettings.modelEnabled` | Enabled platform models | `*` |
|
||||
| `appSettings.adminEmails` | Comma-separated admin emails | `""` |
|
||||
| `appSettings.desktopChannel` | Desktop update channel | `selfhost` |
|
||||
|
||||
### Infrastructure
|
||||
|
||||
Each infra service can be disabled to use an external instance. When disabled, provide connection details via the corresponding external/secret keys.
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `cockroach.enabled` | Deploy built-in CockroachDB | `true` |
|
||||
| `cockroach.image` | CockroachDB image | `cockroachdb/cockroach:latest-v24.2` |
|
||||
| `cockroach.storage` | Data PVC size | `10Gi` |
|
||||
| `cockroach.storageClassName` | PVC storage class (empty = cluster default) | `""` |
|
||||
| `cockroach.database` | Database name | `defaultdb` |
|
||||
| `cockroach.username` | Database user | `selfhost` |
|
||||
| `redpanda.enabled` | Deploy built-in Redpanda | `true` |
|
||||
| `redpanda.image` | Redpanda image | `docker.redpanda.com/...` |
|
||||
| `redpanda.storage` | Data PVC size | `5Gi` |
|
||||
| `redpanda.storageClassName` | PVC storage class | `""` |
|
||||
| `elastic.enabled` | Deploy built-in Elasticsearch | `true` |
|
||||
| `elastic.image` | Elasticsearch image | `elasticsearch:7.14.2` |
|
||||
| `elastic.storage` | Data PVC size | `10Gi` |
|
||||
| `elastic.storageClassName` | PVC storage class | `""` |
|
||||
| `elastic.javaOpts` | JVM heap options | `-Xms1024m -Xmx1024m` |
|
||||
| `minio.enabled` | Deploy built-in MinIO | `true` |
|
||||
| `minio.image` | MinIO image | `minio/minio` |
|
||||
| `minio.storage` | Data PVC size | `50Gi` |
|
||||
| `minio.storageClassName` | PVC storage class | `""` |
|
||||
|
||||
### External Infrastructure
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `external.redpanda` | Kafka-compatible broker address (when `redpanda.enabled=false`) | `""` |
|
||||
| `external.elastic` | Elasticsearch URL (when `elastic.enabled=false`) | `""` |
|
||||
|
||||
### Application Services
|
||||
|
||||
All app services share these overridable keys: `<svc>.replicas`, `<svc>.resources`.
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `hulyVersion` | Image tag for all Huly services | `v0.7.382` |
|
||||
| `kvs.enabled` | Deploy KVS (key-value store) service | `true` |
|
||||
|
||||
### GitHub Integration
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `githubIntegration.enabled` | Deploy GitHub integration service | `false` |
|
||||
| `githubIntegration.replicas` | Replica count | `1` |
|
||||
| `githubIntegration.botName` | Bot display name (must match GitHub App slug + `[bot]`) | `""` |
|
||||
| `githubIntegration.appId` | GitHub App ID | `""` |
|
||||
| `githubIntegration.clientId` | GitHub App Client ID | `""` |
|
||||
| `githubIntegration.clientSecret` | GitHub App Client Secret | `""` |
|
||||
| `githubIntegration.privateKey` | GitHub App Private Key (PEM) | `""` |
|
||||
| `githubIntegration.webhookSecret` | GitHub App Webhook Secret | `""` |
|
||||
|
||||
### AI Bot
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `aibot.enabled` | Deploy AI bot service | `false` |
|
||||
| `aibot.replicas` | Replica count | `1` |
|
||||
| `aibot.firstName` | Bot display first name | `Huly` |
|
||||
| `aibot.lastName` | Bot display last name | `AI` |
|
||||
| `secrets.openaiApiKey` | OpenAI API key (required when enabled) | `""` |
|
||||
| `secrets.openaiBaseUrl` | OpenAI API base URL override | `""` |
|
||||
|
||||
### Global Pod Settings
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| `global.nodeSelector` | Node selector for all pods | `{}` |
|
||||
| `global.tolerations` | Tolerations for all pods | `[]` |
|
||||
| `global.affinity` | Affinity rules for all pods | `{}` |
|
||||
|
||||
## Architecture
|
||||
|
||||
The chart deploys 13+ services (optional services marked with *):
|
||||
|
||||
| Service | Port | Description |
|
||||
|---------|------|-------------|
|
||||
| **cockroach** | 26257 | SQL database (CockroachDB) |
|
||||
| **redpanda** | 9092 | Message queue (Kafka-compatible) |
|
||||
| **elastic** | 9200 | Full-text search (Elasticsearch) |
|
||||
| **minio** | 9000 | Object storage (S3-compatible) |
|
||||
| **front** | 8080 | Web UI |
|
||||
| **account** | 3000 | Authentication & user management |
|
||||
| **transactor** | 3333 | Core transaction engine |
|
||||
| **collaborator** | 3078 | Real-time collaboration (WebSocket) |
|
||||
| **workspace** | — | Workspace lifecycle (background worker) |
|
||||
| **fulltext** | 4700 | Search indexing |
|
||||
| **rekoni** | 4004 | Content intelligence |
|
||||
| **stats** | 4900 | Metrics collection |
|
||||
| **kvs** | 8094 | Key-value store |
|
||||
| **github*** | 3500 | GitHub integration (bidirectional sync) |
|
||||
| **aibot*** | 4010 | AI assistant (requires OpenAI key) |
|
||||
| **mongodb*** | 27017 | Document database (for aibot) |
|
||||
|
||||
All services are exposed under a single domain via path-based NGINX ingress routing:
|
||||
- `/` → front
|
||||
- `/_accounts` → account
|
||||
- `/_transactor` → transactor (WebSocket)
|
||||
- `/_collaborator` → collaborator (WebSocket)
|
||||
- `/_rekoni` → rekoni
|
||||
- `/_stats` → stats
|
||||
- `/_github` → github *
|
||||
- `/_aibot` → aibot *
|
||||
|
||||
## CI / OCI Registry
|
||||
|
||||
On merge to `main`, the GitHub Actions workflow packages and pushes the chart to GHCR:
|
||||
|
||||
```bash
|
||||
helm install huly oci://ghcr.io/hcengineering/charts/huly \
|
||||
--version 0.1.0 \
|
||||
--set domain=huly.mysite.com
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
Huly has been installed!
|
||||
|
||||
{{- $proto := ternary "https" "http" (and .Values.ingress.enabled .Values.ingress.tls.enabled) }}
|
||||
|
||||
Your Huly instance will be available at:
|
||||
|
||||
{{ $proto }}://{{ .Values.domain }}
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
|
||||
Ingress is enabled with class "{{ .Values.ingress.className }}".
|
||||
{{- if .Values.ingress.tls.enabled }}
|
||||
TLS is enabled via cluster-issuer "{{ .Values.ingress.tls.clusterIssuer }}".
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
To check the rollout status:
|
||||
|
||||
kubectl get pods -l app.kubernetes.io/part-of=huly -n {{ .Release.Namespace }}
|
||||
@@ -0,0 +1,156 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "huly.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
*/}}
|
||||
{{- define "huly.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 }}
|
||||
|
||||
{{/*
|
||||
Secret resource name.
|
||||
*/}}
|
||||
{{- define "huly.secretName" -}}
|
||||
{{- printf "%s-secret" (include "huly.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
ConfigMap resource name.
|
||||
*/}}
|
||||
{{- define "huly.configName" -}}
|
||||
{{- printf "%s-config" (include "huly.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels applied to every resource.
|
||||
*/}}
|
||||
{{- define "huly.labels" -}}
|
||||
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.kubernetes.io/part-of: huly
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Global scheduling (nodeSelector, tolerations, affinity).
|
||||
*/}}
|
||||
{{- define "huly.scheduling" -}}
|
||||
{{- with .Values.global.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- with .Values.global.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- with .Values.global.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Effective MinIO enabled (disabled if storage.type == s3).
|
||||
*/}}
|
||||
{{- define "huly.minioEnabled" -}}
|
||||
{{- if and .Values.minio.enabled (eq .Values.storage.type "minio") }}true{{- else }}false{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Checksum annotations — triggers pod restart when secret/configmap changes.
|
||||
Usage: {{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
*/}}
|
||||
{{- define "huly.checksumAnnotations" -}}
|
||||
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Init container that waits for CockroachDB to accept connections.
|
||||
*/}}
|
||||
{{- define "huly.waitForCockroach" -}}
|
||||
{{- if .Values.cockroach.enabled }}
|
||||
- name: wait-cockroach
|
||||
image: busybox:1.36
|
||||
command: ['sh', '-c', 'until nc -z cockroach 26257; do echo "waiting for cockroach..."; sleep 2; done']
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Init container that waits for MongoDB to accept connections.
|
||||
*/}}
|
||||
{{- define "huly.waitForMongodb" -}}
|
||||
{{- if .Values.mongodb.enabled }}
|
||||
- name: wait-mongodb
|
||||
image: busybox:1.36
|
||||
command: ['sh', '-c', 'until nc -z mongodb 27017; do echo "waiting for mongodb..."; sleep 2; done']
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Init container that waits for Redpanda to accept connections.
|
||||
*/}}
|
||||
{{- define "huly.waitForRedpanda" -}}
|
||||
{{- if .Values.redpanda.enabled }}
|
||||
- name: wait-redpanda
|
||||
image: busybox:1.36
|
||||
command: ['sh', '-c', 'until nc -z redpanda 9092; do echo "waiting for redpanda..."; sleep 2; done']
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Backup secret resource name.
|
||||
*/}}
|
||||
{{- define "huly.backupSecretName" -}}
|
||||
{{- printf "%s-backup-secret" (include "huly.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Env var from backup Secret helper.
|
||||
Usage: {{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ENDPOINT" "key" "BACKUP_S3_ENDPOINT" "root" .) }}
|
||||
*/}}
|
||||
{{- define "huly.envBackupSecret" -}}
|
||||
- name: {{ .name }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "huly.backupSecretName" .root }}
|
||||
key: {{ .key }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Env var from Secret helper — reduces boilerplate.
|
||||
Usage: {{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) }}
|
||||
*/}}
|
||||
{{- define "huly.envSecret" -}}
|
||||
- name: {{ .name }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "huly.secretName" .root }}
|
||||
key: {{ .key }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Env var from ConfigMap helper — reduces boilerplate.
|
||||
Usage: {{- include "huly.envConfig" (dict "name" "FRONT_URL" "key" "FRONT_URL" "root" .) }}
|
||||
*/}}
|
||||
{{- define "huly.envConfig" -}}
|
||||
- name: {{ .name }}
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: {{ include "huly.configName" .root }}
|
||||
key: {{ .key }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,75 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: account
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: account
|
||||
spec:
|
||||
replicas: {{ .Values.account.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: account
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: account
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
{{- include "huly.waitForRedpanda" . | nindent 8 }}
|
||||
containers:
|
||||
- name: account
|
||||
image: {{ .Values.hulyRegistry }}/account:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3000
|
||||
env:
|
||||
- name: ACCOUNT_PORT
|
||||
value: "3000"
|
||||
- name: SERVER_PORT
|
||||
value: "3000"
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "FRONT_URL" "key" "FRONT_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "MODEL_ENABLED" "key" "MODEL_ENABLED" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "TRANSACTOR_URL" "key" "TRANSACTOR_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- if .Values.auth.disableSignup }}
|
||||
- name: DISABLE_SIGNUP
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- if .Values.auth.google.clientId }}
|
||||
{{- include "huly.envSecret" (dict "name" "GOOGLE_CLIENT_ID" "key" "GOOGLE_CLIENT_ID" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "GOOGLE_CLIENT_SECRET" "key" "GOOGLE_CLIENT_SECRET" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.github.clientId }}
|
||||
{{- include "huly.envSecret" (dict "name" "GITHUB_CLIENT_ID" "key" "GITHUB_CLIENT_ID" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "GITHUB_CLIENT_SECRET" "key" "GITHUB_CLIENT_SECRET" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.oidc.clientId }}
|
||||
{{- include "huly.envSecret" (dict "name" "OPENID_CLIENT_ID" "key" "OPENID_CLIENT_ID" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "OPENID_CLIENT_SECRET" "key" "OPENID_CLIENT_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "OPENID_ISSUER" "key" "OPENID_ISSUER" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 3000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
{{- with .Values.account.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: account
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: account
|
||||
spec:
|
||||
selector:
|
||||
app: account
|
||||
ports:
|
||||
- name: http
|
||||
port: 3000
|
||||
targetPort: 3000
|
||||
@@ -0,0 +1,82 @@
|
||||
{{- if .Values.aibot.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: aibot
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: aibot
|
||||
spec:
|
||||
replicas: {{ .Values.aibot.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: aibot
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: aibot
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
{{- include "huly.waitForMongodb" . | nindent 8 }}
|
||||
containers:
|
||||
- name: aibot
|
||||
image: {{ .Values.hulyRegistry }}/ai-bot:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4010
|
||||
env:
|
||||
- name: SERVER_PORT
|
||||
value: "4010"
|
||||
- name: FIRST_NAME
|
||||
value: {{ .Values.aibot.firstName | quote }}
|
||||
- name: LAST_NAME
|
||||
value: {{ .Values.aibot.lastName | quote }}
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "OPENAI_API_KEY" "key" "OPENAI_API_KEY" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "PASSWORD" "key" "AIBOT_PASSWORD" "root" .) | nindent 12 }}
|
||||
{{- if .Values.secrets.openaiBaseUrl }}
|
||||
{{- include "huly.envSecret" (dict "name" "OPENAI_BASE_URL" "key" "OPENAI_BASE_URL" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "MONGO_URL" "key" "MONGO_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "LOVE_ENDPOINT" "key" "LOVE_ENDPOINT" "root" .) | nindent 12 }}
|
||||
{{- with .Values.aibot.openaiModel }}
|
||||
- name: OPENAI_MODEL
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.aibot.openaiEmbeddingModel }}
|
||||
- name: OPENAI_EMBEDDING_MODEL
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.aibot.openaiTranslateModel }}
|
||||
- name: AI_OPENAI_TRANSLATE_MODEL
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.aibot.openaiSummaryModel }}
|
||||
- name: AI_OPENAI_SUMMARY_MODEL
|
||||
value: {{ . | quote }}
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4010
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 4010
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
{{- with .Values.aibot.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.aibot.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: aibot
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: aibot
|
||||
spec:
|
||||
selector:
|
||||
app: aibot
|
||||
ports:
|
||||
- name: http
|
||||
port: 4010
|
||||
targetPort: 4010
|
||||
{{- end }}
|
||||
@@ -0,0 +1,122 @@
|
||||
{{- if and .Values.backup.enabled .Values.backup.cockroachdb.enabled .Values.cockroach.enabled }}
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "huly.fullname" . }}-backup-cockroachdb
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: backup-cockroachdb
|
||||
spec:
|
||||
schedule: {{ .Values.backup.cockroachdb.schedule | default .Values.backup.schedule | quote }}
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 12 }}
|
||||
app: backup-cockroachdb
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 10 }}
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: backup
|
||||
emptyDir: {}
|
||||
initContainers:
|
||||
- name: crdb-dump
|
||||
image: cockroachdb/cockroach:latest-v24.2
|
||||
volumeMounts:
|
||||
- name: backup
|
||||
mountPath: /backup
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||
DEST="/backup/cockroachdb_${STAMP}.sql.gz"
|
||||
CRDB="cockroach sql --insecure --host=cockroach:26257 -d {{ .Values.cockroach.database }}"
|
||||
|
||||
echo "=== CockroachDB backup started at $(date -u) ==="
|
||||
|
||||
{
|
||||
# 1. Schema DDL
|
||||
echo "-- Schema dump"
|
||||
$CRDB --format=raw -e "SHOW CREATE ALL TABLES"
|
||||
|
||||
# 2. Per-table data as CSV (COPY format)
|
||||
TABLES=$($CRDB --format=csv -e "
|
||||
SELECT schema_name || '.' || table_name
|
||||
FROM [SHOW TABLES FROM {{ .Values.cockroach.database }}]
|
||||
WHERE schema_name NOT IN ('crdb_internal','pg_catalog','pg_extension','information_schema')
|
||||
ORDER BY schema_name, table_name
|
||||
" | tail -n +2)
|
||||
|
||||
for tbl in $TABLES; do
|
||||
ROW_COUNT=$($CRDB --format=csv -e "SELECT count(*) FROM ${tbl}" | tail -1)
|
||||
if [ "$ROW_COUNT" -gt 0 ] 2>/dev/null; then
|
||||
echo ""
|
||||
echo "-- Data for ${tbl} (${ROW_COUNT} rows)"
|
||||
$CRDB --format=raw -e "SELECT
|
||||
'INSERT INTO ${tbl} (' ||
|
||||
array_to_string(
|
||||
(SELECT array_agg(column_name ORDER BY ordinal_position)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = split_part('${tbl}', '.', 1)
|
||||
AND table_name = split_part('${tbl}', '.', 2)),
|
||||
', '
|
||||
) || ') VALUES' AS header" 2>/dev/null || true
|
||||
|
||||
# Export as CSV, can be loaded with IMPORT INTO
|
||||
echo "-- CSV data for IMPORT INTO ${tbl}:"
|
||||
echo "COPY ${tbl} FROM stdin WITH CSV HEADER;"
|
||||
$CRDB --format=csv -e "TABLE ${tbl}"
|
||||
echo "\\."
|
||||
fi
|
||||
done
|
||||
} | gzip > "$DEST"
|
||||
|
||||
SIZE=$(ls -lh "$DEST" | awk '{print $5}')
|
||||
echo "=== Dump complete: ${DEST} (${SIZE}) ==="
|
||||
containers:
|
||||
- name: rclone-upload
|
||||
image: {{ .Values.backup.rcloneImage }}
|
||||
volumeMounts:
|
||||
- name: backup
|
||||
mountPath: /backup
|
||||
env:
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ENDPOINT" "key" "BACKUP_S3_ENDPOINT" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_REGION" "key" "BACKUP_S3_REGION" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_BUCKET" "key" "BACKUP_S3_BUCKET" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_PATH_PREFIX" "key" "BACKUP_S3_PATH_PREFIX" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ACCESS_KEY" "key" "BACKUP_S3_ACCESS_KEY" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_SECRET_KEY" "key" "BACKUP_S3_SECRET_KEY" "root" .) | nindent 16 }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
# Configure rclone remote
|
||||
rclone config create backup s3 \
|
||||
provider=Other \
|
||||
env_auth=false \
|
||||
access_key_id="$BACKUP_S3_ACCESS_KEY" \
|
||||
secret_access_key="$BACKUP_S3_SECRET_KEY" \
|
||||
endpoint="$BACKUP_S3_ENDPOINT" \
|
||||
region="$BACKUP_S3_REGION" \
|
||||
--non-interactive
|
||||
|
||||
REMOTE_PATH="backup:${BACKUP_S3_BUCKET}/${BACKUP_S3_PATH_PREFIX}/cockroachdb/"
|
||||
|
||||
echo "Uploading to ${REMOTE_PATH}..."
|
||||
rclone copy /backup/ "$REMOTE_PATH" --include "*.sql.gz" -v
|
||||
|
||||
echo "Cleaning up backups older than {{ .Values.backup.retentionDays }} days..."
|
||||
rclone delete "$REMOTE_PATH" --min-age {{ .Values.backup.retentionDays }}d -v
|
||||
|
||||
echo "Backup complete."
|
||||
rclone ls "$REMOTE_PATH" | tail -5
|
||||
{{- end }}
|
||||
@@ -0,0 +1,107 @@
|
||||
{{- if and .Values.backup.enabled .Values.backup.files.enabled }}
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "huly.fullname" . }}-backup-files
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: backup-files
|
||||
spec:
|
||||
schedule: {{ .Values.backup.files.schedule | default .Values.backup.schedule | quote }}
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 12 }}
|
||||
app: backup-files
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 10 }}
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: rclone-sync
|
||||
image: {{ .Values.backup.rcloneImage }}
|
||||
env:
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ENDPOINT" "key" "BACKUP_S3_ENDPOINT" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_REGION" "key" "BACKUP_S3_REGION" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_BUCKET" "key" "BACKUP_S3_BUCKET" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_PATH_PREFIX" "key" "BACKUP_S3_PATH_PREFIX" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ACCESS_KEY" "key" "BACKUP_S3_ACCESS_KEY" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_SECRET_KEY" "key" "BACKUP_S3_SECRET_KEY" "root" .) | nindent 16 }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
|
||||
# Parse STORAGE_CONFIG to extract source S3 details.
|
||||
# Format: s3|https://endpoint?accessKey=X&secretKey=Y®ion=Z&rootBucket=B
|
||||
# or: minio|minio?accessKey=X&secretKey=Y
|
||||
|
||||
PROTO=$(echo "$STORAGE_CONFIG" | cut -d'|' -f1)
|
||||
REST=$(echo "$STORAGE_CONFIG" | cut -d'|' -f2)
|
||||
|
||||
if [ "$PROTO" = "minio" ]; then
|
||||
# MinIO: host is "minio", creds in query string
|
||||
SRC_ENDPOINT="http://minio:9000"
|
||||
SRC_PROVIDER="Minio"
|
||||
else
|
||||
# External S3: endpoint is the URL before '?'
|
||||
SRC_ENDPOINT=$(echo "$REST" | cut -d'?' -f1)
|
||||
SRC_PROVIDER="Other"
|
||||
fi
|
||||
|
||||
PARAMS=$(echo "$REST" | cut -d'?' -f2)
|
||||
SRC_ACCESS_KEY=$(echo "$PARAMS" | tr '&' '\n' | grep '^accessKey=' | cut -d= -f2)
|
||||
SRC_SECRET_KEY=$(echo "$PARAMS" | tr '&' '\n' | grep '^secretKey=' | cut -d= -f2)
|
||||
SRC_REGION=$(echo "$PARAMS" | tr '&' '\n' | grep '^region=' | cut -d= -f2)
|
||||
SRC_ROOT_BUCKET=$(echo "$PARAMS" | tr '&' '\n' | grep '^rootBucket=' | cut -d= -f2)
|
||||
SRC_BUCKET_PREFIX=$(echo "$PARAMS" | tr '&' '\n' | grep '^bucketPrefix=' | cut -d= -f2)
|
||||
|
||||
# Configure source remote
|
||||
rclone config create source s3 \
|
||||
provider="$SRC_PROVIDER" \
|
||||
env_auth=false \
|
||||
access_key_id="$SRC_ACCESS_KEY" \
|
||||
secret_access_key="$SRC_SECRET_KEY" \
|
||||
endpoint="$SRC_ENDPOINT" \
|
||||
region="${SRC_REGION:-us-east-1}" \
|
||||
--non-interactive
|
||||
|
||||
# Configure backup remote
|
||||
rclone config create backup s3 \
|
||||
provider=Other \
|
||||
env_auth=false \
|
||||
access_key_id="$BACKUP_S3_ACCESS_KEY" \
|
||||
secret_access_key="$BACKUP_S3_SECRET_KEY" \
|
||||
endpoint="$BACKUP_S3_ENDPOINT" \
|
||||
region="$BACKUP_S3_REGION" \
|
||||
--non-interactive
|
||||
|
||||
# Determine source path
|
||||
if [ -n "$SRC_ROOT_BUCKET" ]; then
|
||||
SRC_PATH="source:${SRC_ROOT_BUCKET}"
|
||||
elif [ -n "$SRC_BUCKET_PREFIX" ]; then
|
||||
echo "Warning: bucketPrefix mode — syncing all buckets with prefix '${SRC_BUCKET_PREFIX}'"
|
||||
SRC_PATH="source:${SRC_BUCKET_PREFIX}"
|
||||
else
|
||||
echo "Error: cannot determine source bucket from STORAGE_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEST_PATH="backup:${BACKUP_S3_BUCKET}/${BACKUP_S3_PATH_PREFIX}/files/"
|
||||
|
||||
echo "Syncing files from ${SRC_PATH} to ${DEST_PATH}..."
|
||||
rclone sync "$SRC_PATH" "$DEST_PATH" \
|
||||
--transfers 8 \
|
||||
--checkers 16 \
|
||||
--fast-list \
|
||||
-v
|
||||
|
||||
echo "File sync complete."
|
||||
{{- end }}
|
||||
@@ -0,0 +1,84 @@
|
||||
{{- if and .Values.backup.enabled .Values.backup.mongodb.enabled .Values.aibot.enabled }}
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "huly.fullname" . }}-backup-mongodb
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: backup-mongodb
|
||||
spec:
|
||||
schedule: {{ .Values.backup.mongodb.schedule | default .Values.backup.schedule | quote }}
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 12 }}
|
||||
app: backup-mongodb
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 10 }}
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: backup
|
||||
emptyDir: {}
|
||||
initContainers:
|
||||
- name: mongodump
|
||||
image: {{ .Values.mongodb.image }}
|
||||
volumeMounts:
|
||||
- name: backup
|
||||
mountPath: /backup
|
||||
env:
|
||||
{{- include "huly.envConfig" (dict "name" "MONGO_URL" "key" "MONGO_URL" "root" .) | nindent 16 }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||
DEST="/backup/mongodb_${STAMP}.gz"
|
||||
echo "Dumping MongoDB to ${DEST}..."
|
||||
mongodump --uri="$MONGO_URL" --archive="$DEST" --gzip
|
||||
ls -lh "$DEST"
|
||||
echo "mongodump complete."
|
||||
containers:
|
||||
- name: rclone-upload
|
||||
image: {{ .Values.backup.rcloneImage }}
|
||||
volumeMounts:
|
||||
- name: backup
|
||||
mountPath: /backup
|
||||
env:
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ENDPOINT" "key" "BACKUP_S3_ENDPOINT" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_REGION" "key" "BACKUP_S3_REGION" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_BUCKET" "key" "BACKUP_S3_BUCKET" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_PATH_PREFIX" "key" "BACKUP_S3_PATH_PREFIX" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_ACCESS_KEY" "key" "BACKUP_S3_ACCESS_KEY" "root" .) | nindent 16 }}
|
||||
{{- include "huly.envBackupSecret" (dict "name" "BACKUP_S3_SECRET_KEY" "key" "BACKUP_S3_SECRET_KEY" "root" .) | nindent 16 }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
rclone config create backup s3 \
|
||||
provider=Other \
|
||||
env_auth=false \
|
||||
access_key_id="$BACKUP_S3_ACCESS_KEY" \
|
||||
secret_access_key="$BACKUP_S3_SECRET_KEY" \
|
||||
endpoint="$BACKUP_S3_ENDPOINT" \
|
||||
region="$BACKUP_S3_REGION" \
|
||||
--non-interactive
|
||||
|
||||
REMOTE_PATH="backup:${BACKUP_S3_BUCKET}/${BACKUP_S3_PATH_PREFIX}/mongodb/"
|
||||
|
||||
echo "Uploading to ${REMOTE_PATH}..."
|
||||
rclone copy /backup/ "$REMOTE_PATH" --include "*.gz" -v
|
||||
|
||||
echo "Cleaning up backups older than {{ .Values.backup.retentionDays }} days..."
|
||||
rclone delete "$REMOTE_PATH" --min-age {{ .Values.backup.retentionDays }}d -v
|
||||
|
||||
echo "Backup complete."
|
||||
rclone ls "$REMOTE_PATH" | tail -5
|
||||
{{- end }}
|
||||
@@ -0,0 +1,43 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
{{- $secretName := include "huly.backupSecretName" . -}}
|
||||
{{- $existing := lookup "v1" "Secret" .Release.Namespace $secretName -}}
|
||||
{{- $hasExisting := not (empty $existing) -}}
|
||||
|
||||
{{- /* Resolve active credential set */ -}}
|
||||
{{- $accessKey := "" -}}
|
||||
{{- $secretKey := "" -}}
|
||||
{{- if eq .Values.backup.s3.activeCredential "secondary" -}}
|
||||
{{- $accessKey = .Values.backup.s3.secondaryAccessKey -}}
|
||||
{{- $secretKey = .Values.backup.s3.secondarySecretKey -}}
|
||||
{{- else -}}
|
||||
{{- $accessKey = .Values.backup.s3.accessKey -}}
|
||||
{{- $secretKey = .Values.backup.s3.secretKey -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* Fall back to existing secret if keys are empty */ -}}
|
||||
{{- if and (not $accessKey) $hasExisting (hasKey $existing.data "BACKUP_S3_ACCESS_KEY") -}}
|
||||
{{- $accessKey = index $existing.data "BACKUP_S3_ACCESS_KEY" | b64dec -}}
|
||||
{{- end -}}
|
||||
{{- if and (not $secretKey) $hasExisting (hasKey $existing.data "BACKUP_S3_SECRET_KEY") -}}
|
||||
{{- $secretKey = index $existing.data "BACKUP_S3_SECRET_KEY" | b64dec -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if or (not $accessKey) (not $secretKey) -}}
|
||||
{{- fail "backup.s3.accessKey and backup.s3.secretKey are required when backup.enabled=true" }}
|
||||
{{- end -}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ $secretName }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
data:
|
||||
BACKUP_S3_ENDPOINT: {{ .Values.backup.s3.endpoint | b64enc | quote }}
|
||||
BACKUP_S3_REGION: {{ .Values.backup.s3.region | b64enc | quote }}
|
||||
BACKUP_S3_BUCKET: {{ .Values.backup.s3.bucket | b64enc | quote }}
|
||||
BACKUP_S3_PATH_PREFIX: {{ .Values.backup.s3.pathPrefix | b64enc | quote }}
|
||||
BACKUP_S3_ACCESS_KEY: {{ $accessKey | b64enc | quote }}
|
||||
BACKUP_S3_SECRET_KEY: {{ $secretKey | b64enc | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,62 @@
|
||||
{{- if .Values.cockroach.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cockroach
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: cockroach
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cockroach
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: cockroach
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: cockroach
|
||||
image: {{ .Values.cockroach.image }}
|
||||
args:
|
||||
- start-single-node
|
||||
- --insecure
|
||||
ports:
|
||||
- name: grpc
|
||||
containerPort: 26257
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
env:
|
||||
- name: COCKROACH_DATABASE
|
||||
value: {{ .Values.cockroach.database }}
|
||||
- name: COCKROACH_USER
|
||||
value: {{ .Values.cockroach.username }}
|
||||
{{- include "huly.envSecret" (dict "name" "COCKROACH_PASSWORD" "key" "COCKROACH_PASSWORD" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ['sh', '-c', 'curl -sf http://localhost:8080/health?ready=1']
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /cockroach/cockroach-data
|
||||
{{- with .Values.cockroach.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: cockroach-data
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.cockroach.enabled }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: cockroach-data
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
{{- if .Values.cockroach.storageClassName }}
|
||||
storageClassName: {{ .Values.cockroach.storageClassName }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.cockroach.storage }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,20 @@
|
||||
{{- if .Values.cockroach.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cockroach
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: cockroach
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: cockroach
|
||||
ports:
|
||||
- name: grpc
|
||||
port: 26257
|
||||
targetPort: 26257
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
{{- end }}
|
||||
@@ -0,0 +1,48 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: collaborator
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: collaborator
|
||||
spec:
|
||||
replicas: {{ .Values.collaborator.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: collaborator
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: collaborator
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: collaborator
|
||||
image: {{ .Values.hulyRegistry }}/collaborator:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3078
|
||||
env:
|
||||
- name: COLLABORATOR_PORT
|
||||
value: "3078"
|
||||
{{- include "huly.envSecret" (dict "name" "SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3078
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 3078
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
{{- with .Values.collaborator.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: collaborator
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: collaborator
|
||||
spec:
|
||||
selector:
|
||||
app: collaborator
|
||||
ports:
|
||||
- name: http
|
||||
port: 3078
|
||||
targetPort: 3078
|
||||
@@ -0,0 +1,60 @@
|
||||
{{- $proto := ternary "https" "http" (and .Values.ingress.enabled .Values.ingress.tls.enabled) -}}
|
||||
{{- $wsProto := ternary "wss" "ws" (and .Values.ingress.enabled .Values.ingress.tls.enabled) -}}
|
||||
|
||||
{{- /* Resolve infra endpoints: built-in pod name or external URL */ -}}
|
||||
{{- $elasticUrl := ternary "http://elastic:9200" .Values.external.elastic .Values.elastic.enabled -}}
|
||||
{{- $queueConfig := ternary "redpanda:9092" .Values.external.redpanda .Values.redpanda.enabled -}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "huly.configName" . }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
data:
|
||||
# External URLs (via ingress)
|
||||
ACCOUNTS_URL: "{{ $proto }}://{{ .Values.domain }}/_accounts"
|
||||
COLLABORATOR_URL: "{{ $wsProto }}://{{ .Values.domain }}/_collaborator"
|
||||
FRONT_URL: "{{ $proto }}://{{ .Values.domain }}"
|
||||
REKONI_URL: "{{ $proto }}://{{ .Values.domain }}/_rekoni"
|
||||
STATS_URL: "{{ $proto }}://{{ .Values.domain }}/_stats"
|
||||
TRANSACTOR_URL: "ws://transactor:3333;{{ $wsProto }}://{{ .Values.domain }}/_transactor"
|
||||
|
||||
# Internal URLs (pod-to-pod)
|
||||
ELASTIC_URL: {{ $elasticUrl | quote }}
|
||||
ELASTIC_INDEX_NAME: "huly_storage_index"
|
||||
FULLTEXT_URL: "http://fulltext:4700"
|
||||
ACCOUNTS_URL_INTERNAL: "http://account:3000"
|
||||
REKONI_URL_INTERNAL: "http://rekoni:4004"
|
||||
STATS_URL_INTERNAL: "http://stats:4900"
|
||||
QUEUE_CONFIG: {{ $queueConfig | quote }}
|
||||
|
||||
# App settings
|
||||
MODEL_ENABLED: {{ .Values.appSettings.modelEnabled | quote }}
|
||||
LAST_NAME_FIRST: {{ .Values.appSettings.lastNameFirst | quote }}
|
||||
TITLE: {{ .Values.appSettings.title | quote }}
|
||||
DEFAULT_LANGUAGE: {{ .Values.appSettings.defaultLanguage | quote }}
|
||||
UPLOAD_URL: "/files"
|
||||
DESKTOP_UPDATES_CHANNEL: {{ .Values.appSettings.desktopChannel | quote }}
|
||||
{{- if .Values.appSettings.adminEmails }}
|
||||
ADMIN_EMAILS: {{ .Values.appSettings.adminEmails | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.disableSignup }}
|
||||
DISABLE_SIGNUP: "true"
|
||||
{{- end }}
|
||||
|
||||
# Optional integration URLs (required by front even if unused)
|
||||
GMAIL_URL: "{{ $proto }}://{{ .Values.domain }}/_gmail"
|
||||
TELEGRAM_URL: "{{ $proto }}://{{ .Values.domain }}/_telegram"
|
||||
CALENDAR_URL: "{{ $proto }}://{{ .Values.domain }}/_calendar"
|
||||
LOVE_ENDPOINT: "{{ $proto }}://{{ .Values.domain }}/_love"
|
||||
|
||||
{{- if .Values.githubIntegration.enabled }}
|
||||
GITHUB_URL: "{{ $proto }}://{{ .Values.domain }}/_github"
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.aibot.enabled }}
|
||||
AI_URL: "{{ $proto }}://{{ .Values.domain }}/_aibot"
|
||||
AI_BOT_URL: "http://aibot:4010"
|
||||
MONGO_URL: {{ ternary "mongodb://mongodb:27017" .Values.external.mongodb .Values.mongodb.enabled | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,82 @@
|
||||
{{- if .Values.elastic.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: elastic
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: elastic
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: elastic
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: elastic
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: elastic
|
||||
image: {{ .Values.elastic.image }}
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
bin/elasticsearch-plugin install --batch ingest-attachment;
|
||||
/usr/local/bin/docker-entrypoint.sh elasticsearch
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 9200
|
||||
env:
|
||||
- name: BITNAMI_DEBUG
|
||||
value: "true"
|
||||
- name: ELASTICSEARCH_PORT_NUMBER
|
||||
value: "9200"
|
||||
- name: ES_JAVA_OPTS
|
||||
value: {{ .Values.elastic.javaOpts | quote }}
|
||||
- name: discovery.type
|
||||
value: single-node
|
||||
- name: http.cors.enabled
|
||||
value: "true"
|
||||
- name: http.cors.allow-origin
|
||||
value: "http://localhost:8082"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
curl -sf http://localhost:9200/_cluster/health | grep -vq '"status":"red"'
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 20
|
||||
failureThreshold: 10
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
curl -sf http://localhost:9200/_cluster/health
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /usr/share/elasticsearch/data
|
||||
{{- with .Values.elastic.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: elastic-data
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.elastic.enabled }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: elastic-data
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
{{- if .Values.elastic.storageClassName }}
|
||||
storageClassName: {{ .Values.elastic.storageClassName }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.elastic.storage }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.elastic.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: elastic
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: elastic
|
||||
spec:
|
||||
selector:
|
||||
app: elastic
|
||||
ports:
|
||||
- name: http
|
||||
port: 9200
|
||||
targetPort: 9200
|
||||
{{- end }}
|
||||
@@ -0,0 +1,73 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: front
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: front
|
||||
spec:
|
||||
replicas: {{ .Values.front.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: front
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: front
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: front
|
||||
image: {{ .Values.hulyRegistry }}/front:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
env:
|
||||
- name: SERVER_PORT
|
||||
value: "8080"
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL_INTERNAL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "COLLABORATOR_URL" "key" "COLLABORATOR_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "REKONI_URL" "key" "REKONI_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ELASTIC_URL" "key" "ELASTIC_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "DEFAULT_LANGUAGE" "key" "DEFAULT_LANGUAGE" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "TITLE" "key" "TITLE" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "UPLOAD_URL" "key" "UPLOAD_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "LAST_NAME_FIRST" "key" "LAST_NAME_FIRST" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "DESKTOP_UPDATES_CHANNEL" "key" "DESKTOP_UPDATES_CHANNEL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "CALENDAR_URL" "key" "CALENDAR_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "GMAIL_URL" "key" "GMAIL_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "TELEGRAM_URL" "key" "TELEGRAM_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "LOVE_ENDPOINT" "key" "LOVE_ENDPOINT" "root" .) | nindent 12 }}
|
||||
{{- if .Values.githubIntegration.enabled }}
|
||||
{{- include "huly.envConfig" (dict "name" "GITHUB_URL" "key" "GITHUB_URL" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.aibot.enabled }}
|
||||
{{- include "huly.envConfig" (dict "name" "AI_URL" "key" "AI_URL" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.disableSignup }}
|
||||
- name: DISABLE_SIGNUP
|
||||
value: "true"
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
{{- with .Values.front.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: front
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: front
|
||||
spec:
|
||||
selector:
|
||||
app: front
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
@@ -0,0 +1,54 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: fulltext
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: fulltext
|
||||
spec:
|
||||
replicas: {{ .Values.fulltext.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: fulltext
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: fulltext
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
{{- include "huly.waitForRedpanda" . | nindent 8 }}
|
||||
containers:
|
||||
- name: fulltext
|
||||
image: {{ .Values.hulyRegistry }}/fulltext:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4700
|
||||
env:
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "FULLTEXT_DB_URL" "key" "ELASTIC_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ELASTIC_INDEX_NAME" "key" "ELASTIC_INDEX_NAME" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "REKONI_URL" "key" "REKONI_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4700
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 4700
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
{{- with .Values.fulltext.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: fulltext
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: fulltext
|
||||
spec:
|
||||
selector:
|
||||
app: fulltext
|
||||
ports:
|
||||
- name: http
|
||||
port: 4700
|
||||
targetPort: 4700
|
||||
@@ -0,0 +1,61 @@
|
||||
{{- if .Values.githubIntegration.enabled -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: github
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: github
|
||||
spec:
|
||||
replicas: {{ .Values.githubIntegration.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: github
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: github
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: github
|
||||
image: {{ .Values.hulyRegistry }}/github:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3500
|
||||
env:
|
||||
- name: PORT
|
||||
value: "3500"
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "APP_ID" "key" "GITHUB_APP_ID" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "CLIENT_ID" "key" "GITHUB_APP_CLIENT_ID" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "CLIENT_SECRET" "key" "GITHUB_APP_CLIENT_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "PRIVATE_KEY" "key" "GITHUB_APP_PRIVATE_KEY" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "WEBHOOK_SECRET" "key" "GITHUB_APP_WEBHOOK_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "FRONT_URL" "key" "FRONT_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "COLLABORATOR_URL" "key" "COLLABORATOR_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
- name: BOT_NAME
|
||||
value: {{ .Values.githubIntegration.botName | quote }}
|
||||
- name: SERVICE_ID
|
||||
value: "github-service"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3500
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 3500
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
{{- with .Values.githubIntegration.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.githubIntegration.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: github
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: github
|
||||
spec:
|
||||
selector:
|
||||
app: github
|
||||
ports:
|
||||
- name: http
|
||||
port: 3500
|
||||
targetPort: 3500
|
||||
{{- end }}
|
||||
@@ -0,0 +1,98 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullname := include "huly.fullname" . -}}
|
||||
{{- $domain := .Values.domain -}}
|
||||
{{- $tlsEnabled := .Values.ingress.tls.enabled -}}
|
||||
{{- $clusterIssuer := .Values.ingress.tls.clusterIssuer -}}
|
||||
{{- $className := .Values.ingress.className -}}
|
||||
{{- $extraAnnotations := .Values.ingress.annotations -}}
|
||||
|
||||
{{- /* Backend services exposed via path-based routing */ -}}
|
||||
{{- $backends := list
|
||||
(dict "name" "accounts" "svc" "account" "port" 3000 "ws" false)
|
||||
(dict "name" "transactor" "svc" "transactor" "port" 3333 "ws" true)
|
||||
(dict "name" "collaborator" "svc" "collaborator" "port" 3078 "ws" true)
|
||||
(dict "name" "rekoni" "svc" "rekoni" "port" 4004 "ws" false)
|
||||
(dict "name" "stats" "svc" "stats" "port" 4900 "ws" false)
|
||||
-}}
|
||||
{{- if .Values.aibot.enabled }}
|
||||
{{- $backends = append $backends (dict "name" "aibot" "svc" "aibot" "port" 4010 "ws" true) }}
|
||||
{{- end -}}
|
||||
{{- if .Values.githubIntegration.enabled }}
|
||||
{{- $backends = append $backends (dict "name" "github" "svc" "github" "port" 3500 "ws" false) }}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $backends }}
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullname }}-{{ .name }}
|
||||
labels:
|
||||
{{- include "huly.labels" $ | nindent 4 }}
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /$2
|
||||
{{- if .ws }}
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
||||
{{- end }}
|
||||
{{- with $extraAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ $className }}
|
||||
{{- if $tlsEnabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ $domain }}
|
||||
secretName: {{ $fullname }}-tls
|
||||
{{- end }}
|
||||
rules:
|
||||
- host: {{ $domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /_{{ .name }}(/|$)(.*)
|
||||
pathType: ImplementationSpecific
|
||||
backend:
|
||||
service:
|
||||
name: {{ .svc }}
|
||||
port:
|
||||
number: {{ .port }}
|
||||
{{- end }}
|
||||
|
||||
---
|
||||
# Front catch-all — also owns the TLS certificate
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullname }}-front
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if $tlsEnabled }}
|
||||
cert-manager.io/cluster-issuer: {{ $clusterIssuer }}
|
||||
{{- end }}
|
||||
{{- with $extraAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ $className }}
|
||||
{{- if $tlsEnabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ $domain }}
|
||||
secretName: {{ $fullname }}-tls
|
||||
{{- end }}
|
||||
rules:
|
||||
- host: {{ $domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: front
|
||||
port:
|
||||
number: 8080
|
||||
{{- end }}
|
||||
@@ -0,0 +1,49 @@
|
||||
{{- if .Values.kvs.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kvs
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: kvs
|
||||
spec:
|
||||
replicas: {{ .Values.kvs.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kvs
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: kvs
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
containers:
|
||||
- name: kvs
|
||||
image: {{ .Values.hulyRegistry }}/hulykvs:{{ .Values.kvs.version | default .Values.hulyVersion }}
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8094
|
||||
env:
|
||||
{{- include "huly.envSecret" (dict "name" "HULY_DB_CONNECTION" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "HULY_TOKEN_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8094
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8094
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
{{- with .Values.kvs.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.kvs.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kvs
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: kvs
|
||||
spec:
|
||||
selector:
|
||||
app: kvs
|
||||
ports:
|
||||
- name: http
|
||||
port: 8094
|
||||
targetPort: 8094
|
||||
{{- end }}
|
||||
@@ -0,0 +1,61 @@
|
||||
{{- if eq (include "huly.minioEnabled" .) "true" }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: minio
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: minio
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: minio
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: minio
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: minio
|
||||
image: {{ .Values.minio.image }}
|
||||
args:
|
||||
- server
|
||||
- /data
|
||||
- --address
|
||||
- ":9000"
|
||||
- --console-address
|
||||
- ":9001"
|
||||
ports:
|
||||
- name: api
|
||||
containerPort: 9000
|
||||
- name: console
|
||||
containerPort: 9001
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /minio/health/ready
|
||||
port: 9000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /minio/health/live
|
||||
port: 9000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 20
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
{{- with .Values.minio.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-data
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if eq (include "huly.minioEnabled" .) "true" }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-data
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
{{- if .Values.minio.storageClassName }}
|
||||
storageClassName: {{ .Values.minio.storageClassName }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.minio.storage }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- if eq (include "huly.minioEnabled" .) "true" }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: minio
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: minio
|
||||
spec:
|
||||
selector:
|
||||
app: minio
|
||||
ports:
|
||||
- name: api
|
||||
port: 9000
|
||||
targetPort: 9000
|
||||
- name: console
|
||||
port: 9001
|
||||
targetPort: 9001
|
||||
{{- end }}
|
||||
@@ -0,0 +1,50 @@
|
||||
{{- if and .Values.aibot.enabled .Values.mongodb.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mongodb
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: mongodb
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mongodb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: mongodb
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: mongodb
|
||||
image: {{ .Values.mongodb.image }}
|
||||
ports:
|
||||
- name: mongo
|
||||
containerPort: 27017
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 27017
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 27017
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data/db
|
||||
{{- with .Values.mongodb.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: mongodb-data
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if and .Values.aibot.enabled .Values.mongodb.enabled }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mongodb-data
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
{{- if .Values.mongodb.storageClassName }}
|
||||
storageClassName: {{ .Values.mongodb.storageClassName }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.mongodb.storage }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if and .Values.aibot.enabled .Values.mongodb.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mongodb
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: mongodb
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: mongodb
|
||||
ports:
|
||||
- name: mongo
|
||||
port: 27017
|
||||
targetPort: 27017
|
||||
{{- end }}
|
||||
@@ -0,0 +1,87 @@
|
||||
{{- if .Values.redpanda.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: redpanda
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: redpanda
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redpanda
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: redpanda
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
- name: set-datadir-ownership
|
||||
image: busybox:1.36
|
||||
command: ["sh", "-c", "chown -R 101:101 /var/lib/redpanda/data"]
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/redpanda/data
|
||||
containers:
|
||||
- name: redpanda
|
||||
image: {{ .Values.redpanda.image }}
|
||||
args:
|
||||
- redpanda
|
||||
- start
|
||||
- --kafka-addr
|
||||
- internal://0.0.0.0:9092,external://0.0.0.0:19092
|
||||
- --advertise-kafka-addr
|
||||
- internal://redpanda:9092,external://localhost:19092
|
||||
- --pandaproxy-addr
|
||||
- internal://0.0.0.0:8082,external://0.0.0.0:18082
|
||||
- --advertise-pandaproxy-addr
|
||||
- internal://redpanda:8082,external://localhost:18082
|
||||
- --schema-registry-addr
|
||||
- internal://0.0.0.0:8081,external://0.0.0.0:18081
|
||||
- --rpc-addr
|
||||
- 0.0.0.0:33145
|
||||
- --advertise-rpc-addr
|
||||
- redpanda:33145
|
||||
- --mode
|
||||
- dev-container
|
||||
- --smp
|
||||
- "1"
|
||||
- --default-log-level=info
|
||||
ports:
|
||||
- name: kafka
|
||||
containerPort: 9092
|
||||
- name: rpc
|
||||
containerPort: 33145
|
||||
env:
|
||||
- name: REDPANDA_SUPERUSER_USERNAME
|
||||
value: superuser
|
||||
- name: REDPANDA_SUPERUSER_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "huly.secretName" . }}
|
||||
key: REDPANDA_SUPERUSER_PASSWORD
|
||||
- name: NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "rpk cluster info"]
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
failureThreshold: 5
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/redpanda/data
|
||||
{{- with .Values.redpanda.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: redpanda-data
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.redpanda.enabled }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: redpanda-data
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
{{- if .Values.redpanda.storageClassName }}
|
||||
storageClassName: {{ .Values.redpanda.storageClassName }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.redpanda.storage }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- if .Values.redpanda.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redpanda
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: redpanda
|
||||
spec:
|
||||
selector:
|
||||
app: redpanda
|
||||
ports:
|
||||
- name: kafka
|
||||
port: 9092
|
||||
targetPort: 9092
|
||||
- name: rpc
|
||||
port: 33145
|
||||
targetPort: 33145
|
||||
{{- end }}
|
||||
@@ -0,0 +1,43 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: rekoni
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: rekoni
|
||||
spec:
|
||||
replicas: {{ .Values.rekoni.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: rekoni
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: rekoni
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: rekoni
|
||||
image: {{ .Values.hulyRegistry }}/rekoni-service:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4004
|
||||
env:
|
||||
{{- include "huly.envSecret" (dict "name" "SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4004
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 4004
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
{{- with .Values.rekoni.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: rekoni
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: rekoni
|
||||
spec:
|
||||
selector:
|
||||
app: rekoni
|
||||
ports:
|
||||
- name: http
|
||||
port: 4004
|
||||
targetPort: 4004
|
||||
@@ -0,0 +1,124 @@
|
||||
{{- $secretName := include "huly.secretName" . -}}
|
||||
{{- $existing := lookup "v1" "Secret" .Release.Namespace $secretName -}}
|
||||
{{- $hasExisting := not (empty $existing) -}}
|
||||
|
||||
{{- /* SERVER_SECRET */ -}}
|
||||
{{- $serverSecret := "" -}}
|
||||
{{- if .Values.secrets.serverSecret -}}
|
||||
{{- $serverSecret = .Values.secrets.serverSecret -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "SERVER_SECRET") -}}
|
||||
{{- $serverSecret = index $existing.data "SERVER_SECRET" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $serverSecret = randAlphaNum 32 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* COCKROACH_PASSWORD */ -}}
|
||||
{{- $cockroachPwd := "" -}}
|
||||
{{- if .Values.secrets.cockroachPassword -}}
|
||||
{{- $cockroachPwd = .Values.secrets.cockroachPassword -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "COCKROACH_PASSWORD") -}}
|
||||
{{- $cockroachPwd = index $existing.data "COCKROACH_PASSWORD" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $cockroachPwd = randAlphaNum 24 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* REDPANDA_SUPERUSER_PASSWORD */ -}}
|
||||
{{- $redpandaPwd := "" -}}
|
||||
{{- if .Values.secrets.redpandaPassword -}}
|
||||
{{- $redpandaPwd = .Values.secrets.redpandaPassword -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "REDPANDA_SUPERUSER_PASSWORD") -}}
|
||||
{{- $redpandaPwd = index $existing.data "REDPANDA_SUPERUSER_PASSWORD" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $redpandaPwd = randAlphaNum 24 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* STORAGE_CONFIG — explicit values > storage.type config > existing secret > auto-generate */ -}}
|
||||
{{- $storageConfig := "" -}}
|
||||
{{- if .Values.secrets.storageConfig -}}
|
||||
{{- $storageConfig = .Values.secrets.storageConfig -}}
|
||||
{{- else if eq .Values.storage.type "s3" -}}
|
||||
{{- $s3Params := printf "accessKey=%s&secretKey=%s®ion=%s" .Values.storage.s3.accessKey .Values.storage.s3.secretKey .Values.storage.s3.region -}}
|
||||
{{- if .Values.storage.s3.rootBucket -}}
|
||||
{{- $s3Params = printf "%s&rootBucket=%s" $s3Params .Values.storage.s3.rootBucket -}}
|
||||
{{- end -}}
|
||||
{{- if .Values.storage.s3.bucketPrefix -}}
|
||||
{{- $s3Params = printf "%s&bucketPrefix=%s" $s3Params .Values.storage.s3.bucketPrefix -}}
|
||||
{{- end -}}
|
||||
{{- $storageConfig = printf "s3|%s?%s" .Values.storage.s3.endpoint $s3Params -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "STORAGE_CONFIG") -}}
|
||||
{{- $storageConfig = index $existing.data "STORAGE_CONFIG" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $storageConfig = printf "minio|minio?accessKey=%s&secretKey=%s" (randAlphaNum 20) (randAlphaNum 40) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* CR_DB_URL */ -}}
|
||||
{{- $crDbUrl := "" -}}
|
||||
{{- if .Values.secrets.crDbUrl -}}
|
||||
{{- $crDbUrl = .Values.secrets.crDbUrl -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "CR_DB_URL") -}}
|
||||
{{- $crDbUrl = index $existing.data "CR_DB_URL" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $crDbUrl = printf "postgres://%s:%s@cockroach:26257/%s" .Values.cockroach.username $cockroachPwd .Values.cockroach.database -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* AIBOT_PASSWORD */ -}}
|
||||
{{- $aibotPwd := "" -}}
|
||||
{{- if .Values.secrets.aibotPassword -}}
|
||||
{{- $aibotPwd = .Values.secrets.aibotPassword -}}
|
||||
{{- else if and $hasExisting (hasKey $existing.data "AIBOT_PASSWORD") -}}
|
||||
{{- $aibotPwd = index $existing.data "AIBOT_PASSWORD" | b64dec -}}
|
||||
{{- else -}}
|
||||
{{- $aibotPwd = randAlphaNum 24 -}}
|
||||
{{- end -}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ $secretName }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
data:
|
||||
SERVER_SECRET: {{ $serverSecret | b64enc | quote }}
|
||||
COCKROACH_PASSWORD: {{ $cockroachPwd | b64enc | quote }}
|
||||
REDPANDA_SUPERUSER_PASSWORD: {{ $redpandaPwd | b64enc | quote }}
|
||||
STORAGE_CONFIG: {{ $storageConfig | b64enc | quote }}
|
||||
CR_DB_URL: {{ $crDbUrl | b64enc | quote }}
|
||||
AIBOT_PASSWORD: {{ $aibotPwd | b64enc | quote }}
|
||||
{{- if .Values.aibot.enabled }}
|
||||
{{- if not .Values.secrets.openaiApiKey }}
|
||||
{{- fail "secrets.openaiApiKey is required when aibot.enabled=true" }}
|
||||
{{- end }}
|
||||
OPENAI_API_KEY: {{ .Values.secrets.openaiApiKey | b64enc | quote }}
|
||||
{{- with .Values.secrets.openaiBaseUrl }}
|
||||
OPENAI_BASE_URL: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.google.clientId }}
|
||||
GOOGLE_CLIENT_ID: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.google.clientSecret }}
|
||||
GOOGLE_CLIENT_SECRET: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.github.clientId }}
|
||||
GITHUB_CLIENT_ID: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.github.clientSecret }}
|
||||
GITHUB_CLIENT_SECRET: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.oidc.clientId }}
|
||||
OPENID_CLIENT_ID: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.oidc.clientSecret }}
|
||||
OPENID_CLIENT_SECRET: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.auth.oidc.issuer }}
|
||||
OPENID_ISSUER: {{ . | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.githubIntegration.enabled }}
|
||||
GITHUB_APP_ID: {{ .Values.githubIntegration.appId | toString | b64enc | quote }}
|
||||
GITHUB_APP_CLIENT_ID: {{ .Values.githubIntegration.clientId | b64enc | quote }}
|
||||
GITHUB_APP_CLIENT_SECRET: {{ .Values.githubIntegration.clientSecret | b64enc | quote }}
|
||||
GITHUB_APP_PRIVATE_KEY: {{ .Values.githubIntegration.privateKey | b64enc | quote }}
|
||||
GITHUB_APP_WEBHOOK_SECRET: {{ .Values.githubIntegration.webhookSecret | b64enc | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,45 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: stats
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: stats
|
||||
spec:
|
||||
replicas: {{ .Values.stats.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: stats
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: stats
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
containers:
|
||||
- name: stats
|
||||
image: {{ .Values.hulyRegistry }}/stats:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4900
|
||||
env:
|
||||
- name: PORT
|
||||
value: "4900"
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4900
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 4900
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
{{- with .Values.stats.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: stats
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: stats
|
||||
spec:
|
||||
selector:
|
||||
app: stats
|
||||
ports:
|
||||
- name: http
|
||||
port: 4900
|
||||
targetPort: 4900
|
||||
@@ -0,0 +1,61 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: transactor
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: transactor
|
||||
spec:
|
||||
replicas: {{ .Values.transactor.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: transactor
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: transactor
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
{{- include "huly.waitForRedpanda" . | nindent 8 }}
|
||||
containers:
|
||||
- name: transactor
|
||||
image: {{ .Values.hulyRegistry }}/transactor:{{ .Values.hulyVersion }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3333
|
||||
env:
|
||||
- name: SERVER_PORT
|
||||
value: "3333"
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "FRONT_URL" "key" "FRONT_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "FULLTEXT_URL" "key" "FULLTEXT_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "LAST_NAME_FIRST" "key" "LAST_NAME_FIRST" "root" .) | nindent 12 }}
|
||||
{{- if .Values.aibot.enabled }}
|
||||
{{- include "huly.envConfig" (dict "name" "AI_BOT_URL" "key" "AI_BOT_URL" "root" .) | nindent 12 }}
|
||||
{{- end }}
|
||||
- name: SERVER_CURSOR_MAXTIMEMS
|
||||
value: "30000"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3333
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 3333
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
{{- with .Values.transactor.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: transactor
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: transactor
|
||||
spec:
|
||||
selector:
|
||||
app: transactor
|
||||
ports:
|
||||
- name: http
|
||||
port: 3333
|
||||
targetPort: 3333
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: workspace
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 4 }}
|
||||
app: workspace
|
||||
spec:
|
||||
replicas: {{ .Values.workspace.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: workspace
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "huly.checksumAnnotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "huly.labels" . | nindent 8 }}
|
||||
app: workspace
|
||||
spec:
|
||||
{{- include "huly.scheduling" . | nindent 6 }}
|
||||
initContainers:
|
||||
{{- include "huly.waitForCockroach" . | nindent 8 }}
|
||||
{{- include "huly.waitForRedpanda" . | nindent 8 }}
|
||||
containers:
|
||||
- name: workspace
|
||||
image: {{ .Values.hulyRegistry }}/workspace:{{ .Values.hulyVersion }}
|
||||
env:
|
||||
{{- include "huly.envSecret" (dict "name" "SERVER_SECRET" "key" "SERVER_SECRET" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "ACCOUNTS_DB_URL" "key" "CR_DB_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envSecret" (dict "name" "STORAGE_CONFIG" "key" "STORAGE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "ACCOUNTS_URL" "key" "ACCOUNTS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "STATS_URL" "key" "STATS_URL_INTERNAL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "TRANSACTOR_URL" "key" "TRANSACTOR_URL" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "MODEL_ENABLED" "key" "MODEL_ENABLED" "root" .) | nindent 12 }}
|
||||
{{- include "huly.envConfig" (dict "name" "QUEUE_CONFIG" "key" "QUEUE_CONFIG" "root" .) | nindent 12 }}
|
||||
{{- with .Values.workspace.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,292 @@
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# REQUIRED — set this to your domain
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
domain: huly.example
|
||||
|
||||
# Override the chart name / full release name
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Global image tag for all Huly services
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
hulyVersion: v0.7.382
|
||||
|
||||
# Docker registry prefix for Huly service images.
|
||||
# Default "hardcoreeng" pulls from Docker Hub (hardcoreeng/front, etc.).
|
||||
# Override to use a private registry, e.g. europe-west3-docker.pkg.dev/kendall-ledo/docker/huly
|
||||
hulyRegistry: hardcoreeng
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Secrets — leave empty to auto-generate (persists across upgrades)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
secrets:
|
||||
# Shared JWT signing secret (auto-generated if empty)
|
||||
serverSecret: ""
|
||||
# Full storage config string override.
|
||||
# When empty, auto-derived from storage.type + storage.s3.* (or random MinIO creds).
|
||||
# Format: s3|https://s3.example.com?accessKey=X&secretKey=Y®ion=us-east-1&rootBucket=data
|
||||
# or: minio|minio?accessKey=<key>&secretKey=<secret>
|
||||
storageConfig: ""
|
||||
# CockroachDB password (auto-generated if empty)
|
||||
cockroachPassword: ""
|
||||
# Redpanda superuser password (auto-generated if empty)
|
||||
redpandaPassword: ""
|
||||
# CockroachDB connection URL (auto-derived from cockroachPassword if empty)
|
||||
# Set this when using an external database (cockroach.enabled=false).
|
||||
# Format: postgres://<user>:<pass>@<host>:26257/<db>
|
||||
crDbUrl: ""
|
||||
# OpenAI API key (required when aibot.enabled=true)
|
||||
openaiApiKey: ""
|
||||
# OpenAI base URL override (optional, e.g. for Azure OpenAI or proxies)
|
||||
openaiBaseUrl: ""
|
||||
# AI bot password (auto-generated if empty)
|
||||
aibotPassword: ""
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Authentication providers (set on the account service)
|
||||
# At least one provider should be configured for user login.
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
auth:
|
||||
# Google OAuth 2.0
|
||||
google:
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
# GitHub OAuth
|
||||
github:
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
# OpenID Connect (generic OIDC provider)
|
||||
oidc:
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
issuer: "" # e.g. https://accounts.google.com
|
||||
# Set to true to prevent new user registration
|
||||
disableSignup: false
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Storage backend — built-in MinIO or external S3
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
storage:
|
||||
# "minio" = use built-in MinIO (default)
|
||||
# "s3" = use external S3-compatible storage (disables built-in MinIO)
|
||||
type: minio
|
||||
s3:
|
||||
endpoint: "" # e.g. https://s3.amazonaws.com
|
||||
region: "" # e.g. us-east-1
|
||||
accessKey: ""
|
||||
secretKey: ""
|
||||
# rootBucket: store all workspaces as prefixes inside a single bucket
|
||||
rootBucket: "" # e.g. huly-data
|
||||
# bucketPrefix: prefix prepended to per-workspace bucket names (only used if rootBucket is empty)
|
||||
bucketPrefix: "" # e.g. huly-
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Ingress
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
# Extra annotations merged into every ingress resource
|
||||
annotations: {}
|
||||
tls:
|
||||
enabled: true
|
||||
clusterIssuer: letsencrypt-prod
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# App settings (ConfigMap)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
appSettings:
|
||||
modelEnabled: "*"
|
||||
lastNameFirst: "true"
|
||||
title: "Huly Self Host"
|
||||
defaultLanguage: "en"
|
||||
# Comma-separated list of admin email addresses
|
||||
adminEmails: ""
|
||||
# Desktop update channel
|
||||
desktopChannel: "selfhost"
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Global pod settings (applied to all services)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
global:
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Infrastructure — set enabled: false to use external services
|
||||
#
|
||||
# When disabled, provide connection details via:
|
||||
# cockroach: secrets.crDbUrl
|
||||
# redpanda: external.redpanda
|
||||
# elastic: external.elastic
|
||||
# minio: storage.type=s3 + storage.s3.*
|
||||
# mongodb: external.mongodb (only when aibot.enabled=true)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
cockroach:
|
||||
enabled: true
|
||||
image: cockroachdb/cockroach:latest-v24.2
|
||||
database: defaultdb
|
||||
username: selfhost
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
resources: {}
|
||||
|
||||
redpanda:
|
||||
enabled: true
|
||||
image: docker.redpanda.com/redpandadata/redpanda:v24.3.6
|
||||
storage: 5Gi
|
||||
storageClassName: ""
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
elastic:
|
||||
enabled: true
|
||||
image: elasticsearch:7.14.2
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
javaOpts: "-Xms1024m -Xmx1024m"
|
||||
resources: {}
|
||||
|
||||
minio:
|
||||
# Automatically disabled when storage.type=s3
|
||||
enabled: true
|
||||
image: minio/minio
|
||||
storage: 50Gi
|
||||
storageClassName: ""
|
||||
resources: {}
|
||||
|
||||
mongodb:
|
||||
# Built-in MongoDB — only deployed when aibot.enabled=true
|
||||
enabled: true
|
||||
image: mongo:7
|
||||
storage: 5Gi
|
||||
storageClassName: ""
|
||||
resources: {}
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# External infrastructure endpoints
|
||||
# Used when the corresponding built-in service is disabled.
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
external:
|
||||
# Used when redpanda.enabled=false
|
||||
redpanda: "" # e.g. kafka.example.com:9092
|
||||
# Used when elastic.enabled=false
|
||||
elastic: "" # e.g. https://elasticsearch.example.com:9200
|
||||
# Used when mongodb.enabled=false (requires aibot.enabled=true)
|
||||
mongodb: "" # e.g. mongodb://user:pass@host:27017
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Application services
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
front:
|
||||
replicas: 1
|
||||
resources: {}
|
||||
|
||||
account:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
transactor:
|
||||
replicas: 1
|
||||
resources: {}
|
||||
|
||||
collaborator:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
workspace:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
fulltext:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
rekoni:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 500Mi
|
||||
|
||||
stats:
|
||||
replicas: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 500Mi
|
||||
|
||||
kvs:
|
||||
enabled: true
|
||||
replicas: 1
|
||||
resources: {}
|
||||
|
||||
githubIntegration:
|
||||
# GitHub App integration — syncs issues, PRs, and comments with GitHub
|
||||
enabled: false
|
||||
replicas: 1
|
||||
# Bot name shown on GitHub (must match the GitHub App's slug + [bot])
|
||||
botName: ""
|
||||
# GitHub App credentials (stored in the shared secret)
|
||||
appId: ""
|
||||
clientId: ""
|
||||
clientSecret: ""
|
||||
privateKey: "" # PEM-encoded private key (use multiline YAML |)
|
||||
webhookSecret: ""
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
aibot:
|
||||
# AI bot service — requires OpenAI API key
|
||||
enabled: false
|
||||
replicas: 1
|
||||
firstName: "Huly"
|
||||
lastName: "AI"
|
||||
# Override default models (leave empty for upstream defaults)
|
||||
openaiModel: ""
|
||||
openaiEmbeddingModel: ""
|
||||
openaiTranslateModel: ""
|
||||
openaiSummaryModel: ""
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Backup — nightly CronJobs to S3-compatible storage
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
backup:
|
||||
enabled: false
|
||||
schedule: "0 2 * * *" # 2 AM daily
|
||||
retentionDays: 30
|
||||
rcloneImage: rclone/rclone:latest
|
||||
s3:
|
||||
endpoint: "" # e.g. https://nbg1.your-objectstorage.com
|
||||
region: ""
|
||||
bucket: "" # e.g. ledo-backups
|
||||
pathPrefix: "" # e.g. huly-ledo
|
||||
accessKey: ""
|
||||
secretKey: ""
|
||||
# Secondary credentials for rotation (optional)
|
||||
secondaryAccessKey: ""
|
||||
secondarySecretKey: ""
|
||||
# Which credential set is active: "primary" or "secondary"
|
||||
activeCredential: "primary"
|
||||
cockroachdb:
|
||||
enabled: true
|
||||
schedule: "" # override global schedule
|
||||
files:
|
||||
enabled: true
|
||||
schedule: ""
|
||||
mongodb:
|
||||
enabled: true # only runs when aibot.enabled=true
|
||||
schedule: ""
|
||||
Reference in New Issue
Block a user