feat: add helm charts
Signed-off-by: Thomas Stocker <thomas.stocker.pro@gmail.com>
This commit is contained in:
committed by
Bryan Frimin
parent
6d1760ce9b
commit
4a96bd796a
22
contrib/helm/.gitignore
vendored
Normal file
22
contrib/helm/.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# General files for the project
|
||||||
|
pkg/*
|
||||||
|
*.pyc
|
||||||
|
bin/*
|
||||||
|
.project
|
||||||
|
/.bin
|
||||||
|
/_test/secrets/*.json
|
||||||
|
|
||||||
|
# OSX leaves these everywhere on SMB shares
|
||||||
|
._*
|
||||||
|
|
||||||
|
# OSX trash
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# Vscode files
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
charts/probo/charts
|
||||||
474
contrib/helm/README.md
Normal file
474
contrib/helm/README.md
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
# Probo Kubernetes Deployment
|
||||||
|
|
||||||
|
This directory contains the Helm chart for deploying Probo on Kubernetes with external managed services.
|
||||||
|
|
||||||
|
## Quick Links
|
||||||
|
|
||||||
|
- [Helm Chart Documentation](charts/probo/README.md)
|
||||||
|
- [Values Reference](charts/probo/values.yaml)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before deploying Probo, ensure you have:
|
||||||
|
|
||||||
|
1. **Kubernetes Cluster** - Version 1.23+
|
||||||
|
2. **Helm** - Version 3.8+
|
||||||
|
3. **PostgreSQL Database** - Managed service (AWS RDS, GCP Cloud SQL, Azure Database, etc.)
|
||||||
|
4. **S3 Storage** - AWS S3 or S3-compatible storage (GCS, DigitalOcean Spaces, MinIO, etc.)
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Generate Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||||
|
export COOKIE_SECRET=$(openssl rand -base64 32)
|
||||||
|
export PASSWORD_PEPPER=$(openssl rand -base64 32)
|
||||||
|
export TRUST_TOKEN_SECRET=$(openssl rand -base64 32)
|
||||||
|
|
||||||
|
echo "Save these secrets securely!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Install
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
#### Using Official Chart Repository
|
||||||
|
> Have Helm 3 [installed](https://helm.sh/docs/intro/install).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
helm repo add probo https://getprobo.github.io/probo-helm-charts/
|
||||||
|
helm install probo probo/probo -n probo --create-namespace --values values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
To update versions:
|
||||||
|
|
||||||
|
```
|
||||||
|
helm repo update probo
|
||||||
|
helm upgrade probo probo/probo -n probo --values values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using Local Chart
|
||||||
|
|
||||||
|
##### Generate Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||||
|
export COOKIE_SECRET=$(openssl rand -base64 32)
|
||||||
|
export PASSWORD_PEPPER=$(openssl rand -base64 32)
|
||||||
|
export TRUST_TOKEN_SECRET=$(openssl rand -base64 32)
|
||||||
|
|
||||||
|
# Save these somewhere secure!
|
||||||
|
echo "ENCRYPTION_KEY=$ENCRYPTION_KEY"
|
||||||
|
echo "COOKIE_SECRET=$COOKIE_SECRET"
|
||||||
|
echo "PASSWORD_PEPPER=$PASSWORD_PEPPER"
|
||||||
|
echo "TRUST_TOKEN_SECRET=$TRUST_TOKEN_SECRET"
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Install using Chart and set values
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install my-probo ./charts/probo \
|
||||||
|
--set probo.hostname="probo.example.com" \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.enabled=true \
|
||||||
|
--set postgres.auth.postgresUser="probod" \
|
||||||
|
--set postgres.auth.postgresPassword="your-db-password" \
|
||||||
|
--set postgres.auth.database="probod" \
|
||||||
|
--set minio.enabled=true \
|
||||||
|
--set s3.bucket="your-bucket-name" \
|
||||||
|
--set s3.accessKeyId="your-access-key" \
|
||||||
|
--set s3.secretAccessKey="your-secret-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Install using Chart and values file
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install my-probo ./charts/probo \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
-f ./charts/probo/values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Access
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl port-forward svc/probo 8080:8080
|
||||||
|
# Visit http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
For production deployments, we recommend:
|
||||||
|
|
||||||
|
1. **Copy the production template:**
|
||||||
|
```bash
|
||||||
|
cp charts/probo/values.yaml charts/probo/values-k8s-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit the configuration:**
|
||||||
|
- Set your domain name
|
||||||
|
- Configure external PostgreSQL connection
|
||||||
|
- Configure S3 storage credentials
|
||||||
|
- Add SMTP settings for email
|
||||||
|
- Enable ingress with TLS
|
||||||
|
- Configure autoscaling
|
||||||
|
|
||||||
|
3. **Install:**
|
||||||
|
```bash
|
||||||
|
helm install probo ./charts/probo -f ./charts/probo/values-k8s-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### What Gets Deployed
|
||||||
|
|
||||||
|
- **Probo Application** - Main Go binary serving GraphQL APIs and React frontends
|
||||||
|
- **Chrome Headless** - For PDF generation (optional, can use external service)
|
||||||
|
- **LoadBalancer Service** - For external access via TCP on ports 80, 443, and 8080
|
||||||
|
- **Ingress** - Alternative to LoadBalancer for HTTP routing (optional)
|
||||||
|
|
||||||
|
### External Dependencies (Required)
|
||||||
|
|
||||||
|
- **PostgreSQL** - Managed database for compliance data
|
||||||
|
- **S3 Storage** - Object storage for files and documents
|
||||||
|
|
||||||
|
The chart is designed to work with managed cloud services, ensuring reliability and scalability.
|
||||||
|
|
||||||
|
### Deployment Mode: HAProxy Ingress (Default)
|
||||||
|
|
||||||
|
The default configuration uses HAProxy Ingress controller which provides both Layer 4 (TCP passthrough) and Layer 7 (HTTP routing) capabilities.
|
||||||
|
|
||||||
|
**Architecture:**
|
||||||
|
|
||||||
|
```
|
||||||
|
Client
|
||||||
|
↓
|
||||||
|
HAProxy Ingress LoadBalancer
|
||||||
|
├─ Port 80 (TCP Layer 4 passthrough) → probo:80
|
||||||
|
├─ Port 443 (TCP Layer 4 passthrough) → probo:443
|
||||||
|
└─ HTTP probo.example.com (Layer 7 routing) → probo:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
|
||||||
|
1. **HAProxy Ingress Controller** runs in the release namespace with a LoadBalancer service
|
||||||
|
2. **TCP ConfigMap** defines Layer 4 TCP passthrough rules:
|
||||||
|
- Port 80 → Probo service port 80
|
||||||
|
- Port 443 → Probo service port 443
|
||||||
|
3. **HTTP Ingress** defines Layer 7 HTTP routing:
|
||||||
|
- Host `probo.example.com` → Probo service port 8080
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Single LoadBalancer for both TCP and HTTP traffic
|
||||||
|
- TCP passthrough for ports 80/443 (Probo handles TLS directly)
|
||||||
|
- HTTP routing for backoffice on port 8080
|
||||||
|
- Supports ACME/Let's Encrypt integration
|
||||||
|
|
||||||
|
**Port Configuration:**
|
||||||
|
- **Port 80** - TCP passthrough to Probo:80 (HTTP service, ACME challenges)
|
||||||
|
- **Port 443** - TCP passthrough to Probo:443 (HTTPS service with TLS)
|
||||||
|
- **Port 8080** - HTTP routing to Probo:8080 (Backoffice, via host-based routing)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Required Configuration
|
||||||
|
|
||||||
|
All deployments require:
|
||||||
|
|
||||||
|
- `probo.encryptionKey` - For data encryption at rest
|
||||||
|
- `probo.auth.cookieSecret` - For session management
|
||||||
|
- `probo.auth.passwordPepper` - For password hashing
|
||||||
|
- `probo.trustAuth.tokenSecret` - For trust center tokens
|
||||||
|
- `postgresql.host` - PostgreSQL server hostname
|
||||||
|
- `postgresql.password` - Database password
|
||||||
|
- `s3.accessKeyId` - S3 access credentials
|
||||||
|
- `s3.secretAccessKey` - S3 secret key
|
||||||
|
|
||||||
|
See [values.yaml](charts/probo/values.yaml) for all available options.
|
||||||
|
|
||||||
|
|
||||||
|
## Cloud Provider Examples
|
||||||
|
|
||||||
|
### AWS
|
||||||
|
- PostgreSQL: Amazon RDS for PostgreSQL
|
||||||
|
- Storage: Amazon S3
|
||||||
|
- Kubernetes: Amazon EKS
|
||||||
|
|
||||||
|
#### Exemple
|
||||||
|
```bash
|
||||||
|
# Prerequisites:
|
||||||
|
# - Amazon RDS PostgreSQL instance
|
||||||
|
# - S3 bucket created
|
||||||
|
|
||||||
|
helm install my-probo ././charts/probo \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.host="mydb.abc123.us-east-1.rds.amazonaws.com" \
|
||||||
|
--set postgresql.password="<rds-password>" \
|
||||||
|
--set s3.region="us-east-1" \
|
||||||
|
--set s3.bucket="my-probo-bucket" \
|
||||||
|
--set s3.accessKeyId="<aws-access-key>" \
|
||||||
|
--set s3.secretAccessKey="<aws-secret-key>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GCP
|
||||||
|
- PostgreSQL: Cloud SQL for PostgreSQL
|
||||||
|
- Storage: Cloud Storage with S3 compatibility
|
||||||
|
- Kubernetes: Google Kubernetes Engine (GKE)
|
||||||
|
|
||||||
|
#### Exemple
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prerequisites:
|
||||||
|
# - Cloud SQL PostgreSQL instance
|
||||||
|
# - Cloud Storage bucket with HMAC keys
|
||||||
|
|
||||||
|
helm install my-probo ././charts/probo \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.host="10.0.0.5" \
|
||||||
|
--set postgresql.password="<cloudsql-password>" \
|
||||||
|
--set s3.endpoint="https://storage.googleapis.com" \
|
||||||
|
--set s3.bucket="my-probo-bucket" \
|
||||||
|
--set s3.accessKeyId="<hmac-access-key>" \
|
||||||
|
--set s3.secretAccessKey="<hmac-secret>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Azure
|
||||||
|
- PostgreSQL: Azure Database for PostgreSQL
|
||||||
|
- Storage: Azure Blob Storage (with S3 compatibility)
|
||||||
|
- Kubernetes: Azure Kubernetes Service (AKS)
|
||||||
|
|
||||||
|
#### Exemple
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prerequisites:
|
||||||
|
# - Azure Database for PostgreSQL instance
|
||||||
|
# - Azure Blob Storage container with S3 compatibility
|
||||||
|
helm install my-probo ././charts/probo \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.host="mydb.postgres.database.azure.com" \
|
||||||
|
--set postgresql.password="<azure-db-password>" \
|
||||||
|
--set s3.endpoint="https://<your-storage-account>.blob.core.windows.net" \
|
||||||
|
--set s3.bucket="my-probo-bucket" \
|
||||||
|
--set s3.accessKeyId="<azure-access-key>" \
|
||||||
|
--set s3.secretAccessKey="<azure-secret-key>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### DigitalOcean
|
||||||
|
- PostgreSQL: Managed PostgreSQL Database
|
||||||
|
- Storage: DigitalOcean Spaces
|
||||||
|
- Kubernetes: DigitalOcean Kubernetes (DOKS)
|
||||||
|
|
||||||
|
#### Exemple
|
||||||
|
```bash
|
||||||
|
# Prerequisites:
|
||||||
|
# - Managed PostgreSQL Database
|
||||||
|
# - Spaces bucket
|
||||||
|
|
||||||
|
helm install my-probo ././charts/probo \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.host="db-postgresql-nyc1-12345.ondigitalocean.com" \
|
||||||
|
--set postgresql.password="<db-password>" \
|
||||||
|
--set s3.region="nyc3" \
|
||||||
|
--set s3.endpoint="https://nyc3.digitaloceanspaces.com" \
|
||||||
|
--set s3.bucket="my-probo-bucket" \
|
||||||
|
--set s3.accessKeyId="<spaces-key>" \
|
||||||
|
--set s3.secretAccessKey="<spaces-secret>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using External Secrets Operator
|
||||||
|
|
||||||
|
Example with AWS Secrets Manager:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: probo-secrets
|
||||||
|
spec:
|
||||||
|
secretStoreRef:
|
||||||
|
name: aws-secrets-manager
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: probo
|
||||||
|
data:
|
||||||
|
- secretKey: encryption-key
|
||||||
|
remoteRef:
|
||||||
|
key: probo/encryption-key
|
||||||
|
- secretKey: db-password
|
||||||
|
remoteRef:
|
||||||
|
key: probo/db-password
|
||||||
|
```
|
||||||
|
|
||||||
|
## Full Values
|
||||||
|
|
||||||
|
| Key | Type | Default | Description |
|
||||||
|
|-----------------------------------------------| ------- |----------------------------------------------------|-----------------------------------------------------------------------------------------------------|
|
||||||
|
| replicaCount | int | `1` | Number of Probo application replicas |
|
||||||
|
| image.repository | string | `"ghcr.io/getprobo/probo"` | Container image repository |
|
||||||
|
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
|
||||||
|
| image.tag | string | `"latest"` | Overrides the image tag whose default is the chart appVersion |
|
||||||
|
| imagePullSecrets | list | `[]` | Image pull secrets for private registries |
|
||||||
|
| nameOverride | string | `""` | Override the name of the chart |
|
||||||
|
| fullnameOverride | string | `""` | Override the fullname of the chart |
|
||||||
|
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
|
||||||
|
| serviceAccount.automount | bool | `true` | Automatically mount a ServiceAccount's API credentials |
|
||||||
|
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
|
||||||
|
| serviceAccount.name | string | `""` | The name of the service account to use |
|
||||||
|
| podAnnotations | object | `{}` | Annotations to add to pods |
|
||||||
|
| podLabels | object | `{}` | Labels to add to pods |
|
||||||
|
| podSecurityContext.runAsUser | int | `0` | User ID to run the container as (0 = root, change to 1000 for production) |
|
||||||
|
| podSecurityContext.runAsGroup | int | `0` | Group ID to run the container as (0 = root, change to 1000 for production) |
|
||||||
|
| securityContext.runAsUser | int | `0` | User ID for the security context |
|
||||||
|
| securityContext.runAsGroup | int | `0` | Group ID for the security context |
|
||||||
|
| securityContext.privileged | bool | `true` | Enable privileged mode for the container (set to false for production) |
|
||||||
|
| securityContext.capabilities.drop | list | `["ALL"]` | Linux capabilities to drop from the container |
|
||||||
|
| securityContext.readOnlyRootFilesystem | bool | `false` | Mount root filesystem as read-only (/data directory requires write access) |
|
||||||
|
| service.type | string | `"ClusterIP"` | Kubernetes service type |
|
||||||
|
| service.port | int | `8080` | Service port |
|
||||||
|
| service.httpPort | int | `80` | HTTP port for TCP passthrough |
|
||||||
|
| service.httpsPort | int | `443` | HTTPS port for TCP passthrough |
|
||||||
|
| service.annotations | object | `{}` | Annotations for the service |
|
||||||
|
| haproxy-ingress.enabled | bool | `true` | Enable included HAProxy Ingress controller |
|
||||||
|
| haproxy-ingress.controller.ingressClass | string | `"haproxy"` | Ingress class name for the controller |
|
||||||
|
| haproxy-ingress.controller.ingressClassResource.enabled | bool | `true` | Enable IngressClass resource creation |
|
||||||
|
| haproxy-ingress.controller.ingressClassResource.name | string | `"haproxy"` | Name of the IngressClass resource |
|
||||||
|
| haproxy-ingress.controller.ingressClassResource.default | bool | `false` | Set as default IngressClass |
|
||||||
|
| haproxy-ingress.controller.service.type | string | `"LoadBalancer"` | HAProxy Ingress controller service type |
|
||||||
|
| haproxy-ingress.controller.extraArgs | list | `["--tcp-services-configmap=$(POD_NAMESPACE)/haproxy-tcp-services"]` | Extra arguments for HAProxy controller |
|
||||||
|
| haproxy-ingress.controller.config.ssl-redirect | string | `"false"` | Disable automatic SSL redirect |
|
||||||
|
| ingress.enabled | bool | `true` | Enable ingress resource |
|
||||||
|
| ingress.className | string | `"haproxy"` | Ingress class name |
|
||||||
|
| ingress.annotations | object | `{"kubernetes.io/ingress.class": "haproxy"}` | Annotations for the ingress resource |
|
||||||
|
| ingress.hosts[0].host | string | `"probo.example.com"` | Ingress hostname |
|
||||||
|
| ingress.hosts[0].paths[0].path | string | `"/"` | Path to match |
|
||||||
|
| ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | Path matching type |
|
||||||
|
| ingress.tls | list | `[]` | TLS configuration for ingress |
|
||||||
|
| resources.limits.cpu | string | `"2000m"` | CPU limit for the container |
|
||||||
|
| resources.limits.memory | string | `"2Gi"` | Memory limit for the container |
|
||||||
|
| resources.requests.cpu | string | `"500m"` | CPU request for the container |
|
||||||
|
| resources.requests.memory | string | `"512Mi"` | Memory request for the container |
|
||||||
|
| livenessProbe.httpGet.path | string | `"/"` | Path for the liveness probe |
|
||||||
|
| livenessProbe.httpGet.port | string | `"http"` | Port for the liveness probe |
|
||||||
|
| livenessProbe.initialDelaySeconds | int | `30` | Initial delay for liveness probe |
|
||||||
|
| livenessProbe.periodSeconds | int | `10` | Period for liveness probe |
|
||||||
|
| livenessProbe.timeoutSeconds | int | `5` | Timeout for liveness probe |
|
||||||
|
| livenessProbe.failureThreshold | int | `6` | Failure threshold for liveness probe |
|
||||||
|
| readinessProbe.httpGet.path | string | `"/"` | Path for the readiness probe |
|
||||||
|
| readinessProbe.httpGet.port | string | `"http"` | Port for the readiness probe |
|
||||||
|
| readinessProbe.initialDelaySeconds | int | `10` | Initial delay for readiness probe |
|
||||||
|
| readinessProbe.periodSeconds | int | `5` | Period for readiness probe |
|
||||||
|
| readinessProbe.timeoutSeconds | int | `3` | Timeout for readiness probe |
|
||||||
|
| readinessProbe.failureThreshold | int | `3` | Failure threshold for readiness probe |
|
||||||
|
| autoscaling.enabled | bool | `false` | Enable horizontal pod autoscaling |
|
||||||
|
| autoscaling.minReplicas | int | `1` | Minimum number of replicas |
|
||||||
|
| autoscaling.maxReplicas | int | `10` | Maximum number of replicas |
|
||||||
|
| autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage |
|
||||||
|
| volumes | list | `[]` | Additional volumes on the output Deployment definition |
|
||||||
|
| volumeMounts | list | `[]` | Additional volumeMounts on the output Deployment definition |
|
||||||
|
| nodeSelector | object | `{}` | Node selector for pod assignment |
|
||||||
|
| tolerations | list | `[]` | Tolerations for pod assignment |
|
||||||
|
| affinity | object | `{}` | Affinity rules for pod assignment |
|
||||||
|
| persistence.enabled | bool | `false` | Enable persistent volume for data storage |
|
||||||
|
| persistence.storageClass | string | `""` | Storage class for the persistent volume |
|
||||||
|
| persistence.accessMode | string | `"ReadWriteOnce"` | Access mode for the persistent volume |
|
||||||
|
| persistence.size | string | `"10Gi"` | Size of the persistent volume |
|
||||||
|
| persistence.annotations | object | `{}` | Annotations for the persistent volume claim |
|
||||||
|
| metrics.serviceMonitor.enabled | bool | `false` | Enable Prometheus Operator ServiceMonitor |
|
||||||
|
| metrics.serviceMonitor.interval | string | `"30s"` | Scrape interval for metrics |
|
||||||
|
| metrics.serviceMonitor.scrapeTimeout | string | `"10s"` | Scrape timeout for metrics |
|
||||||
|
| metrics.serviceMonitor.labels | object | `{}` | Labels for the ServiceMonitor |
|
||||||
|
| metrics.serviceMonitor.relabelings | list | `[]` | Relabeling configs for the ServiceMonitor |
|
||||||
|
| probo.hostname | string | `"probo.example.com"` | Public hostname where Probo will be accessible |
|
||||||
|
| probo.encryptionKey | string | `""` | **REQUIRED** Base64-encoded encryption key (generate with: openssl rand -base64 32) |
|
||||||
|
| probo.service.port | int | `8080` | Probo application service port |
|
||||||
|
| probo.metrics.port | int | `8081` | Probo metrics service port |
|
||||||
|
| probo.tracing.enabled | bool | `false` | Enable OpenTelemetry tracing |
|
||||||
|
| probo.tracing.addr | string | `""` | OTLP gRPC endpoint (e.g., tempo:4317) |
|
||||||
|
| probo.tracing.maxBatchSize | int | `512` | Maximum batch size for trace exports |
|
||||||
|
| probo.tracing.batchTimeout | int | `5` | Batch timeout in seconds |
|
||||||
|
| probo.tracing.exportTimeout | int | `30` | Export timeout in seconds |
|
||||||
|
| probo.tracing.maxQueueSize | int | `2048` | Maximum queue size for traces |
|
||||||
|
| probo.cors.allowedOrigins | list | `["https://probo.example.com", "http://..."]` | CORS allowed origins |
|
||||||
|
| probo.extraHeaderFields | object | `{}` | Extra HTTP headers to add to responses |
|
||||||
|
| probo.auth.disableSignup | bool | `false` | Disable user signup |
|
||||||
|
| probo.auth.invitationTokenValidity | int | `3600` | Invitation token validity in seconds |
|
||||||
|
| probo.auth.cookieName | string | `"SSID"` | Authentication cookie name |
|
||||||
|
| probo.auth.cookieDomain | string | `"probo.example.com"` | Authentication cookie domain |
|
||||||
|
| probo.auth.cookieSecret | string | `""` | **REQUIRED** Cookie signing secret (at least 32 bytes, generate with: openssl rand -base64 32) |
|
||||||
|
| probo.auth.cookieDuration | int | `24` | Cookie duration in hours |
|
||||||
|
| probo.auth.passwordPepper | string | `""` | **REQUIRED** Password hashing pepper (at least 32 bytes, generate with: openssl rand -base64 32) |
|
||||||
|
| probo.auth.passwordIterations | int | `1000000` | Password hashing iterations |
|
||||||
|
| probo.trustAuth.cookieName | string | `"TCT"` | Trust center cookie name |
|
||||||
|
| probo.trustAuth.cookieDomain | string | `"probo.example.com"` | Trust center cookie domain |
|
||||||
|
| probo.trustAuth.cookieDuration | int | `24` | Trust center cookie duration in hours |
|
||||||
|
| probo.trustAuth.tokenDuration | int | `168` | Trust token duration in hours |
|
||||||
|
| probo.trustAuth.reportUrlDuration | int | `15` | Report URL duration in minutes |
|
||||||
|
| probo.trustAuth.tokenSecret | string | `""` | **REQUIRED** Trust token signing secret (at least 32 bytes, generate with: openssl rand -base64 32) |
|
||||||
|
| probo.trustAuth.scope | string | `"trust_center_readonly"` | Trust token scope |
|
||||||
|
| probo.trustAuth.tokenType | string | `"trust_center_access"` | Trust token type |
|
||||||
|
| probo.mailer.senderName | string | `"Probo"` | Email sender name |
|
||||||
|
| probo.mailer.senderEmail | string | `"no-reply@notification.getprobo.com"` | Email sender address |
|
||||||
|
| probo.mailer.smtp.addr | string | `"sandbox.smtp.mailtrap.io:2525"` | SMTP server address |
|
||||||
|
| probo.mailer.smtp.user | string | `"2d1b1d0e8b3d0b"` | SMTP username |
|
||||||
|
| probo.mailer.smtp.password | string | `"25a8eb11e75e8d"` | SMTP password |
|
||||||
|
| probo.mailer.smtp.tlsRequired | bool | `true` | Require TLS for SMTP connection |
|
||||||
|
| probo.openai.apiKey | string | `""` | OpenAI API key for AI features (optional) |
|
||||||
|
| probo.openai.temperature | float | `0.1` | OpenAI temperature setting |
|
||||||
|
| probo.openai.modelName | string | `"gpt-4o"` | OpenAI model name |
|
||||||
|
| probo.customDomains.enabled | bool | `false` | Enable custom domains feature |
|
||||||
|
| probo.customDomains.renewalInterval | int | `3600` | Certificate renewal interval in seconds |
|
||||||
|
| probo.customDomains.provisionInterval | int | `30` | Domain provision interval in seconds |
|
||||||
|
| probo.customDomains.cnameTarget | string | `"probo.example.com"` | CNAME target for custom domains |
|
||||||
|
| probo.customDomains.acme.directory | string | `"https://acme-v02.api.letsencrypt.org/directory"` | ACME directory URL |
|
||||||
|
| probo.customDomains.acme.email | string | `"admin@example.com"` | ACME registration email |
|
||||||
|
| probo.customDomains.acme.keyType | string | `"EC256"` | ACME key type |
|
||||||
|
| probo.customDomains.acme.insecureTls | bool | `false` | Allow insecure TLS for ACME |
|
||||||
|
| probo.connectors | list | `[]` | External OAuth2 connectors configuration |
|
||||||
|
| postgresql.enabled | bool | `true` | Enable included PostgreSQL container for demo purposes using CloudNativePG |
|
||||||
|
| postgresql.resources.limits.memory | string | `"2Gi"` | PostgreSQL memory limit |
|
||||||
|
| postgresql.resources.limits.ephemeral-storage | string | `"5Gi"` | PostgreSQL ephemeral storage limit |
|
||||||
|
| postgresql.auth.postgresUser | string | `"probod"` | PostgreSQL username |
|
||||||
|
| postgresql.auth.postgresPassword | string | `"probod"` | PostgreSQL password |
|
||||||
|
| postgresql.auth.database | string | `"probod"` | PostgreSQL database name |
|
||||||
|
| s3.region | string | `"us-east-1"` | S3 region |
|
||||||
|
| s3.bucket | string | `"probod"` | S3 bucket name |
|
||||||
|
| s3.endpoint | string | `""` | S3 endpoint (leave empty for AWS S3, set for S3-compatible storage) |
|
||||||
|
| s3.accessKeyId | string | `""` | **REQUIRED** (when minio.enabled=false) S3 access key |
|
||||||
|
| s3.secretAccessKey | string | `""` | **REQUIRED** (when minio.enabled=false) S3 secret key |
|
||||||
|
| minio.enabled | bool | `true` | Enable included MinIO for demo purposes (NOT for production) |
|
||||||
|
| minio.mode | string | `"standalone"` | MinIO mode |
|
||||||
|
| minio.persistence.enabled | bool | `false` | Enable MinIO persistence |
|
||||||
|
| minio.resources.requests.memory | string | `"128Mi"` | MinIO memory request |
|
||||||
|
| minio.primary.enabled | bool | `true` | Enable MinIO primary node |
|
||||||
|
| minio.auth.rootUser | string | `"probod"` | MinIO root username |
|
||||||
|
| minio.auth.rootPassword | string | `"probod"` | MinIO root password |
|
||||||
|
| chrome.enabled | bool | `true` | Deploy Chrome headless in the cluster for PDF generation |
|
||||||
|
| chrome.replicaCount | int | `1` | Number of Chrome replicas |
|
||||||
|
| chrome.image.repository | string | `"chromedp/headless-shell"` | Chrome container image repository |
|
||||||
|
| chrome.image.tag | string | `"140.0.7259.2"` | Chrome image tag |
|
||||||
|
| chrome.image.pullPolicy | string | `"IfNotPresent"` | Chrome image pull policy |
|
||||||
|
| chrome.resources.limits.cpu | string | `"1000m"` | Chrome CPU limit |
|
||||||
|
| chrome.resources.limits.memory | string | `"1Gi"` | Chrome memory limit |
|
||||||
|
| chrome.resources.requests.cpu | string | `"100m"` | Chrome CPU request |
|
||||||
|
| chrome.resources.requests.memory | string | `"256Mi"` | Chrome memory request |
|
||||||
|
| chrome.external.addr | string | `""` | External Chrome address (used when chrome.enabled=false) |
|
||||||
23
contrib/helm/charts/probo/.helmignore
Normal file
23
contrib/helm/charts/probo/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
||||||
87
contrib/helm/charts/probo/CONFIG_NOTE.md
Normal file
87
contrib/helm/charts/probo/CONFIG_NOTE.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Configuration Note
|
||||||
|
|
||||||
|
## Environment Variable Substitution
|
||||||
|
|
||||||
|
The Helm chart templates use a `-from-env` suffix pattern in the configuration file (e.g., `encryption-key-from-env: "ENCRYPTION_KEY"`). This pattern assumes the Probo application supports reading secrets from environment variables instead of directly from the config file.
|
||||||
|
|
||||||
|
### Current Implementation
|
||||||
|
|
||||||
|
The chart currently:
|
||||||
|
1. Stores sensitive values in a Kubernetes Secret
|
||||||
|
2. Mounts them as environment variables in the pod
|
||||||
|
3. References them in the config with `-from-env` suffix
|
||||||
|
|
||||||
|
### If Probo Doesn't Support `-from-env` Pattern
|
||||||
|
|
||||||
|
If the current Probo application doesn't support the `-from-env` pattern, you have three options:
|
||||||
|
|
||||||
|
#### Option 1: Implement in Probo (Recommended)
|
||||||
|
|
||||||
|
Update the Probo configuration parser to recognize `-from-env` suffixes and read from environment variables. This is the most secure approach.
|
||||||
|
|
||||||
|
Example in Go:
|
||||||
|
```go
|
||||||
|
// In config loading code
|
||||||
|
if strings.HasSuffix(key, "-from-env") {
|
||||||
|
envVar := value.(string)
|
||||||
|
actualValue := os.Getenv(envVar)
|
||||||
|
// Use actualValue instead of value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: Use initContainer with envsubst
|
||||||
|
|
||||||
|
Modify the deployment to use an init container that substitutes environment variables:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
initContainers:
|
||||||
|
- name: config-init
|
||||||
|
image: alpine:3.19
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
apk add --no-cache gettext
|
||||||
|
envsubst < /config-template/config.yaml > /config/config.yaml
|
||||||
|
env:
|
||||||
|
# All environment variables from secrets
|
||||||
|
- name: ENCRYPTION_KEY
|
||||||
|
valueFrom: ...
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-template
|
||||||
|
mountPath: /config-template
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update the ConfigMap to use `${ENCRYPTION_KEY}` instead of the `-from-env` pattern.
|
||||||
|
|
||||||
|
#### Option 3: Mount Everything as Secret
|
||||||
|
|
||||||
|
Create a complete config.yaml as a Secret (not ConfigMap) with actual values:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: probo-config
|
||||||
|
stringData:
|
||||||
|
config.yaml: |
|
||||||
|
probod:
|
||||||
|
encryption-key: {{ .Values.probo.encryptionKey }}
|
||||||
|
# ... all config with actual values
|
||||||
|
```
|
||||||
|
|
||||||
|
This is simpler but less secure as the entire config is stored as a Secret.
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
We recommend implementing Option 1 in the Probo codebase as it:
|
||||||
|
- Follows Kubernetes best practices
|
||||||
|
- Keeps secrets separate from configuration
|
||||||
|
- Works well with secret management tools (Vault, External Secrets, etc.)
|
||||||
|
- Supports secret rotation without config changes
|
||||||
|
|
||||||
|
## Current Status
|
||||||
|
|
||||||
|
The Helm chart is built with Option 1 in mind. If the Probo application doesn't yet support `-from-env`, please implement it or use one of the alternative approaches above.
|
||||||
9
contrib/helm/charts/probo/Chart.lock
Normal file
9
contrib/helm/charts/probo/Chart.lock
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: minio
|
||||||
|
repository: https://charts.min.io/
|
||||||
|
version: 5.4.0
|
||||||
|
- name: kubernetes-ingress
|
||||||
|
repository: https://haproxytech.github.io/helm-charts
|
||||||
|
version: 1.45.1
|
||||||
|
digest: sha256:86861ee988df3673c6306ff42719f09d12ce22e2d48a0db757ad4365d204bd85
|
||||||
|
generated: "2025-10-31T10:17:36.108938+01:00"
|
||||||
29
contrib/helm/charts/probo/Chart.yaml
Normal file
29
contrib/helm/charts/probo/Chart.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: probo
|
||||||
|
description: A Helm chart for deploying Probo - Open Source Compliance Platform
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "0.74.7"
|
||||||
|
keywords:
|
||||||
|
- compliance
|
||||||
|
- soc2
|
||||||
|
- security
|
||||||
|
- governance
|
||||||
|
home: https://getprobo.com
|
||||||
|
sources:
|
||||||
|
- https://github.com/getprobo/probo
|
||||||
|
maintainers:
|
||||||
|
- name: Probo Team
|
||||||
|
email: hello@getprobo.com
|
||||||
|
icon: https://github.com/getprobo/probo/blob/main/.github/cover_v3.png
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- name: minio
|
||||||
|
condition: minio.enabled
|
||||||
|
repository: https://charts.min.io/
|
||||||
|
version: 5.4.0 # Latest stable version
|
||||||
|
- name: kubernetes-ingress
|
||||||
|
alias: haproxy-ingress
|
||||||
|
condition: haproxy-ingress.enabled
|
||||||
|
version: 1.45.1
|
||||||
|
repository: https://haproxytech.github.io/helm-charts
|
||||||
267
contrib/helm/charts/probo/README.md
Normal file
267
contrib/helm/charts/probo/README.md
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
# Probo Helm Chart
|
||||||
|
|
||||||
|
This Helm chart deploys Probo - an open-source SOC-2 compliance platform - on Kubernetes.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.23+
|
||||||
|
- Helm 3.8+
|
||||||
|
- External PostgreSQL database (AWS RDS, GCP Cloud SQL, Azure Database, etc.)
|
||||||
|
- S3 or S3-compatible object storage (AWS S3, GCS, DigitalOcean Spaces, MinIO, etc.)
|
||||||
|
|
||||||
|
## Installing the Chart
|
||||||
|
|
||||||
|
### Generate Required Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate required secrets
|
||||||
|
export ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||||
|
export COOKIE_SECRET=$(openssl rand -base64 32)
|
||||||
|
export PASSWORD_PEPPER=$(openssl rand -base64 32)
|
||||||
|
export TRUST_TOKEN_SECRET=$(openssl rand -base64 32)
|
||||||
|
|
||||||
|
echo "Save these secrets securely!"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install probo . \
|
||||||
|
--set probo.hostname="probo.example.com" \
|
||||||
|
--set probo.encryptionKey="$ENCRYPTION_KEY" \
|
||||||
|
--set probo.auth.cookieSecret="$COOKIE_SECRET" \
|
||||||
|
--set probo.auth.passwordPepper="$PASSWORD_PEPPER" \
|
||||||
|
--set probo.trustAuth.tokenSecret="$TRUST_TOKEN_SECRET" \
|
||||||
|
--set postgresql.host="postgres.example.com" \
|
||||||
|
--set postgresql.password="<db-password>" \
|
||||||
|
--set s3.bucket="probo-production" \
|
||||||
|
--set s3.accessKeyId="<aws-access-key-id>" \
|
||||||
|
--set s3.secretAccessKey="<aws-secret-access-key>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Deployment
|
||||||
|
|
||||||
|
For production, create a `values-production.yaml` file:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# values-production.yaml
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/getprobo/probo
|
||||||
|
tag: "0.74.7"
|
||||||
|
|
||||||
|
replicaCount: 3
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "nginx"
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
hosts:
|
||||||
|
- host: probo.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: probo-tls
|
||||||
|
hosts:
|
||||||
|
- probo.example.com
|
||||||
|
|
||||||
|
probo:
|
||||||
|
hostname: "probo.example.com"
|
||||||
|
encryptionKey: "<secret>"
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://probo.example.com"
|
||||||
|
auth:
|
||||||
|
cookieDomain: "example.com"
|
||||||
|
cookieSecret: "<secret>"
|
||||||
|
passwordPepper: "<secret>"
|
||||||
|
trustAuth:
|
||||||
|
cookieDomain: "example.com"
|
||||||
|
tokenSecret: "<secret>"
|
||||||
|
mailer:
|
||||||
|
senderEmail: "noreply@example.com"
|
||||||
|
smtp:
|
||||||
|
addr: "smtp.sendgrid.net:587"
|
||||||
|
user: "apikey"
|
||||||
|
password: "<smtp-password>"
|
||||||
|
tlsRequired: true
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
host: "postgres.example.com"
|
||||||
|
password: "<db-password>"
|
||||||
|
|
||||||
|
s3:
|
||||||
|
region: "us-east-1"
|
||||||
|
bucket: "probo-production"
|
||||||
|
accessKeyId: "<aws-access-key-id>"
|
||||||
|
secretAccessKey: "<aws-secret-access-key>"
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
Install with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install probo . -f values-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Required Configuration
|
||||||
|
|
||||||
|
The following parameters **must** be configured:
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| `probo.encryptionKey` | Base64-encoded encryption key (32+ bytes) |
|
||||||
|
| `probo.auth.cookieSecret` | Cookie signing secret (32+ bytes) |
|
||||||
|
| `probo.auth.passwordPepper` | Password hashing pepper (32+ bytes) |
|
||||||
|
| `probo.trustAuth.tokenSecret` | Trust token secret (32+ bytes) |
|
||||||
|
| `postgresql.host` | PostgreSQL hostname |
|
||||||
|
| `postgresql.password` | PostgreSQL password |
|
||||||
|
| `s3.accessKeyId` | S3 access key ID |
|
||||||
|
| `s3.secretAccessKey` | S3 secret access key |
|
||||||
|
|
||||||
|
### Key Configuration Parameters
|
||||||
|
|
||||||
|
| Parameter | Description | Default |
|
||||||
|
|-----------|-------------|---------|
|
||||||
|
| `image.repository` | Probo image repository | `ghcr.io/getprobo/probo` |
|
||||||
|
| `image.tag` | Probo image tag | Chart appVersion |
|
||||||
|
| `replicaCount` | Number of Probo replicas | `1` |
|
||||||
|
| `probo.hostname` | Public hostname | `probo.example.com` |
|
||||||
|
| `postgresql.host` | PostgreSQL host | `""` (required) |
|
||||||
|
| `postgresql.port` | PostgreSQL port | `5432` |
|
||||||
|
| `postgresql.database` | Database name | `probod` |
|
||||||
|
| `postgresql.username` | Database user | `probod` |
|
||||||
|
| `s3.bucket` | S3 bucket name | `probod` |
|
||||||
|
| `s3.region` | AWS region | `us-east-1` |
|
||||||
|
| `s3.endpoint` | S3 endpoint (for S3-compatible) | `""` |
|
||||||
|
| `chrome.enabled` | Deploy Chrome | `true` |
|
||||||
|
| `chrome.external.addr` | External Chrome (if disabled) | `""` |
|
||||||
|
| `ingress.enabled` | Enable ingress | `false` |
|
||||||
|
|
||||||
|
See [values.yaml](values.yaml) for all available options.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
The chart deploys the following:
|
||||||
|
|
||||||
|
- **Probo Application**: Main Go binary serving GraphQL APIs and SPAs
|
||||||
|
- **Chrome Headless**: For PDF generation (optional, can use external)
|
||||||
|
- **Ingress**: For external access with TLS (optional)
|
||||||
|
|
||||||
|
### External Dependencies (Required)
|
||||||
|
|
||||||
|
- **PostgreSQL**: Managed database service
|
||||||
|
- **S3 Storage**: Object storage for files and documents
|
||||||
|
|
||||||
|
## Database Management
|
||||||
|
|
||||||
|
### Migrations
|
||||||
|
|
||||||
|
Database migrations run automatically when Probo starts. No manual intervention is required.
|
||||||
|
|
||||||
|
### Backup
|
||||||
|
|
||||||
|
Use your PostgreSQL provider's backup solution (e.g., AWS RDS automated backups, GCP Cloud SQL backups).
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade probo . -f values-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uninstalling
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm uninstall probo
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** This does not delete your external PostgreSQL database or S3 bucket.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs -f deployment/probo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl describe configmap probo
|
||||||
|
kubectl get secret probo -o yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Database Connection
|
||||||
|
|
||||||
|
Check the Probo logs for database connection errors. The application will fail to start if it cannot connect to PostgreSQL.
|
||||||
|
|
||||||
|
### Test S3 Connection
|
||||||
|
|
||||||
|
Check the Probo logs for S3 connection errors when uploading files.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### AWS Deployment
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
postgresql:
|
||||||
|
host: "mydb.abc123.us-east-1.rds.amazonaws.com"
|
||||||
|
password: "<rds-password>"
|
||||||
|
|
||||||
|
s3:
|
||||||
|
region: "us-east-1"
|
||||||
|
bucket: "my-probo-bucket"
|
||||||
|
accessKeyId: "<aws-key>"
|
||||||
|
secretAccessKey: "<aws-secret>"
|
||||||
|
# Leave endpoint empty for AWS S3
|
||||||
|
```
|
||||||
|
|
||||||
|
### GCP Deployment
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
postgresql:
|
||||||
|
host: "10.0.0.5" # Cloud SQL private IP
|
||||||
|
password: "<cloudsql-password>"
|
||||||
|
|
||||||
|
s3:
|
||||||
|
region: "us-east1"
|
||||||
|
bucket: "my-probo-bucket"
|
||||||
|
endpoint: "https://storage.googleapis.com"
|
||||||
|
accessKeyId: "<hmac-access-key>"
|
||||||
|
secretAccessKey: "<hmac-secret>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### DigitalOcean Deployment
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
postgresql:
|
||||||
|
host: "db-postgresql-nyc1-12345.ondigitalocean.com"
|
||||||
|
password: "<db-password>"
|
||||||
|
|
||||||
|
s3:
|
||||||
|
region: "nyc3"
|
||||||
|
bucket: "my-probo-bucket"
|
||||||
|
endpoint: "https://nyc3.digitaloceanspaces.com"
|
||||||
|
accessKeyId: "<spaces-access-key>"
|
||||||
|
secretAccessKey: "<spaces-secret>"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using External Chrome Service
|
||||||
|
|
||||||
|
By default, Chrome is deployed in the cluster. To use an external Chrome service:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
chrome:
|
||||||
|
enabled: false
|
||||||
|
external:
|
||||||
|
addr: "chrome.browserless.io:3000"
|
||||||
|
```
|
||||||
84
contrib/helm/charts/probo/templates/NOTES.txt
Normal file
84
contrib/helm/charts/probo/templates/NOTES.txt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
🎉 Probo has been successfully deployed!
|
||||||
|
|
||||||
|
📋 Release Information:
|
||||||
|
Name: {{ .Release.Name }}
|
||||||
|
Namespace: {{ .Release.Namespace }}
|
||||||
|
Version: {{ .Chart.AppVersion }}
|
||||||
|
|
||||||
|
🌐 Accessing Probo:
|
||||||
|
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
{{- range $host := .Values.ingress.hosts }}
|
||||||
|
Application: {{ if $.Values.ingress.tls }}https{{ else }}http{{ end }}://{{ $host.host }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
Get the application URL by running:
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "probo.fullname" . }})
|
||||||
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
|
echo "Application: http://$NODE_IP:$NODE_PORT"
|
||||||
|
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status by running:
|
||||||
|
kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "probo.fullname" . }}
|
||||||
|
|
||||||
|
Once available, get the application URL by running:
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "probo.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo "Application: http://$SERVICE_IP:{{ .Values.service.port }}"
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
Application is available only within the cluster.
|
||||||
|
|
||||||
|
To access it from your local machine, run:
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "probo.fullname" . }} 8080:{{ .Values.service.port }}
|
||||||
|
|
||||||
|
Then visit: http://localhost:8080
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
📊 Monitoring:
|
||||||
|
Metrics endpoint: http://{{ include "probo.fullname" . }}:{{ .Values.probo.metrics.port }}/metrics
|
||||||
|
|
||||||
|
To access metrics from your local machine, run:
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "probo.fullname" . }} 8081:{{ .Values.probo.metrics.port }}
|
||||||
|
|
||||||
|
🔍 View Logs:
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} logs -f deployment/{{ include "probo.fullname" . }}
|
||||||
|
|
||||||
|
🗄️ Database:
|
||||||
|
Using external PostgreSQL at: {{ .Values.postgresql.host }}:{{ .Values.postgresql.port }}
|
||||||
|
Database: {{ .Values.postgresql.database }}
|
||||||
|
|
||||||
|
💾 Object Storage:
|
||||||
|
Using S3 storage
|
||||||
|
Bucket: {{ .Values.s3.bucket }}
|
||||||
|
Region: {{ .Values.s3.region }}
|
||||||
|
{{- if .Values.s3.endpoint }}
|
||||||
|
Endpoint: {{ .Values.s3.endpoint }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
⚠️ Important Security Notes:
|
||||||
|
|
||||||
|
{{- if not .Values.ingress.tls }}
|
||||||
|
⚠️ TLS is not enabled! Enable it for production by configuring ingress.tls
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
📚 Next Steps:
|
||||||
|
|
||||||
|
1. Update the hostname in values.yaml to match your domain:
|
||||||
|
probo.hostname: "{{ .Values.probo.hostname }}"
|
||||||
|
|
||||||
|
2. Configure email delivery:
|
||||||
|
Update probo.mailer.smtp settings with your SMTP server details.
|
||||||
|
|
||||||
|
{{- if not .Values.probo.openai.apiKey }}
|
||||||
|
3. (Optional) Configure OpenAI integration for AI-powered features:
|
||||||
|
Set probo.openai.apiKey in values.yaml
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
4. Review and update CORS allowed origins:
|
||||||
|
probo.cors.allowedOrigins
|
||||||
|
|
||||||
|
📖 Documentation:
|
||||||
|
- GitHub: https://github.com/getprobo/probo
|
||||||
|
- Discord: https://discord.gg/8qfdJYfvpY
|
||||||
|
- Website: https://getprobo.com
|
||||||
|
|
||||||
|
✨ Thank you for using Probo!
|
||||||
159
contrib/helm/charts/probo/templates/_helpers.tpl
Normal file
159
contrib/helm/charts/probo/templates/_helpers.tpl
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "probo.chart" . }}
|
||||||
|
{{ include "probo.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "probo.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "probo.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
PostgreSQL hostname
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.postgresql.host" -}}
|
||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
{{- printf "%s-postgresql-demo" .Release.Name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.postgresql.host | required "postgresql.host is required when postgresql.enabled=false" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
PostgreSQL port
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.postgresql.port" -}}
|
||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
{{- 5432 }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.postgresql.port | default 5432 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
PostgreSQL database name
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.postgresql.database" -}}
|
||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
{{- .Values.postgresql.auth.database | default "probod" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.postgresql.database | default "probod" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
PostgreSQL username
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.postgresql.username" -}}
|
||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
{{- .Values.postgresql.auth.postgresUser | default "probod" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.postgresql.username | default "probod" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
PostgreSQL password (from subchart or external config)
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.postgresql.password" -}}
|
||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
{{- .Values.postgresql.auth.postgresPassword | required "postgresql.auth.postgresPassword is required when postgresql.enabled=true" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.postgresql.password | required "postgresql.password is required when postgresql.enabled=false" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
S3 endpoint
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.s3.endpoint" -}}
|
||||||
|
{{- if .Values.minio.enabled }}
|
||||||
|
{{- printf "http://%s-minio:9000" .Release.Name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.s3.endpoint }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
S3 access key
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.s3.accessKeyId" -}}
|
||||||
|
{{- if .Values.minio.enabled }}
|
||||||
|
{{- .Values.minio.auth.rootUser | required "minio.auth.rootUser is required when minio.enabled=true" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.s3.accessKeyId | required "s3.accessKeyId is required when minio.enabled=false" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
S3 secret key
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.s3.secretAccessKey" -}}
|
||||||
|
{{- if .Values.minio.enabled }}
|
||||||
|
{{- .Values.minio.auth.rootPassword | required "minio.auth.rootPassword is required when minio.enabled=true" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.s3.secretAccessKey | required "s3.secretAccessKey is required when minio.enabled=false" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Chrome DevTools Protocol address
|
||||||
|
*/}}
|
||||||
|
{{- define "probo.chrome.addr" -}}
|
||||||
|
{{- if .Values.chrome.enabled }}
|
||||||
|
{{- printf "%s-chrome:9222" (include "probo.fullname" .) }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.chrome.external.addr | required "chrome.external.addr is required when chrome.enabled=false" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
77
contrib/helm/charts/probo/templates/chrome.yaml
Normal file
77
contrib/helm/charts/probo/templates/chrome.yaml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
{{- if .Values.chrome.enabled }}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}-chrome
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: chrome
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.chrome.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 6 }}
|
||||||
|
app.kubernetes.io/component: chrome
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: chrome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: chrome
|
||||||
|
image: "{{ .Values.chrome.image.repository }}:{{ .Values.chrome.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.chrome.image.pullPolicy }}
|
||||||
|
args:
|
||||||
|
- --headless
|
||||||
|
- --disable-gpu
|
||||||
|
- --disable-dev-shm-usage
|
||||||
|
- --hide-scrollbars
|
||||||
|
- --mute-audio
|
||||||
|
- --no-default-browser-check
|
||||||
|
- --no-first-run
|
||||||
|
- --disable-background-networking
|
||||||
|
- --disable-background-timer-throttling
|
||||||
|
- --disable-extensions
|
||||||
|
ports:
|
||||||
|
- name: devtools
|
||||||
|
containerPort: 9222
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /json/version
|
||||||
|
port: devtools
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /json/version
|
||||||
|
port: devtools
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.chrome.resources | nindent 12 }}
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}-chrome
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: chrome
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 9222
|
||||||
|
targetPort: devtools
|
||||||
|
protocol: TCP
|
||||||
|
name: devtools
|
||||||
|
selector:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: chrome
|
||||||
|
{{- end }}
|
||||||
119
contrib/helm/charts/probo/templates/configmap.yaml
Normal file
119
contrib/helm/charts/probo/templates/configmap.yaml
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
config.yml: |
|
||||||
|
unit:
|
||||||
|
metrics:
|
||||||
|
addr: "0.0.0.0:{{ .Values.probo.metrics.port }}"
|
||||||
|
{{- if .Values.probo.tracing.enabled }}
|
||||||
|
tracing:
|
||||||
|
addr: {{ .Values.probo.tracing.addr | quote }}
|
||||||
|
max-batch-size: {{ .Values.probo.tracing.maxBatchSize }}
|
||||||
|
batch-timeout: {{ .Values.probo.tracing.batchTimeout }}
|
||||||
|
export-timeout: {{ .Values.probo.tracing.exportTimeout }}
|
||||||
|
max-queue-size: {{ .Values.probo.tracing.maxQueueSize }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
probod:
|
||||||
|
hostname: {{ .Values.probo.hostname | quote }}
|
||||||
|
encryption-key: {{ .Values.probo.encryptionKey | quote }}
|
||||||
|
chrome-dp-addr: {{ include "probo.chrome.addr" . | quote }}
|
||||||
|
|
||||||
|
api:
|
||||||
|
addr: "0.0.0.0:{{ .Values.service.port }}"
|
||||||
|
cors:
|
||||||
|
allowed-origins:
|
||||||
|
{{- toYaml .Values.probo.cors.allowedOrigins | nindent 12 }}
|
||||||
|
{{- if .Values.probo.extraHeaderFields }}
|
||||||
|
extra-header-fields:
|
||||||
|
{{- toYaml .Values.probo.extraHeaderFields | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
pg:
|
||||||
|
addr: "{{ include "probo.postgresql.host" . }}:{{ include "probo.postgresql.port" . }}"
|
||||||
|
username: {{ include "probo.postgresql.username" . | quote }}
|
||||||
|
password: {{ include "probo.postgresql.password" . | quote }}
|
||||||
|
database: {{ include "probo.postgresql.database" . | quote }}
|
||||||
|
pool-size: {{ .Values.postgresql.poolSize }}
|
||||||
|
{{- if .Values.postgresql.caCertBundle }}
|
||||||
|
ca-cert-bundle: |
|
||||||
|
{{- .Values.postgresql.caCertBundle | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
auth:
|
||||||
|
disable-signup: {{ .Values.probo.auth.disableSignup }}
|
||||||
|
invitation-confirmation-token-validity: {{ .Values.probo.auth.invitationTokenValidity }}
|
||||||
|
cookie:
|
||||||
|
name: {{ .Values.probo.auth.cookieName | quote }}
|
||||||
|
domain: {{ .Values.probo.auth.cookieDomain | quote }}
|
||||||
|
secret: {{ .Values.probo.auth.cookieSecret | quote }}
|
||||||
|
duration: {{ .Values.probo.auth.cookieDuration }}
|
||||||
|
password:
|
||||||
|
pepper: {{ .Values.probo.auth.passwordPepper | quote }}
|
||||||
|
iterations: {{ .Values.probo.auth.passwordIterations }}
|
||||||
|
|
||||||
|
trust-auth:
|
||||||
|
cookie-name: {{ .Values.probo.trustAuth.cookieName | quote }}
|
||||||
|
cookie-domain: {{ .Values.probo.trustAuth.cookieDomain | quote }}
|
||||||
|
cookie-duration: {{ .Values.probo.trustAuth.cookieDuration }}
|
||||||
|
token-duration: {{ .Values.probo.trustAuth.tokenDuration }}
|
||||||
|
report-url-duration: {{ .Values.probo.trustAuth.reportUrlDuration }}
|
||||||
|
{{- if .Values.probo.trustAuth.ports }}
|
||||||
|
ports:
|
||||||
|
http-challenge: {{ .Values.probo.trustAuth.ports.httpChallenge }}
|
||||||
|
tls-http-server: {{ .Values.probo.trustAuth.ports.tlsHttpServer }}
|
||||||
|
{{- end }}
|
||||||
|
token-secret: {{ .Values.probo.trustAuth.tokenSecret | quote }}
|
||||||
|
scope: {{ .Values.probo.trustAuth.scope | quote }}
|
||||||
|
token-type: {{ .Values.probo.trustAuth.tokenType | quote }}
|
||||||
|
|
||||||
|
aws:
|
||||||
|
region: {{ .Values.s3.region | quote }}
|
||||||
|
bucket: {{ .Values.s3.bucket | quote }}
|
||||||
|
access-key-id: {{ .Values.s3.accessKey | quote }}
|
||||||
|
secret-access-key: {{ .Values.s3.secretKey | quote }}
|
||||||
|
{{- $s3Endpoint := include "probo.s3.endpoint" . }}
|
||||||
|
{{- if $s3Endpoint }}
|
||||||
|
endpoint: {{ $s3Endpoint | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
mailer:
|
||||||
|
sender-name: {{ .Values.probo.mailer.senderName | quote }}
|
||||||
|
sender-email: {{ .Values.probo.mailer.senderEmail | quote }}
|
||||||
|
smtp:
|
||||||
|
addr: {{ .Values.probo.mailer.smtp.addr | quote }}
|
||||||
|
{{- if .Values.probo.mailer.smtp.user }}
|
||||||
|
user: {{ .Values.probo.mailer.smtp.user | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.probo.mailer.smtp.password }}
|
||||||
|
password: {{ .Values.probo.mailer.smtp.password | quote }}
|
||||||
|
{{- end }}
|
||||||
|
tls-required: {{ .Values.probo.mailer.smtp.tlsRequired }}
|
||||||
|
|
||||||
|
{{- if .Values.probo.openai.apiKey }}
|
||||||
|
openai:
|
||||||
|
api-key-from-env: "OPENAI_API_KEY"
|
||||||
|
temperature: {{ .Values.probo.openai.temperature }}
|
||||||
|
model-name: {{ .Values.probo.openai.modelName | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.probo.customDomains.enabled }}
|
||||||
|
custom-domains:
|
||||||
|
renewal-interval: {{ .Values.probo.customDomains.renewalInterval }}
|
||||||
|
provision-interval: {{ .Values.probo.customDomains.provisionInterval }}
|
||||||
|
cname-target: {{ .Values.probo.customDomains.cnameTarget | quote }}
|
||||||
|
acme:
|
||||||
|
directory: {{ .Values.probo.customDomains.acme.directory | quote }}
|
||||||
|
email: {{ .Values.probo.customDomains.acme.email | quote }}
|
||||||
|
key-type: {{ .Values.probo.customDomains.acme.keyType | quote }}
|
||||||
|
insecure-tls: {{ .Values.probo.customDomains.acme.insecureTls }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.probo.connectors }}
|
||||||
|
connectors:
|
||||||
|
{{- toYaml .Values.probo.connectors | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
162
contrib/helm/charts/probo/templates/deployment.yaml
Normal file
162
contrib/helm/charts/probo/templates/deployment.yaml
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||||
|
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 8 }}
|
||||||
|
{{- with .Values.podLabels }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "probo.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
command: ["/bin/sh", "-c"] # replaces ENTRYPOINT
|
||||||
|
args: ["echo $DB_PASSWORD && cat /etc/probod/config.yml && exec /usr/local/bin/probod -cfg-file /etc/probod/config.yml"]
|
||||||
|
|
||||||
|
# args:
|
||||||
|
# - "-cfg-file"
|
||||||
|
# - "/etc/probod/config.yml"
|
||||||
|
env:
|
||||||
|
# Database credentials
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: db-password
|
||||||
|
# S3 credentials
|
||||||
|
- name: S3_ACCESS_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: s3-access-key
|
||||||
|
- name: S3_SECRET_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: s3-secret-key
|
||||||
|
# Application secrets
|
||||||
|
- name: ENCRYPTION_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: encryption-key
|
||||||
|
- name: COOKIE_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: cookie-secret
|
||||||
|
- name: PASSWORD_PEPPER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: password-pepper
|
||||||
|
- name: TRUST_TOKEN_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: trust-token-secret
|
||||||
|
# Optional SMTP credentials
|
||||||
|
{{- if .Values.probo.mailer.smtp.user }}
|
||||||
|
- name: SMTP_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: smtp-user
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.probo.mailer.smtp.password }}
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: smtp-password
|
||||||
|
{{- end }}
|
||||||
|
# Optional OpenAI API key
|
||||||
|
{{- if .Values.probo.openai.apiKey }}
|
||||||
|
- name: OPENAI_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
key: openai-api-key
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.httpPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: https
|
||||||
|
containerPort: {{ .Values.service.httpsPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: backoffice
|
||||||
|
containerPort: {{ .Values.service.port }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: metrics
|
||||||
|
containerPort: {{ .Values.probo.metrics.port }}
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/probod
|
||||||
|
readOnly: false
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
{{- with .Values.volumeMounts }}
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
- name: data
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ .Values.persistence.existingClaim | default (include "probo.fullname" .) }}
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.volumes }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{{- if index .Values "haproxy-ingress" "enabled" -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: haproxy-tcp-services
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
# TCP passthrough for port 80 (HTTP)
|
||||||
|
# Format: "<port>": "<namespace>/<service>:<port>"
|
||||||
|
"80": "{{ .Release.Namespace }}/{{ include "probo.fullname" . }}:{{ .Values.service.httpPort }}"
|
||||||
|
|
||||||
|
# TCP passthrough for port 443 (HTTPS)
|
||||||
|
"443": "{{ .Release.Namespace }}/{{ include "probo.fullname" . }}:{{ .Values.service.httpsPort }}"
|
||||||
|
{{- end }}
|
||||||
32
contrib/helm/charts/probo/templates/hpa.yaml
Normal file
32
contrib/helm/charts/probo/templates/hpa.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v2
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
metrics:
|
||||||
|
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: cpu
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: memory
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
41
contrib/helm/charts/probo/templates/ingress.yaml
Normal file
41
contrib/helm/charts/probo/templates/ingress.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}-http
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "probo.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
81
contrib/helm/charts/probo/templates/postgresql-demo-app.yml
Normal file
81
contrib/helm/charts/probo/templates/postgresql-demo-app.yml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{{- if .Values.postgresql.enabled }}
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}-postgresql-demo
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ include "probo.fullname" . }}-postgresql-demo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ include "probo.fullname" . }}-postgresql-demo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:18
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: {{ .Values.postgresql.auth.postgresUser }}
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
value: {{ .Values.postgresql.auth.postgresPassword }}
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: {{ .Values.postgresql.auth.database }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
volumeMounts:
|
||||||
|
- name: postgres-init
|
||||||
|
mountPath: /docker-entrypoint-initdb.d
|
||||||
|
readOnly: true
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.postgresql.resources | nindent 12 }}
|
||||||
|
volumes:
|
||||||
|
- name: postgres-init
|
||||||
|
configMap:
|
||||||
|
name: {{ include "probo.fullname" . }}-postgres-init
|
||||||
|
defaultMode: 0755
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .Release.Name }}-postgresql-demo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: {{ include "probo.fullname" . }}-postgresql-demo
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: 5432
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}-postgres-init
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
01_probod.sh: |
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 -U $POSTGRES_USER <<-EOF
|
||||||
|
ALTER USER probod WITH SUPERUSER;
|
||||||
|
ALTER USER probod PASSWORD 'probod';
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE probod TO probod;
|
||||||
|
CREATE DATABASE probod_test;
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE probod_test TO probod;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 -U $POSTGRES_USER -d probod <<-EOF
|
||||||
|
ALTER SCHEMA public OWNER TO probod;
|
||||||
|
GRANT ALL ON SCHEMA public TO probod;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 -U $POSTGRES_USER -d probod_test <<-EOF
|
||||||
|
ALTER SCHEMA public OWNER TO probod;
|
||||||
|
GRANT ALL ON SCHEMA public TO probod;
|
||||||
|
EOF
|
||||||
|
---
|
||||||
|
{{- end -}}
|
||||||
25
contrib/helm/charts/probo/templates/pvc.yaml
Normal file
25
contrib/helm/charts/probo/templates/pvc.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.persistence.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size | quote }}
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
{{- if (eq "-" .Values.persistence.storageClass) }}
|
||||||
|
storageClassName: ""
|
||||||
|
{{- else }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
33
contrib/helm/charts/probo/templates/secret.yaml
Normal file
33
contrib/helm/charts/probo/templates/secret.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Database credentials
|
||||||
|
db-password: {{ include "probo.postgresql.password" . | quote }}
|
||||||
|
|
||||||
|
# S3 credentials
|
||||||
|
s3-access-key: {{ include "probo.s3.accessKeyId" . | quote }}
|
||||||
|
s3-secret-key: {{ include "probo.s3.secretAccessKey" . | quote }}
|
||||||
|
|
||||||
|
# Application secrets
|
||||||
|
encryption-key: {{ .Values.probo.encryptionKey | required "probo.encryptionKey is required" | quote }}
|
||||||
|
cookie-secret: {{ .Values.probo.auth.cookieSecret | required "probo.auth.cookieSecret is required" | quote }}
|
||||||
|
password-pepper: {{ .Values.probo.auth.passwordPepper | required "probo.auth.passwordPepper is required" | quote }}
|
||||||
|
trust-token-secret: {{ .Values.probo.trustAuth.tokenSecret | required "probo.trustAuth.tokenSecret is required" | quote }}
|
||||||
|
|
||||||
|
# Optional SMTP credentials
|
||||||
|
{{- if .Values.probo.mailer.smtp.user }}
|
||||||
|
smtp-user: {{ .Values.probo.mailer.smtp.user | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.probo.mailer.smtp.password }}
|
||||||
|
smtp-password: {{ .Values.probo.mailer.smtp.password | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Optional OpenAI API key
|
||||||
|
{{- if .Values.probo.openai.apiKey }}
|
||||||
|
openai-api-key: {{ .Values.probo.openai.apiKey | quote }}
|
||||||
|
{{- end }}
|
||||||
44
contrib/helm/charts/probo/templates/service.yaml
Normal file
44
contrib/helm/charts/probo/templates/service.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.service.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
{{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }}
|
||||||
|
clusterIP: {{ .Values.service.clusterIP }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.loadBalancerIP }}
|
||||||
|
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.loadBalancerSourceRanges }}
|
||||||
|
loadBalancerSourceRanges:
|
||||||
|
{{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.httpPort }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
- port: {{ .Values.service.httpsPort }}
|
||||||
|
targetPort: https
|
||||||
|
protocol: TCP
|
||||||
|
name: https
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: backoffice
|
||||||
|
protocol: TCP
|
||||||
|
name: backoffice
|
||||||
|
{{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }}
|
||||||
|
nodePort: {{ .Values.service.nodePort }}
|
||||||
|
{{- end }}
|
||||||
|
- port: {{ .Values.probo.metrics.port }}
|
||||||
|
targetPort: metrics
|
||||||
|
protocol: TCP
|
||||||
|
name: metrics
|
||||||
|
selector:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 4 }}
|
||||||
13
contrib/helm/charts/probo/templates/serviceaccount.yaml
Normal file
13
contrib/helm/charts/probo/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{{- if .Values.serviceAccount.create -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.serviceAccountName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
|
||||||
|
{{- end }}
|
||||||
24
contrib/helm/charts/probo/templates/servicemonitor.yaml
Normal file
24
contrib/helm/charts/probo/templates/servicemonitor.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{{- if .Values.metrics.serviceMonitor.enabled }}
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
name: {{ include "probo.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "probo.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.labels }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "probo.selectorLabels" . | nindent 6 }}
|
||||||
|
endpoints:
|
||||||
|
- port: metrics
|
||||||
|
path: /metrics
|
||||||
|
interval: {{ .Values.metrics.serviceMonitor.interval }}
|
||||||
|
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.relabelings }}
|
||||||
|
relabelings:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
311
contrib/helm/charts/probo/values-production.yaml.example
Normal file
311
contrib/helm/charts/probo/values-production.yaml.example
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
# Production values for probo.
|
||||||
|
# This file provides a template for production deployment.
|
||||||
|
# Copy this file to values-production.yaml and customize it for your environment.
|
||||||
|
|
||||||
|
# Use specific version tag
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/getprobo/probo
|
||||||
|
tag: "0.74.7"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Scale for high availability
|
||||||
|
replicaCount: 3
|
||||||
|
|
||||||
|
# Production security context (non-root user)
|
||||||
|
podSecurityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000 # probo user (UID defined in Dockerfile)
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false # /data directory requires write access
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
|
||||||
|
# Service configuration
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
httpPort: 80
|
||||||
|
httpsPort: 443
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# Production resource limits
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
|
||||||
|
# Enable horizontal pod autoscaling
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilizationPercentage: 70
|
||||||
|
targetMemoryUtilizationPercentage: 80
|
||||||
|
|
||||||
|
# HAProxy Ingress Controller configuration
|
||||||
|
haproxy-ingress:
|
||||||
|
enabled: true
|
||||||
|
controller:
|
||||||
|
ingressClass: haproxy
|
||||||
|
ingressClassResource:
|
||||||
|
enabled: true
|
||||||
|
name: haproxy
|
||||||
|
default: false
|
||||||
|
name: controller
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
annotations:
|
||||||
|
# Cloud provider annotations for LoadBalancer
|
||||||
|
# AWS example:
|
||||||
|
# service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
|
||||||
|
# GCP example:
|
||||||
|
# cloud.google.com/load-balancer-type: "External"
|
||||||
|
extraArgs:
|
||||||
|
- --tcp-services-configmap=$(POD_NAMESPACE)/haproxy-tcp-services
|
||||||
|
config:
|
||||||
|
ssl-redirect: "false" # Probo handles SSL internally
|
||||||
|
|
||||||
|
# Configure ingress with TLS
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "haproxy"
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: haproxy
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
hosts:
|
||||||
|
- host: probo.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: probo-tls
|
||||||
|
hosts:
|
||||||
|
- probo.example.com
|
||||||
|
|
||||||
|
# Probo application configuration
|
||||||
|
probo:
|
||||||
|
# Must match your ingress hostname
|
||||||
|
hostname: "probo.example.com"
|
||||||
|
|
||||||
|
# REQUIRED: Generate with: openssl rand -base64 32
|
||||||
|
encryptionKey: "CHANGE_ME_ENCRYPTION_KEY"
|
||||||
|
|
||||||
|
service:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
port: 8081
|
||||||
|
|
||||||
|
# CORS configuration - add all domains that will access the API
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://probo.example.com"
|
||||||
|
|
||||||
|
# Extra HTTP headers to add to responses
|
||||||
|
extraHeaderFields: {}
|
||||||
|
# X-Custom-Header: "custom-value"
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
auth:
|
||||||
|
# Set to true to disable public signup
|
||||||
|
disableSignup: false
|
||||||
|
# Cookie domain should be your root domain
|
||||||
|
cookieDomain: "example.com"
|
||||||
|
# REQUIRED: Generate with: openssl rand -base64 32
|
||||||
|
cookieSecret: "CHANGE_ME_COOKIE_SECRET"
|
||||||
|
# REQUIRED: Generate with: openssl rand -base64 32
|
||||||
|
passwordPepper: "CHANGE_ME_PASSWORD_PEPPER"
|
||||||
|
|
||||||
|
# Trust center authentication
|
||||||
|
trustAuth:
|
||||||
|
cookieName: "TCT"
|
||||||
|
cookieDomain: "example.com"
|
||||||
|
cookieDuration: 24
|
||||||
|
tokenDuration: 168
|
||||||
|
reportUrlDuration: 15
|
||||||
|
ports:
|
||||||
|
httpChallenge: 80
|
||||||
|
tlsHttpServer: 443
|
||||||
|
# REQUIRED: Generate with: openssl rand -base64 32
|
||||||
|
tokenSecret: "CHANGE_ME_TRUST_TOKEN_SECRET"
|
||||||
|
scope: "trust_center_readonly"
|
||||||
|
tokenType: "trust_center_access"
|
||||||
|
|
||||||
|
# Email configuration
|
||||||
|
mailer:
|
||||||
|
senderName: "Probo"
|
||||||
|
senderEmail: "noreply@example.com"
|
||||||
|
smtp:
|
||||||
|
# Use your SMTP provider (e.g., SendGrid, Mailgun, AWS SES)
|
||||||
|
addr: "smtp.sendgrid.net:587"
|
||||||
|
user: "apikey"
|
||||||
|
password: "CHANGE_ME_SMTP_PASSWORD"
|
||||||
|
tlsRequired: true
|
||||||
|
|
||||||
|
# OpenAI integration for AI features (optional)
|
||||||
|
openai:
|
||||||
|
apiKey: "CHANGE_ME_OPENAI_API_KEY"
|
||||||
|
temperature: 0.1
|
||||||
|
modelName: "gpt-4o"
|
||||||
|
|
||||||
|
# OpenTelemetry tracing (optional)
|
||||||
|
tracing:
|
||||||
|
enabled: true
|
||||||
|
addr: "tempo.monitoring:4317"
|
||||||
|
maxBatchSize: 1000
|
||||||
|
batchTimeout: 10
|
||||||
|
exportTimeout: 30
|
||||||
|
maxQueueSize: 10000
|
||||||
|
|
||||||
|
# Custom domains with Let's Encrypt (optional)
|
||||||
|
customDomains:
|
||||||
|
enabled: true
|
||||||
|
renewalInterval: 86400 # 24 hours
|
||||||
|
provisionInterval: 300 # 5 minutes
|
||||||
|
cnameTarget: "custom.example.com"
|
||||||
|
acme:
|
||||||
|
directory: "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
email: "admin@example.com"
|
||||||
|
keyType: "EC256"
|
||||||
|
insecureTls: false
|
||||||
|
|
||||||
|
# External OAuth2 connectors (optional)
|
||||||
|
connectors:
|
||||||
|
- name: "github"
|
||||||
|
type: "oauth2"
|
||||||
|
config:
|
||||||
|
client-id: "CHANGE_ME_GITHUB_CLIENT_ID"
|
||||||
|
client-secret: "CHANGE_ME_GITHUB_CLIENT_SECRET"
|
||||||
|
redirect-uri: "https://probo.example.com/api/console/v1/connectors/complete"
|
||||||
|
auth-url: "https://github.com/login/oauth/authorize"
|
||||||
|
token-url: "https://github.com/login/oauth/access_token"
|
||||||
|
|
||||||
|
# PostgreSQL configuration (REQUIRED)
|
||||||
|
# For production: Use external managed PostgreSQL (AWS RDS, GCP Cloud SQL, etc.)
|
||||||
|
# Disable the included PostgreSQL chart
|
||||||
|
postgresql:
|
||||||
|
# Disable the included PostgreSQL for production
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# External PostgreSQL connection (configure these when enabled=false)
|
||||||
|
# Examples:
|
||||||
|
# - AWS RDS: mydb.abc123.us-east-1.rds.amazonaws.com
|
||||||
|
# - GCP Cloud SQL: 10.0.0.5 (private IP)
|
||||||
|
# - Azure Database: myserver.postgres.database.azure.com
|
||||||
|
# - DigitalOcean: db-postgresql-nyc1-12345.ondigitalocean.com
|
||||||
|
host: "CHANGE_ME_POSTGRES_HOST"
|
||||||
|
port: 5432
|
||||||
|
database: "probod"
|
||||||
|
username: "probod"
|
||||||
|
password: "CHANGE_ME_DB_PASSWORD"
|
||||||
|
poolSize: 200
|
||||||
|
# Uncomment if using TLS with custom CA
|
||||||
|
# caCertBundle: |
|
||||||
|
# -----BEGIN CERTIFICATE-----
|
||||||
|
# ...
|
||||||
|
# -----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# MinIO configuration
|
||||||
|
# Disable included MinIO for production - use external S3 instead
|
||||||
|
minio:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# S3 storage configuration (REQUIRED)
|
||||||
|
s3:
|
||||||
|
# AWS S3 example:
|
||||||
|
region: "us-east-1"
|
||||||
|
bucket: "probo-production"
|
||||||
|
# Leave endpoint empty for AWS S3
|
||||||
|
endpoint: ""
|
||||||
|
accessKeyId: "CHANGE_ME_AWS_ACCESS_KEY_ID"
|
||||||
|
secretAccessKey: "CHANGE_ME_AWS_SECRET_ACCESS_KEY"
|
||||||
|
|
||||||
|
# GCP Cloud Storage example (uncomment and adjust):
|
||||||
|
# region: "us-east1"
|
||||||
|
# bucket: "probo-production"
|
||||||
|
# endpoint: "https://storage.googleapis.com"
|
||||||
|
# accessKeyId: "GOOG1E..." # HMAC access key
|
||||||
|
# secretAccessKey: "..." # HMAC secret
|
||||||
|
|
||||||
|
# DigitalOcean Spaces example (uncomment and adjust):
|
||||||
|
# region: "nyc3"
|
||||||
|
# bucket: "probo-production"
|
||||||
|
# endpoint: "https://nyc3.digitaloceanspaces.com"
|
||||||
|
# accessKeyId: "..." # Spaces access key
|
||||||
|
# secretAccessKey: "..." # Spaces secret
|
||||||
|
|
||||||
|
# Chrome for PDF generation
|
||||||
|
chrome:
|
||||||
|
enabled: true
|
||||||
|
# Scale for concurrent PDF generation
|
||||||
|
replicaCount: 3
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
|
||||||
|
# To use external Chrome service instead, set enabled=false and configure:
|
||||||
|
# external:
|
||||||
|
# addr: "chrome.browserless.io:3000"
|
||||||
|
|
||||||
|
# Persistent data volume (optional)
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
# Use existing PVC or let Helm create one
|
||||||
|
# existingClaim: "probo-data-pvc"
|
||||||
|
storageClass: "" # Use default storage class or specify one
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 50Gi
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# Enable Prometheus monitoring
|
||||||
|
metrics:
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: true
|
||||||
|
interval: 30s
|
||||||
|
scrapeTimeout: 10s
|
||||||
|
labels:
|
||||||
|
prometheus: kube-prometheus
|
||||||
|
|
||||||
|
# Pod placement (optional)
|
||||||
|
nodeSelector: {}
|
||||||
|
# node-role.kubernetes.io/worker: "true"
|
||||||
|
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
# Anti-affinity for high availability
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- weight: 100
|
||||||
|
podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: app.kubernetes.io/name
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- probo
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
|
||||||
|
# Service account annotations (for workload identity, IRSA, etc.)
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
annotations: {}
|
||||||
|
# AWS EKS example (uncomment and adjust):
|
||||||
|
# eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/probo-role
|
||||||
|
|
||||||
|
# GCP GKE example (uncomment and adjust):
|
||||||
|
# iam.gke.io/gcp-service-account: probo@PROJECT_ID.iam.gserviceaccount.com
|
||||||
352
contrib/helm/charts/probo/values.yaml
Normal file
352
contrib/helm/charts/probo/values.yaml
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
# Default values for probo.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/getprobo/probo
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
|
tag: "latest"
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
# Specifies whether a service account should be created
|
||||||
|
create: true
|
||||||
|
# Automatically mount a ServiceAccount's API credentials?
|
||||||
|
automount: true
|
||||||
|
# Annotations to add to the service account
|
||||||
|
annotations: {}
|
||||||
|
# The name of the service account to use.
|
||||||
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
podLabels: {}
|
||||||
|
|
||||||
|
podSecurityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
runAsGroup: 0
|
||||||
|
# runAsNonRoot: false
|
||||||
|
# runAsUser: 1000 # probo user (UID defined in Dockerfile)
|
||||||
|
# fsGroup: 1000 # probo group
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
runAsGroup: 0
|
||||||
|
privileged: true
|
||||||
|
# allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false # /data directory requires write access for file uploads
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
httpPort: 80
|
||||||
|
httpsPort: 443
|
||||||
|
# nodePort: 30080
|
||||||
|
# clusterIP: ""
|
||||||
|
# loadBalancerIP: ""
|
||||||
|
# loadBalancerSourceRanges: []
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
haproxy-ingress:
|
||||||
|
enabled: true
|
||||||
|
controller:
|
||||||
|
ingressClass: haproxy # This tells the controller to create an IngressClass
|
||||||
|
ingressClassResource:
|
||||||
|
enabled: true # Enable IngressClass resource creation
|
||||||
|
name: haproxy
|
||||||
|
default: false
|
||||||
|
name: controller
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
annotations: {}
|
||||||
|
extraArgs:
|
||||||
|
- --tcp-services-configmap=$(POD_NAMESPACE)/haproxy-tcp-services
|
||||||
|
config:
|
||||||
|
# HAProxy Ingress global config
|
||||||
|
ssl-redirect: "false"
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "haproxy"
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: haproxy
|
||||||
|
# cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
hosts:
|
||||||
|
- host: probo.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: probo
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
|
tls: []
|
||||||
|
# - secretName: probo-tls
|
||||||
|
# hosts:
|
||||||
|
# - probo.example.com
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: backoffice
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 6
|
||||||
|
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: backoffice
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilizationPercentage: 80
|
||||||
|
# targetMemoryUtilizationPercentage: 80
|
||||||
|
|
||||||
|
# Additional volumes on the output Deployment definition.
|
||||||
|
volumes: []
|
||||||
|
# - name: foo
|
||||||
|
# secret:
|
||||||
|
# secretName: mysecret
|
||||||
|
# optional: false
|
||||||
|
|
||||||
|
# Additional volumeMounts on the output Deployment definition.
|
||||||
|
volumeMounts: []
|
||||||
|
# - name: foo
|
||||||
|
# mountPath: "/etc/foo"
|
||||||
|
# readOnly: true
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
affinity: {}
|
||||||
|
|
||||||
|
# Persistent data volume
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
# existingClaim: ""
|
||||||
|
storageClass: ""
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 10Gi
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# Prometheus Operator ServiceMonitor
|
||||||
|
metrics:
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: false
|
||||||
|
interval: 30s
|
||||||
|
scrapeTimeout: 10s
|
||||||
|
labels: {}
|
||||||
|
relabelings: []
|
||||||
|
|
||||||
|
# Probo application configuration
|
||||||
|
probo:
|
||||||
|
# Public hostname where Probo will be accessible
|
||||||
|
# This should match your ingress host
|
||||||
|
hostname: probo.example.com
|
||||||
|
|
||||||
|
# Base64-encoded encryption key (REQUIRED)
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
encryptionKey: ""
|
||||||
|
|
||||||
|
service:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
port: 8081
|
||||||
|
|
||||||
|
# OpenTelemetry tracing configuration
|
||||||
|
tracing:
|
||||||
|
enabled: false
|
||||||
|
# OTLP gRPC endpoint (e.g., tempo:4317)
|
||||||
|
addr: ""
|
||||||
|
maxBatchSize: 512
|
||||||
|
batchTimeout: 5
|
||||||
|
exportTimeout: 30
|
||||||
|
maxQueueSize: 2048
|
||||||
|
# pg:
|
||||||
|
# addr: "probo-postgresql-demo-app:5432"
|
||||||
|
# username: "postgres"
|
||||||
|
# password: "probod"
|
||||||
|
# database: "probod"
|
||||||
|
# pool-size: 100
|
||||||
|
|
||||||
|
# CORS configuration
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://probo.example.com"
|
||||||
|
- "http://probo.example.com"
|
||||||
|
|
||||||
|
# Extra HTTP headers to add to responses
|
||||||
|
extraHeaderFields: {}
|
||||||
|
|
||||||
|
# Authentication configuration
|
||||||
|
auth:
|
||||||
|
disableSignup: false
|
||||||
|
invitationTokenValidity: 3600
|
||||||
|
cookieName: "SSID"
|
||||||
|
cookieDomain: "probo.example.com"
|
||||||
|
# Cookie signing secret (REQUIRED, at least 32 bytes)
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
cookieSecret: ""
|
||||||
|
cookieDuration: 24
|
||||||
|
# Password hashing pepper (REQUIRED, at least 32 bytes)
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
passwordPepper: ""
|
||||||
|
passwordIterations: 1000000
|
||||||
|
|
||||||
|
# Trust center authentication
|
||||||
|
trustAuth:
|
||||||
|
cookieName: "TCT"
|
||||||
|
cookieDomain: "probo.example.com"
|
||||||
|
cookieDuration: 24
|
||||||
|
tokenDuration: 168
|
||||||
|
reportUrlDuration: 15
|
||||||
|
ports:
|
||||||
|
httpChallenge: 80
|
||||||
|
tlsHttpServer: 443
|
||||||
|
# Trust token signing secret (REQUIRED, at least 32 bytes)
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
tokenSecret: ""
|
||||||
|
scope: "trust_center_readonly"
|
||||||
|
tokenType: "trust_center_access"
|
||||||
|
|
||||||
|
# Email configuration
|
||||||
|
mailer:
|
||||||
|
senderName: "Probo"
|
||||||
|
senderEmail: "no-reply@notification.getprobo.com"
|
||||||
|
smtp:
|
||||||
|
addr: "sandbox.smtp.mailtrap.io:2525"
|
||||||
|
user: "2d1b1d0e8b3d0b"
|
||||||
|
password: "25a8eb11e75e8d"
|
||||||
|
tlsRequired: true
|
||||||
|
# smtp:
|
||||||
|
# addr: "localhost:1025"
|
||||||
|
# user: ""
|
||||||
|
# password: ""
|
||||||
|
# tlsRequired: false
|
||||||
|
|
||||||
|
# OpenAI integration (optional)
|
||||||
|
openai:
|
||||||
|
apiKey: ""
|
||||||
|
temperature: 0.1
|
||||||
|
modelName: "gpt-4o"
|
||||||
|
|
||||||
|
# Custom domains configuration (optional)
|
||||||
|
customDomains:
|
||||||
|
enabled: false
|
||||||
|
renewalInterval: 3600
|
||||||
|
provisionInterval: 30
|
||||||
|
cnameTarget: "probo.example.com"
|
||||||
|
acme:
|
||||||
|
directory: "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
email: "admin@example.com"
|
||||||
|
keyType: "EC256"
|
||||||
|
insecureTls: false
|
||||||
|
|
||||||
|
# External OAuth2 connectors (optional)
|
||||||
|
connectors: []
|
||||||
|
# - name: "github"
|
||||||
|
# type: "oauth2"
|
||||||
|
# config:
|
||||||
|
# client-id: "github-client-id"
|
||||||
|
# client-secret: "github-client-secret"
|
||||||
|
# redirect-uri: "https://probo.example.com/api/console/v1/connectors/complete"
|
||||||
|
# auth-url: "https://github.com/login/oauth/authorize"
|
||||||
|
# token-url: "https://github.com/login/oauth/access_token"
|
||||||
|
|
||||||
|
# PostgreSQL configuration
|
||||||
|
# For production: Use external managed PostgreSQL (AWS RDS, GCP Cloud SQL, etc.)
|
||||||
|
# For testing: Enable the included PostgreSQL chart
|
||||||
|
postgresql:
|
||||||
|
# -- enabled included Postgres container for demo purposes only using cloudnative-pg
|
||||||
|
enabled: true
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
ephemeral-storage: "5Gi"
|
||||||
|
auth:
|
||||||
|
postgresUser: probod
|
||||||
|
postgresPassword: probod
|
||||||
|
database: probod
|
||||||
|
|
||||||
|
# S3 storage configuration
|
||||||
|
# For production: Use external S3 (AWS S3, GCS, etc.)
|
||||||
|
# For testing: Enable the included MinIO chart
|
||||||
|
s3:
|
||||||
|
# External S3 configuration (used when minio.enabled=false)
|
||||||
|
region: "us-east-1"
|
||||||
|
bucket: "probod"
|
||||||
|
# For AWS S3, leave endpoint empty
|
||||||
|
# For S3-compatible storage (MinIO, DigitalOcean Spaces, etc.), set the endpoint
|
||||||
|
endpoint: ""
|
||||||
|
accessKeyId: "" # REQUIRED when minio.enabled=false: S3 access key
|
||||||
|
secretAccessKey: "" # REQUIRED when minio.enabled=false: S3 secret key
|
||||||
|
|
||||||
|
# MinIO configuration
|
||||||
|
# Enable included MinIO for testing/development (NOT for production)
|
||||||
|
minio:
|
||||||
|
# -- enabled included Minio operator for s3 resource demo purposes
|
||||||
|
enabled: true
|
||||||
|
mode: standalone
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 128Mi
|
||||||
|
primary:
|
||||||
|
enabled: true
|
||||||
|
auth:
|
||||||
|
rootUser: probod
|
||||||
|
rootPassword: probod
|
||||||
|
|
||||||
|
# Headless Chrome for PDF generation
|
||||||
|
chrome:
|
||||||
|
# Deploy Chrome in the cluster
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: chromedp/headless-shell
|
||||||
|
tag: "140.0.7259.2"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
# External Chrome configuration
|
||||||
|
# Used when chrome.enabled=false
|
||||||
|
external:
|
||||||
|
addr: ""
|
||||||
Reference in New Issue
Block a user