diff --git a/_deprecated/charts/discourse/Chart.yaml b/_deprecated/charts/discourse/Chart.yaml new file mode 100644 index 0000000..ffec82a --- /dev/null +++ b/_deprecated/charts/discourse/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: discourse +description: Helm chart for deploying the Discourse application and dependencies. +type: application +version: 0.1.0 +appVersion: "3.6.0-beta0" +keywords: + - discourse + - forum + - ruby + - rails diff --git a/_deprecated/charts/discourse/README.md b/_deprecated/charts/discourse/README.md new file mode 100644 index 0000000..8c5d754 --- /dev/null +++ b/_deprecated/charts/discourse/README.md @@ -0,0 +1,277 @@ +# Discourse Helm Chart + +This chart deploys the [Discourse](https://www.discourse.org/) application together with optional PostgreSQL and Redis dependencies. It ships with opinionated defaults for both a cost-conscious staging environment and a highly-available production setup that integrates with managed AWS services. + +## Features + +- Discourse web and Sidekiq deployments based on the official `discourse/discourse:beta` image +- Optional single-instance PostgreSQL (StatefulSet) and Redis (Deployment) for staging +- External RDS and ElastiCache integration for production +- Configurable Ingress for NGINX and AWS Load Balancer Controller +- S3-based uploads configuration with separate backup bucket +- Horizontal Pod Autoscaler for production web tier +- Network policies and PodDisruptionBudgets (opt-in) + +## Repository Layout + +``` +discourse/ +├── Chart.yaml +├── README.md +├── values.yaml +└── templates/ + ├── _helpers.tpl + ├── configmap.yaml + ├── secret.yaml + ├── deployment-web.yaml + ├── deployment-sidekiq.yaml + ├── service-web.yaml + ├── ingress.yaml + ├── hpa-web.yaml + ├── serviceaccount.yaml + ├── networkpolicy.yaml + ├── pdb-*.yaml + ├── postgresql-*.yaml + └── redis-*.yaml +``` + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8+ +- AWS CLI configured with access to the target account (for S3/RDS/ElastiCache/ALB management) +- Existing ACM certificate in the target region for production ingress +- Container registry access to pull `discourse/discourse:beta` + +## Configuration + +Base settings live in `values.yaml` and are shared between environments. Key sections include: + +- `config.*`: Hostname, database, Redis, S3, and SMTP settings exposed to the web and Sidekiq pods. +- `secrets.*`: Sensitive values that are rendered into a Kubernetes Secret. **Do not commit real credentials.** +- `postgresql.*` / `redis.*`: Toggle embedded services and persistence options. +- `web.*` / `sidekiq.*`: Pod-level settings, resources, probes, and autoscaling. +- `ingress.*`: Ingress class, annotations, hosts, and TLS. +- `networkPolicy.*`: Optional traffic controls per component. +- `podDisruptionBudget.*`: Optional hardening controls. + + +## Deploying Staging (All-In-Cluster) + +1. Create (and version) copies of `values.yaml` with real secrets, or supply them at install time via `--set-file` / `--set`. +2. Ensure the target namespace exists: + + ```bash + kubectl create namespace discourse-staging + ``` + +3. Deploy the chart: + + ```bash + helm upgrade --install discourse-staging ./discourse \ + --namespace discourse-staging \ + -f discourse/values.yaml \ + -f discourse/values-staging.yaml + ``` + +4. Run database migrations once pods are healthy: + + ```bash + kubectl exec deployment/discourse-staging-web -n discourse-staging -- \ + bundle exec rake db:migrate + ``` + +5. Seed an admin account if required: + + ```bash + kubectl exec deployment/discourse-staging-web -n discourse-staging -- \ + bundle exec rake admin:create + ``` + +## Deploying Production (AWS Managed Services) + +1. Provision AWS resources: + - **RDS PostgreSQL 14+** (Multi-AZ) and note the cluster endpoint, username, and password. + - **ElastiCache Redis** (Multi-AZ) and note the primary endpoint and password if enabled. + - **S3 buckets** for uploads and backups with the desired storage classes. + - **ACM certificate** in the same region as the EKS cluster. + +2. Update `values-production.yaml` with the endpoints, bucket names, SMTP settings, and secrets. + +3. Deploy: + + ```bash + kubectl create namespace discourse-prod + + helm upgrade --install discourse-prod ./discourse \ + --namespace discourse-prod \ + -f discourse/values.yaml \ + -f discourse/values-production.yaml + ``` + +4. After deployment, run migrations and reseed admins as shown in the staging section (adjust the namespace). + +## Operations + +- **Upgrades**: Update the image tag in your values file and rerun `helm upgrade`. Always follow up with `kubectl rollout status` for both deployments. +- **Backups**: Staging relies on EBS snapshots for PostgreSQL/Redis PVCs. Production uses managed RDS/ElastiCache backups and S3 versioning. Establish recurring cross-account exports as needed. +- **Restarts**: Use `kubectl rollout restart deployment/discourse-prod-web` (and `-sidekiq`) to pick up config changes. +- **Log collection**: Stream logs via `kubectl logs -f deployment/discourse-prod-web` or forward them to CloudWatch/ELK using your preferred DaemonSet. +- **Metrics**: Integrate with Prometheus by enabling scraping annotations or sidecar exporters. Web HPA thresholds default to 65% CPU. +- **Secrets rotation**: Update the relevant entries under `secrets.*` and run `helm upgrade`. Redis/PostgreSQL pods will recycle automatically when the secret hash changes. + +## Migration Checklist + +- [ ] Confirm EKS cluster nodes provide sufficient CPU/memory (see `resources` requests). +- [ ] Validate DNS records point to the ingress controller/ALB once deployed. +- [ ] Upload site settings (`app.yml`) into environment variables or the UI post-migration. +- [ ] Reconfigure SSO providers and email once the new hostname resolves. +- [ ] Test large uploads to verify S3 credentials and bucket policies. +- [ ] Exercise backup and rollback procedures before cutover. + +## TLS/Certificate Configuration + +### Using cert-manager + +If you have cert-manager installed in your cluster, you can automatically provision TLS certificates: + +```yaml +ingress: + enabled: true + className: nginx + hosts: + - host: forum.example.com + paths: + - path: / + pathType: Prefix + certManager: + enabled: true + issuerName: letsencrypt-prod + issuerKind: ClusterIssuer + # secretName: forum-tls # Optional, defaults to -discourse-tls + duration: 2160h # 90 days + renewBefore: 720h # 30 days +``` + +### Using existing TLS secret + +If you already have a TLS secret: + +```yaml +ingress: + enabled: true + tls: + - secretName: existing-tls-secret + hosts: + - forum.example.com +``` + +## Environment Variables Configuration + +The chart supports flexible environment variable configuration with multiple sourcing options: + +### Variable Types + +1. **kv (Key-Value)**: Hardcoded values directly in values.yaml +2. **parameterStore**: AWS Parameter Store via External Secrets Operator +3. **secret**: Reference to existing Kubernetes Secret +4. **configmapRef**: Reference to existing ConfigMap + +### Examples + +```yaml +externalSecrets: + clusterSecretStoreName: aws-parameter-store + refreshInterval: 1m + +env: + # Hardcoded value + DISCOURSE_SMTP_DOMAIN: + type: kv + value: example.com + + # From AWS Parameter Store + DISCOURSE_SECRET_KEY_BASE: + type: parameterStore + name: secret-key-base + parameter_name: /discourse/prod/secret-key-base + + # From existing Kubernetes Secret + API_KEY: + type: secret + name: discourse-api-keys + key: api-key + + # From existing ConfigMap + CUSTOM_CONFIG: + type: configmapRef + name: discourse-custom-config + key: custom-value +``` + +### Prerequisites for parameterStore type + +- External Secrets Operator must be installed +- ClusterSecretStore must be configured +- IAM permissions for accessing Parameter Store + +## IRSA Configuration for S3 Access + +Instead of using static AWS credentials, you can configure IAM Roles for Service Accounts (IRSA) to grant Discourse pods access to S3 buckets. + +### Prerequisites + +1. Create an IAM role with appropriate S3 permissions +2. Configure the trust policy to allow your EKS service account to assume the role +3. Ensure your EKS cluster has an OIDC provider configured + +### Configuration + +Add the IAM role ARN to your values file: + +```yaml +serviceAccount: + create: true + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME + +config: + discourseS3Bucket: your-bucket-name + discourseS3BackupBucket: your-bucket-name # Can be the same bucket with different prefix + discourseS3UploadsPrefix: uploads/ + discourseS3BackupsPrefix: backups/ + +# When using IRSA, S3 credentials are not required +secrets: + s3AccessKeyId: "" + s3SecretAccessKey: "" +``` + +### Example for Staging + +```yaml +serviceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::068992353948:role/eks-forum-staging-discourse-s3 + +config: + discourseS3Bucket: forum-staging.sky.money + discourseS3BackupBucket: forum-staging.sky.money + discourseS3UploadsPrefix: uploads/ + discourseS3BackupsPrefix: backups/ +``` + +## Development Notes + +- The rendered manifests assume Kubernetes DNS is available (`kube-dns` / `CoreDNS`). +- When using IRSA for S3 access, the `secrets.s3AccessKeyId` and `secrets.s3SecretAccessKey` values can be left empty. +- Enable `networkPolicy.*` and `podDisruptionBudget.*` only after verifying HPA and replica counts satisfy availability goals. + +## Removing the Stack + +```bash +helm uninstall discourse-staging -n discourse-staging +kubectl delete namespace discourse-staging +``` + +Repeat for production after ensuring traffic has already switched off the cluster. diff --git a/_deprecated/charts/discourse/helm-values-staging.yaml b/_deprecated/charts/discourse/helm-values-staging.yaml new file mode 100644 index 0000000..d04e622 --- /dev/null +++ b/_deprecated/charts/discourse/helm-values-staging.yaml @@ -0,0 +1,303 @@ +# Parent Chart Values for Forum Staging +# Usage: helm install forum-staging . -f helm-values-staging.yaml -n forum --create-namespace + +# Certificate Configuration (managed by parent chart) +certificate: + enabled: true + name: forum-staging-tls + dnsNames: + - forum-staging.sky.money + duration: 2160h0m0s + renewBefore: 720h0m0s + secretName: forum-staging-tls-secret + issuer: + kind: ClusterIssuer + name: cloudflare + +# Discourse subchart values +discourse: + # Global Configuration + global: + storageClass: gp3 + + image: + registry: docker.io + repository: bitnami/discourse + pullPolicy: IfNotPresent + +# Discourse Configuration +discourse: + host: forum-staging.sky.money + siteName: "MakerDAO Forum Staging" + + # Skip install wizard - we'll restore from backup + skipInstall: false + + # Username/password for initial admin (staging only) + username: admin + password: ForumAdmin2024Staging + email: team@techops.services + + # Plugins from app.yaml + plugins: + - https://github.com/discourse/docker_manager.git + - https://github.com/makerdao/discourse-docs.git + - https://github.com/makerdao/discourse-docs-card-filter.git + - https://github.com/hernandoagf/extended-api-scopes.git + - https://github.com/unfoldingWord-dev/discourse-mermaid.git + + persistPlugins: true + compatiblePlugins: true + + # Extra environment variables from app.yaml + extraEnvVars: + - name: DISCOURSE_VERSION + value: "tests-passed" + - name: LANG + value: "en_US.UTF-8" + - name: UNICORN_WORKERS + value: "4" + - name: DISCOURSE_DEVELOPER_EMAILS + value: "team@techops.services" + - name: DISCOURSE_ONION + value: "" + - name: DISCOURSE_ENABLE_MINI_PROFILER + value: "true" + - name: DISCOURSE_VERBOSE_LOCALIZATION + value: "true" + - name: DISCOURSE_COMPRESS_ANON_CACHE + value: "false" + - name: DB_DEFAULT_TEXT_SEARCH_CONFIG + value: "pg_catalog.english" + # S3 uploads and backups via IRSA (no static keys) + - name: DISCOURSE_USE_S3 + value: "true" + - name: DISCOURSE_S3_REGION + value: "us-east-1" + - name: DISCOURSE_S3_BUCKET + value: "REPLACE_ME_UPLOAD_BUCKET" + - name: DISCOURSE_BACKUP_LOCATION + value: "s3" + - name: DISCOURSE_S3_BACKUP_BUCKET + value: "REPLACE_ME_BACKUP_BUCKET" + - name: DISCOURSE_S3_ACL + value: "private" + - name: DISCOURSE_S3_ENDPOINT + value: "" + - name: AWS_REGION + value: "us-east-1" + # Internal database settings (using subcharts) + - name: DISCOURSE_DATABASE_HOST + value: "forum-staging-postgresql" + - name: DISCOURSE_DATABASE_PORT + value: "5432" + - name: DISCOURSE_DATABASE_NAME + value: "discourse" + - name: DISCOURSE_DATABASE_USERNAME + value: "discourse" + - name: DISCOURSE_DATABASE_PASSWORD + value: "ForumStaging2024DB" + - name: DISCOURSE_REDIS_HOST + value: "forum-staging-redis-master" + - name: DISCOURSE_REDIS_PORT + value: "6379" + # Allow empty Redis password for staging + - name: ALLOW_EMPTY_PASSWORD + value: "yes" + + # SMTP Configuration from app.yaml + smtp: + enabled: true + host: email-smtp.us-east-1.amazonaws.com + port: 587 + user: AKIARAECDY2ON5PL2AEK + password: "BDC8aj/Y1I/gvOEkVnow/t/N1HzQQ5E+EwS6+fWMqZdM" + tls: true + auth: plain + + resources: + requests: + memory: 2Gi + cpu: 500m + limits: + memory: 4Gi + cpu: 2 + + # IRSA service account for Discourse + serviceAccount: + create: true + name: forum-staging-discourse + automountServiceAccountToken: true + annotations: + eks.amazonaws.com/role-arn: "REPLACE_ME_IRSA_ROLE_ARN" + # Ensure pod receives token for IRSA + automountServiceAccountToken: true + +# Sidekiq Configuration +sidekiq: + enabled: true + + # Extra environment for sidekiq + extraEnvVars: + - name: DISCOURSE_SIDEKIQ_WORKERS + value: "2" + # S3 uploads and backups via IRSA (match app env) + - name: DISCOURSE_USE_S3 + value: "true" + - name: DISCOURSE_S3_REGION + value: "us-east-1" + - name: DISCOURSE_S3_BUCKET + value: "REPLACE_ME_UPLOAD_BUCKET" + - name: DISCOURSE_BACKUP_LOCATION + value: "s3" + - name: DISCOURSE_S3_BACKUP_BUCKET + value: "REPLACE_ME_BACKUP_BUCKET" + - name: DISCOURSE_S3_ACL + value: "private" + - name: DISCOURSE_S3_ENDPOINT + value: "" + - name: AWS_REGION + value: "us-east-1" + + resources: + requests: + memory: 1Gi + cpu: 250m + limits: + memory: 2Gi + cpu: 1 + +# PostgreSQL Configuration (Internal subchart) +postgresql: + enabled: true + auth: + username: discourse + password: ForumStaging2024DB + database: discourse + postgresPassword: PostgresAdmin2024Staging + primary: + persistence: + enabled: true + size: 20Gi + storageClass: gp3 + resources: + requests: + memory: 1Gi + cpu: 250m + limits: + memory: 2Gi + cpu: 500m + +# Redis Configuration (Internal subchart) +redis: + enabled: true + auth: + enabled: false + master: + persistence: + enabled: true + size: 5Gi + storageClass: gp3 + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 512Mi + cpu: 250m + +# Persistence Configuration with EBS GP3 +persistence: + enabled: true + storageClass: gp3 + accessModes: + - ReadWriteOnce + size: 20Gi + +# Service Configuration +service: + type: ClusterIP + ports: + http: 80 + https: 443 + +# Ingress Configuration (following ArgoCD pattern) +ingress: + enabled: true + ingressClassName: traefik + hostname: forum-staging.sky.money + pathType: Prefix + path: / + annotations: + external-dns.alpha.kubernetes.io/cloudflare-proxied: "true" + extraTls: + - hosts: + - forum-staging.sky.money + secretName: forum-staging-tls-secret + +# Autoscaling (disabled for staging) +autoscaling: + enabled: false + +# Replicas (single for staging) +replicaCount: 1 + +# Disable PodDisruptionBudget for single pod +podDisruptionBudget: + enabled: false + +# Node affinity +affinity: {} + +# Tolerations +tolerations: [] + +# Health Check Probes - Extended for slow startup +startupProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 30 # 60 + (30 * 30) = 960 seconds (16 minutes) max startup time + successThreshold: 1 + +livenessProbe: + enabled: true + initialDelaySeconds: 300 # Start after 5 minutes + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + +readinessProbe: + enabled: true + initialDelaySeconds: 120 # Start checking after 2 minutes + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 20 # 120 + (15 * 20) = 420 seconds (7 minutes) + successThreshold: 1 + +# Security Context +containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + +podSecurityContext: + enabled: true + fsGroup: 1001 + +# Certificate subchart configuration +forum-certificate: + certificate: + enabled: true + name: forum-staging-tls + namespace: forum + dnsNames: + - forum-staging.sky.money + duration: 2160h0m0s + renewBefore: 720h0m0s + secretName: forum-staging-tls-secret + issuer: + kind: ClusterIssuer + name: cloudflare diff --git a/_deprecated/charts/discourse/templates/_helpers.tpl b/_deprecated/charts/discourse/templates/_helpers.tpl new file mode 100644 index 0000000..98ab9a1 --- /dev/null +++ b/_deprecated/charts/discourse/templates/_helpers.tpl @@ -0,0 +1,83 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "discourse.name" -}} +{{- default .Chart.Name .Values.global.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "discourse.fullname" -}} +{{- if .Values.global.fullnameOverride -}} +{{- .Values.global.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.global.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "discourse.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" -}} +{{- end -}} + +{{/* +Common labels. +*/}} +{{- define "discourse.labels" -}} +helm.sh/chart: {{ include "discourse.chart" . }} +app.kubernetes.io/name: {{ include "discourse.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end }} +{{- end -}} + +{{/* +Selector labels. +*/}} +{{- define "discourse.selectorLabels" -}} +app.kubernetes.io/name: {{ include "discourse.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Service account name. +*/}} +{{- define "discourse.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} +{{- if .Values.serviceAccount.name -}} +{{- .Values.serviceAccount.name -}} +{{- else -}} +{{- include "discourse.fullname" . -}} +{{- end -}} +{{- else -}} +{{- default "default" .Values.serviceAccount.name -}} +{{- end -}} +{{- end -}} + +{{/* +PostgreSQL resource names. +*/}} +{{- define "discourse.postgresql.fullname" -}} +{{- printf "%s-postgresql" (include "discourse.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "discourse.postgresql.serviceName" -}} +{{- include "discourse.postgresql.fullname" . -}} +{{- end -}} + +{{/* +Redis resource names. +*/}} +{{- define "discourse.redis.fullname" -}} +{{- printf "%s-redis" (include "discourse.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "discourse.redis.serviceName" -}} +{{- include "discourse.redis.fullname" . -}} +{{- end -}} diff --git a/_deprecated/charts/discourse/templates/certificate.yaml b/_deprecated/charts/discourse/templates/certificate.yaml new file mode 100644 index 0000000..d466f50 --- /dev/null +++ b/_deprecated/charts/discourse/templates/certificate.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.ingress.enabled .Values.ingress.certManager .Values.ingress.certManager.enabled }} +{{- $fullName := include "discourse.fullname" . -}} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $fullName }} + labels: + {{- include "discourse.labels" . | nindent 4 }} +spec: + secretName: {{ .Values.ingress.certManager.secretName | default (printf "%s-tls" $fullName) }} + duration: {{ .Values.ingress.certManager.duration | default "2160h" }} + renewBefore: {{ .Values.ingress.certManager.renewBefore | default "720h" }} + issuerRef: + name: {{ required "ingress.certManager.issuerName is required when certManager is enabled" .Values.ingress.certManager.issuerName }} + kind: {{ .Values.ingress.certManager.issuerKind | default "ClusterIssuer" }} + dnsNames: + {{- range .Values.ingress.hosts }} + - {{ .host | quote }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/configmap.yaml b/_deprecated/charts/discourse/templates/configmap.yaml new file mode 100644 index 0000000..d901b56 --- /dev/null +++ b/_deprecated/charts/discourse/templates/configmap.yaml @@ -0,0 +1,51 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "discourse.fullname" . }}-config + labels: + {{- include "discourse.labels" . | nindent 4 }} +data: + DISCOURSE_HOSTNAME: {{ required "config.discourseHostname must be provided" .Values.config.discourseHostname | quote }} + DISCOURSE_DB_NAME: {{ .Values.config.discourseDbName | quote }} + DISCOURSE_DB_USERNAME: {{ .Values.config.discourseDbUsername | quote }} + DISCOURSE_DB_PORT: {{ printf "%d" (int .Values.config.discourseDbPort) | quote }} + DISCOURSE_REDIS_PORT: {{ printf "%d" (int .Values.config.discourseRedisPort) | quote }} + DISCOURSE_ENABLE_CORS: {{ ternary "true" "false" .Values.config.discourseEnableCors | quote }} + DISCOURSE_CORS_ORIGIN: {{ .Values.config.discourseCorsOrigin | quote }} + DISCOURSE_SERVE_STATIC_ASSETS: {{ ternary "true" "false" .Values.config.discourseServeStaticAssets | quote }} + DISCOURSE_S3_ENABLED: {{ ternary "true" "false" .Values.config.discourseS3Enabled | quote }} + DISCOURSE_USE_S3: {{ ternary "true" "false" .Values.config.discourseUseS3 | quote }} +{{- if .Values.config.discourseUseS3 }} + DISCOURSE_S3_REGION: {{ .Values.config.discourseS3Region | quote }} + DISCOURSE_S3_BUCKET: {{ .Values.config.discourseS3Bucket | quote }} + DISCOURSE_S3_UPLOAD_BUCKET: {{ .Values.config.discourseS3Bucket | quote }} + DISCOURSE_S3_BACKUP_BUCKET: {{ .Values.config.discourseS3BackupBucket | quote }} + DISCOURSE_S3_USE_IAM_PROFILE: {{ ternary "true" "false" .Values.config.discourseS3UseIamProfile | quote }} +{{- if .Values.config.discourseS3Endpoint }} + DISCOURSE_S3_ENDPOINT: {{ .Values.config.discourseS3Endpoint | quote }} +{{- end }} +{{- if .Values.config.discourseS3UploadsPrefix }} + DISCOURSE_S3_UPLOAD_BUCKET_PREFIX: {{ .Values.config.discourseS3UploadsPrefix | quote }} +{{- end }} +{{- if .Values.config.discourseS3BackupsPrefix }} + DISCOURSE_S3_BACKUP_BUCKET_PREFIX: {{ .Values.config.discourseS3BackupsPrefix | quote }} +{{- end }} +{{- end }} + DISCOURSE_DEVELOPER_EMAILS: {{ .Values.config.discourseDeveloperEmails | quote }} + DISCOURSE_MAXMIND_LICENSE_KEY: {{ default "" .Values.config.discourseMaxMindLicenseKey | quote }} +{{- if .Values.postgresql.enabled }} + DISCOURSE_DB_HOST: {{ include "discourse.postgresql.serviceName" . | quote }} +{{- else }} + DISCOURSE_DB_HOST: {{ default "" .Values.config.discourseDbHost | quote }} +{{- end }} +{{- if .Values.redis.enabled }} + DISCOURSE_REDIS_HOST: {{ include "discourse.redis.serviceName" . | quote }} +{{- else }} + DISCOURSE_REDIS_HOST: {{ default "" .Values.config.discourseRedisHost | quote }} +{{- end }} + DISCOURSE_ENABLE_S3_UPLOADS: {{ ternary "true" "false" .Values.config.discourseS3Enabled | quote }} + SMTP_ADDRESS: {{ .Values.config.smtpAddress | quote }} + SMTP_PORT: {{ printf "%d" (int .Values.config.smtpPort) | quote }} + SMTP_USER_NAME: {{ .Values.config.smtpUserName | quote }} + SMTP_DOMAIN: {{ .Values.config.smtpDomain | quote }} + SMTP_ENABLE_START_TLS: {{ ternary "true" "false" .Values.config.smtpEnableStartTls | quote }} diff --git a/_deprecated/charts/discourse/templates/deployment-sidekiq.yaml b/_deprecated/charts/discourse/templates/deployment-sidekiq.yaml new file mode 100644 index 0000000..397b016 --- /dev/null +++ b/_deprecated/charts/discourse/templates/deployment-sidekiq.yaml @@ -0,0 +1,102 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "discourse.fullname" . }}-sidekiq + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: sidekiq +spec: + replicas: {{ .Values.sidekiq.replicaCount }} + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: sidekiq + template: + metadata: + labels: + {{- include "discourse.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: sidekiq + {{- with .Values.sidekiq.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "discourse.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: sidekiq + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.sidekiq.command }} + command: + {{- toYaml . | nindent 12 }} + {{- end }} + envFrom: + - configMapRef: + name: {{ include "discourse.fullname" . }}-config + - secretRef: + name: {{ include "discourse.fullname" . }}-secrets + {{- with .Values.sidekiq.extraEnvFrom }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + {{- with .Values.sidekiq.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- range $k, $v := .Values.env }} + - name: {{ $k | quote }} + {{- if eq $v.type "kv" }} + value: {{ $v.value | quote }} + {{- else if eq $v.type "parameterStore" }} + valueFrom: + secretKeyRef: + name: "{{ include "discourse.fullname" $ }}-{{ $v.name }}" + key: "{{ include "discourse.fullname" $ }}-{{ $v.name }}" + {{- else if eq $v.type "configmapRef" }} + valueFrom: + configMapKeyRef: + name: {{ $v.name | quote }} + key: {{ $v.key | quote }} + {{- else if eq $v.type "secret" }} + valueFrom: + secretKeyRef: + name: {{ $v.name | quote }} + key: {{ $v.key | quote }} + {{- end }} + {{- end }} + {{- with .Values.sidekiq.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: shared-tmp + mountPath: /shared/tmp + - name: shared-state + mountPath: /shared/state + resources: + {{- toYaml .Values.sidekiq.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- with .Values.sidekiq.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.sidekiq.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.sidekiq.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: shared-tmp + emptyDir: {} + - name: shared-state + emptyDir: {} diff --git a/_deprecated/charts/discourse/templates/deployment-web.yaml b/_deprecated/charts/discourse/templates/deployment-web.yaml new file mode 100644 index 0000000..df5a574 --- /dev/null +++ b/_deprecated/charts/discourse/templates/deployment-web.yaml @@ -0,0 +1,122 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "discourse.fullname" . }}-web + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: web +spec: + replicas: {{ .Values.web.replicaCount }} + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: web + template: + metadata: + labels: + {{- include "discourse.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: web + {{- with .Values.web.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "discourse.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: web + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.web.command }} + command: + {{- toYaml . | nindent 12 }} + {{- end }} + envFrom: + - configMapRef: + name: {{ include "discourse.fullname" . }}-config + - secretRef: + name: {{ include "discourse.fullname" . }}-secrets + {{- with .Values.web.extraEnvFrom }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + {{- with .Values.web.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- range $k, $v := .Values.env }} + - name: {{ $k | quote }} + {{- if eq $v.type "kv" }} + value: {{ $v.value | quote }} + {{- else if eq $v.type "parameterStore" }} + valueFrom: + secretKeyRef: + name: "{{ include "discourse.fullname" $ }}-{{ $v.name }}" + key: "{{ include "discourse.fullname" $ }}-{{ $v.name }}" + {{- else if eq $v.type "configmapRef" }} + valueFrom: + configMapKeyRef: + name: {{ $v.name | quote }} + key: {{ $v.key | quote }} + {{- else if eq $v.type "secret" }} + valueFrom: + secretKeyRef: + name: {{ $v.name | quote }} + key: {{ $v.key | quote }} + {{- end }} + {{- end }} + {{- with .Values.web.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 3000 + protocol: TCP + volumeMounts: + - name: shared-tmp + mountPath: /shared/tmp + - name: shared-state + mountPath: /shared/state + {{- if and .Values.web.livenessProbe.enabled .Values.web.livenessProbe.httpGet.path }} + livenessProbe: + httpGet: + path: {{ .Values.web.livenessProbe.httpGet.path }} + port: {{ .Values.web.livenessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.web.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.web.livenessProbe.periodSeconds }} + {{- end }} + {{- if and .Values.web.readinessProbe.enabled .Values.web.readinessProbe.httpGet.path }} + readinessProbe: + httpGet: + path: {{ .Values.web.readinessProbe.httpGet.path }} + port: {{ .Values.web.readinessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.web.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.web.readinessProbe.periodSeconds }} + {{- end }} + resources: + {{- toYaml .Values.web.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- with .Values.web.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: shared-tmp + emptyDir: {} + - name: shared-state + emptyDir: {} diff --git a/_deprecated/charts/discourse/templates/externalSecret.yaml b/_deprecated/charts/discourse/templates/externalSecret.yaml new file mode 100644 index 0000000..05e0ce4 --- /dev/null +++ b/_deprecated/charts/discourse/templates/externalSecret.yaml @@ -0,0 +1,22 @@ +{{- $fullName := include "discourse.fullname" . -}} +{{- $externalSecrets := default dict .Values.externalSecrets }} +{{- range $k, $v := .Values.env }} +{{- if eq $v.type "parameterStore" }} +--- +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: "{{ $fullName }}-{{ $v.name }}" + labels: + {{- include "discourse.labels" $ | nindent 4 }} +spec: + refreshInterval: {{ $externalSecrets.refreshInterval | default "1m" }} + secretStoreRef: + kind: ClusterSecretStore + name: {{ required "externalSecrets.clusterSecretStoreName is required when using parameterStore env type" $externalSecrets.clusterSecretStoreName }} + data: + - secretKey: "{{ $fullName }}-{{ $v.name }}" + remoteRef: + key: {{ $v.parameter_name }} +{{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/hpa-web.yaml b/_deprecated/charts/discourse/templates/hpa-web.yaml new file mode 100644 index 0000000..976e455 --- /dev/null +++ b/_deprecated/charts/discourse/templates/hpa-web.yaml @@ -0,0 +1,31 @@ +{{- if .Values.web.hpa.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "discourse.fullname" . }}-web + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: web +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "discourse.fullname" . }}-web + minReplicas: {{ .Values.web.hpa.minReplicas }} + maxReplicas: {{ .Values.web.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.web.hpa.targetCPUUtilizationPercentage }} + {{- if .Values.web.hpa.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.web.hpa.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/ingress.yaml b/_deprecated/charts/discourse/templates/ingress.yaml new file mode 100644 index 0000000..019c5b5 --- /dev/null +++ b/_deprecated/charts/discourse/templates/ingress.yaml @@ -0,0 +1,35 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "discourse.fullname" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "discourse.fullname" $ }}-web + port: + name: http + {{- end }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- toYaml .Values.ingress.tls | nindent 4 }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/networkpolicy.yaml b/_deprecated/charts/discourse/templates/networkpolicy.yaml new file mode 100644 index 0000000..8e1cde5 --- /dev/null +++ b/_deprecated/charts/discourse/templates/networkpolicy.yaml @@ -0,0 +1,166 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "discourse.fullname" . }}-web + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: web +spec: + podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: web + policyTypes: + - Ingress + - Egress + ingress: + - from: + - {} + ports: + - port: 3000 + protocol: TCP + egress: + - to: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: postgresql + ports: + - port: 5432 + protocol: TCP + - to: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: redis + ports: + - port: 6379 + protocol: TCP + - to: + - namespaceSelector: {} + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - port: 80 + protocol: TCP + - port: 443 + protocol: TCP + - port: 587 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "discourse.fullname" . }}-sidekiq + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: sidekiq +spec: + podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: sidekiq + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: postgresql + ports: + - port: 5432 + protocol: TCP + - to: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: redis + ports: + - port: 6379 + protocol: TCP + - to: + - namespaceSelector: {} + ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - port: 80 + protocol: TCP + - port: 443 + protocol: TCP + - port: 587 + protocol: TCP +--- +{{- if .Values.postgresql.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "discourse.fullname" . }}-postgresql + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: postgresql +spec: + podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: postgresql + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: web + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: sidekiq + ports: + - port: 5432 + protocol: TCP +--- +{{- end }} +{{- if .Values.redis.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "discourse.fullname" . }}-redis + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: redis +spec: + podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: redis + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: web + - podSelector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 14 }} + app.kubernetes.io/component: sidekiq + ports: + - port: 6379 + protocol: TCP +{{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/pdb-sidekiq.yaml b/_deprecated/charts/discourse/templates/pdb-sidekiq.yaml new file mode 100644 index 0000000..c36af2e --- /dev/null +++ b/_deprecated/charts/discourse/templates/pdb-sidekiq.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.sidekiq.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "discourse.fullname" . }}-sidekiq + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: sidekiq +spec: + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: sidekiq + {{- if .Values.podDisruptionBudget.sidekiq.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.sidekiq.minAvailable }} + {{- else if .Values.podDisruptionBudget.sidekiq.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.sidekiq.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/pdb-web.yaml b/_deprecated/charts/discourse/templates/pdb-web.yaml new file mode 100644 index 0000000..78e034e --- /dev/null +++ b/_deprecated/charts/discourse/templates/pdb-web.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.web.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "discourse.fullname" . }}-web + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: web +spec: + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: web + {{- if .Values.podDisruptionBudget.web.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.web.minAvailable }} + {{- else if .Values.podDisruptionBudget.web.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.web.maxUnavailable }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/postgresql-pvc.yaml b/_deprecated/charts/discourse/templates/postgresql-pvc.yaml new file mode 100644 index 0000000..f431adf --- /dev/null +++ b/_deprecated/charts/discourse/templates/postgresql-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.postgresql.enabled .Values.postgresql.persistence.enabled (not .Values.postgresql.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "discourse.postgresql.fullname" . }}-data + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: postgresql +spec: + accessModes: + {{- toYaml .Values.postgresql.persistence.accessModes | nindent 4 }} + resources: + requests: + storage: {{ .Values.postgresql.persistence.size }} + {{- if .Values.postgresql.persistence.storageClass }} + storageClassName: {{ .Values.postgresql.persistence.storageClass }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/postgresql-service.yaml b/_deprecated/charts/discourse/templates/postgresql-service.yaml new file mode 100644 index 0000000..cffe291 --- /dev/null +++ b/_deprecated/charts/discourse/templates/postgresql-service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.postgresql.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "discourse.postgresql.serviceName" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: postgresql +spec: + clusterIP: None + selector: + {{- include "discourse.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: postgresql + ports: + - name: postgres + port: {{ .Values.postgresql.servicePort }} + targetPort: postgres + protocol: TCP +{{- end }} diff --git a/_deprecated/charts/discourse/templates/postgresql-statefulset.yaml b/_deprecated/charts/discourse/templates/postgresql-statefulset.yaml new file mode 100644 index 0000000..1ff2ea8 --- /dev/null +++ b/_deprecated/charts/discourse/templates/postgresql-statefulset.yaml @@ -0,0 +1,90 @@ +{{- if .Values.postgresql.enabled }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "discourse.postgresql.fullname" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: postgresql +spec: + serviceName: {{ include "discourse.postgresql.serviceName" . }} + replicas: {{ .Values.postgresql.replicaCount }} + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: postgresql + template: + metadata: + labels: + {{- include "discourse.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: postgresql + {{- with .Values.postgresql.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.postgresql.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: postgresql + image: "{{ .Values.postgresql.image.repository }}:{{ .Values.postgresql.image.tag }}" + imagePullPolicy: {{ .Values.postgresql.image.pullPolicy }} + env: + - name: POSTGRES_DB + value: {{ .Values.config.discourseDbName | quote }} + - name: POSTGRES_USER + value: {{ .Values.config.discourseDbUsername | quote }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "discourse.fullname" . }}-secrets + key: DISCOURSE_DB_PASSWORD + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + {{- with .Values.postgresql.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.postgresql.parameters }} + args: + {{- range $key, $value := . }} + - "-c" + - "{{ $key }}={{ $value }}" + {{- end }} + {{- end }} + ports: + - name: postgres + containerPort: 5432 + volumeMounts: + - name: data + mountPath: /var/lib/postgresql/data + resources: + {{- toYaml .Values.postgresql.resources | nindent 12 }} + {{- with .Values.postgresql.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.postgresql.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.postgresql.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.postgresql.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.persistence.enabled }} + volumes: + - name: data + persistentVolumeClaim: + claimName: {{ default (printf "%s-data" (include "discourse.postgresql.fullname" .)) .Values.postgresql.persistence.existingClaim }} + {{- else }} + volumes: + - name: data + emptyDir: {} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/redis-deployment.yaml b/_deprecated/charts/discourse/templates/redis-deployment.yaml new file mode 100644 index 0000000..98e97a4 --- /dev/null +++ b/_deprecated/charts/discourse/templates/redis-deployment.yaml @@ -0,0 +1,80 @@ +{{- if .Values.redis.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "discourse.redis.fullname" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: redis +spec: + replicas: 1 + selector: + matchLabels: + {{- include "discourse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: redis + template: + metadata: + labels: + {{- include "discourse.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: redis + {{- with .Values.redis.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.redis.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: redis + image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}" + imagePullPolicy: {{ .Values.redis.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + set -e + CMD="redis-server --appendonly yes --save 900 1 --save 300 10 --save 60 10000" + if [ -n "${REDIS_PASSWORD:-}" ]; then + CMD="$CMD --requirepass ${REDIS_PASSWORD}" + fi + exec ${CMD} + env: + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "discourse.fullname" . }}-secrets + key: DISCOURSE_REDIS_PASSWORD + {{- with .Values.redis.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: redis + containerPort: 6379 + volumeMounts: + - name: redis-data + mountPath: /data + resources: + {{- toYaml .Values.redis.resources | nindent 12 }} + {{- with .Values.redis.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: redis-data + persistentVolumeClaim: + claimName: {{ default (printf "%s-data" (include "discourse.redis.fullname" .)) .Values.redis.persistence.existingClaim }} + {{- with .Values.redis.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.redis.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.redis.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/redis-pvc.yaml b/_deprecated/charts/discourse/templates/redis-pvc.yaml new file mode 100644 index 0000000..573f74d --- /dev/null +++ b/_deprecated/charts/discourse/templates/redis-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.redis.enabled .Values.redis.persistence.enabled (not .Values.redis.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "discourse.redis.fullname" . }}-data + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: redis +spec: + accessModes: + {{- toYaml .Values.redis.persistence.accessModes | nindent 4 }} + resources: + requests: + storage: {{ .Values.redis.persistence.size }} + {{- if .Values.redis.persistence.storageClass }} + storageClassName: {{ .Values.redis.persistence.storageClass }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/templates/redis-service.yaml b/_deprecated/charts/discourse/templates/redis-service.yaml new file mode 100644 index 0000000..e080ad0 --- /dev/null +++ b/_deprecated/charts/discourse/templates/redis-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.redis.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "discourse.redis.serviceName" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: redis +spec: + selector: + {{- include "discourse.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: redis + ports: + - name: redis + port: {{ .Values.redis.servicePort }} + targetPort: redis + protocol: TCP +{{- end }} diff --git a/_deprecated/charts/discourse/templates/secret.yaml b/_deprecated/charts/discourse/templates/secret.yaml new file mode 100644 index 0000000..c979040 --- /dev/null +++ b/_deprecated/charts/discourse/templates/secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "discourse.fullname" . }}-secrets + labels: + {{- include "discourse.labels" . | nindent 4 }} +type: Opaque +data: + DISCOURSE_DB_PASSWORD: {{ required "secrets.dbPassword must be provided" .Values.secrets.dbPassword | b64enc | quote }} + DISCOURSE_REDIS_PASSWORD: {{ default "" .Values.secrets.redisPassword | b64enc | quote }} +{{- if .Values.secrets.s3AccessKeyId }} + DISCOURSE_S3_ACCESS_KEY_ID: {{ .Values.secrets.s3AccessKeyId | b64enc | quote }} +{{- end }} +{{- if .Values.secrets.s3SecretAccessKey }} + DISCOURSE_S3_SECRET_ACCESS_KEY: {{ .Values.secrets.s3SecretAccessKey | b64enc | quote }} +{{- end }} + SMTP_PASSWORD: {{ default "" .Values.secrets.smtpPassword | b64enc | quote }} diff --git a/_deprecated/charts/discourse/templates/service-web.yaml b/_deprecated/charts/discourse/templates/service-web.yaml new file mode 100644 index 0000000..afacb3d --- /dev/null +++ b/_deprecated/charts/discourse/templates/service-web.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "discourse.fullname" . }}-web + labels: + {{- include "discourse.labels" . | nindent 4 }} + app.kubernetes.io/component: web + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + selector: + {{- include "discourse.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: web + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: {{ default "http" .Values.service.targetPort }} + protocol: TCP diff --git a/_deprecated/charts/discourse/templates/serviceaccount.yaml b/_deprecated/charts/discourse/templates/serviceaccount.yaml new file mode 100644 index 0000000..9b98acb --- /dev/null +++ b/_deprecated/charts/discourse/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "discourse.serviceAccountName" . }} + labels: + {{- include "discourse.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/_deprecated/charts/discourse/values-staging.yaml b/_deprecated/charts/discourse/values-staging.yaml new file mode 100644 index 0000000..4c691aa --- /dev/null +++ b/_deprecated/charts/discourse/values-staging.yaml @@ -0,0 +1,290 @@ +# Staging environment configuration for Discourse +# Migrated from Bitnami Discourse Helm chart +# Uses official discourse/discourse:beta image with embedded PostgreSQL and Redis + +# Image Configuration (official upstream, not Bitnami) +image: + repository: discourse/discourse + tag: latest + pullPolicy: IfNotPresent + +# Service Account with IRSA for S3 access +serviceAccount: + create: true + name: forum-staging-discourse + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::068992353948:role/eks-forum-staging-discourse-s3 + +# Pod Security Context (run as root to allow chown) +podSecurityContext: + runAsUser: 0 # root + runAsGroup: 0 # root + fsGroup: 1000 # ensure projected IRSA token readable by discourse user + fsGroupChangePolicy: OnRootMismatch + +# Container Security Context (allow running as root) +securityContext: + allowPrivilegeEscalation: true + readOnlyRootFilesystem: false + capabilities: + add: + - CHOWN + drop: [] + +# Discourse Configuration +config: + discourseHostname: forum-staging.sky.money + discourseDbHost: "" # Will use embedded PostgreSQL + discourseDbName: discourse + discourseDbUsername: discourse + discourseDbPort: 5432 + discourseRedisHost: "" # Will use embedded Redis + discourseRedisPort: 6379 + discourseEnableCors: true + discourseCorsOrigin: "*" + discourseServeStaticAssets: false + + # S3 Configuration (IRSA-based, no credentials) + discourseS3Enabled: true + discourseUseS3: true + discourseS3Region: us-east-2 + discourseS3Bucket: forum-staging.sky.money + discourseS3BackupBucket: forum-staging.sky.money + discourseS3UploadsPrefix: uploads/ + discourseS3BackupsPrefix: backups/ + discourseS3UseIamProfile: true + discourseS3Endpoint: "" + + # Admin Configuration + discourseDeveloperEmails: team@techops.services + discourseMaxMindLicenseKey: "" + + # SMTP Configuration (from Bitnami values) + smtpAddress: email-smtp.us-east-1.amazonaws.com + smtpPort: 587 + smtpUserName: AKIARAECDY2ON5PL2AEK + smtpDomain: sky.money + smtpEnableStartTls: true + +# Secrets (no S3 credentials needed with IRSA) +secrets: + dbPassword: "ForumStaging2024DB" + redisPassword: "" # Redis without auth for staging + s3AccessKeyId: "" + s3SecretAccessKey: "" + smtpPassword: "BDC8aj/Y1I/gvOEkVnow/t/N1HzQQ5E+EwS6+fWMqZdM" + +# Additional environment variables via flexible env pattern +env: + DISCOURSE_VERSION: + type: kv + value: "tests-passed" + LANG: + type: kv + value: "en_US.UTF-8" + UNICORN_WORKERS: + type: kv + value: "4" + DISCOURSE_ENABLE_MINI_PROFILER: + type: kv + value: "true" + DISCOURSE_VERBOSE_LOCALIZATION: + type: kv + value: "true" + AWS_REGION: + type: kv + value: "us-east-2" + DISCOURSE_COMPRESS_ANON_CACHE: + type: kv + value: "false" + DB_DEFAULT_TEXT_SEARCH_CONFIG: + type: kv + value: "pg_catalog.english" + DISCOURSE_BACKUP_LOCATION: + type: kv + value: "s3" + DISCOURSE_S3_ACL: + type: kv + value: "private" + +# Web Configuration +web: + replicaCount: 1 + command: + - /sbin/boot + env: + - name: RAILS_ENV + value: production + resources: + requests: + cpu: 500m + memory: 2Gi + limits: + cpu: 2000m + memory: 4Gi + + # Extended probes for slow startup (from Bitnami) + livenessProbe: + enabled: true + httpGet: + path: /srv/status + port: http + initialDelaySeconds: 300 # 5 minutes + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + enabled: true + httpGet: + path: /srv/status + port: http + initialDelaySeconds: 120 # 2 minutes + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 20 + + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + extraEnvFrom: [] + + hpa: + enabled: false + +# Sidekiq Configuration +sidekiq: + replicaCount: 1 + command: + - /sbin/boot + env: + - name: DISCOURSE_SIDEKIQ + value: "1" + - name: RAILS_ENV + value: production + + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + cpu: 1000m + memory: 2Gi + + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + + # Additional Sidekiq environment variables + extraEnv: + - name: DISCOURSE_SIDEKIQ_WORKERS + value: "2" + +# Service Configuration +service: + type: ClusterIP + port: 80 + annotations: {} + +# Ingress Configuration (Traefik with Cloudflare) +ingress: + enabled: true + className: traefik + annotations: + external-dns.alpha.kubernetes.io/cloudflare-proxied: "true" + hosts: + - host: forum-staging.sky.money + paths: + - path: / + pathType: Prefix + tls: + - secretName: forum-staging-tls-secret + hosts: + - forum-staging.sky.money + + # Certificate manager configuration + certManager: + enabled: true + issuerName: cloudflare + issuerKind: ClusterIssuer + secretName: forum-staging-tls-secret + duration: 2160h0m0s # 90 days + renewBefore: 720h0m0s # 30 days + +# PostgreSQL Configuration (embedded for staging) +postgresql: + enabled: true + servicePort: 5432 + replicaCount: 1 + image: + repository: pgvector/pgvector + tag: "pg14" + pullPolicy: IfNotPresent + + persistence: + enabled: true + size: 20Gi + storageClass: gp3 + accessModes: + - ReadWriteOnce + + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + cpu: 500m + memory: 2Gi + + parameters: + max_connections: "200" + + podSecurityContext: {} + + containerSecurityContext: {} + +# Redis Configuration (embedded for staging) +redis: + enabled: true + servicePort: 6379 + image: + repository: redis + tag: "7" + pullPolicy: IfNotPresent + + persistence: + enabled: true + size: 5Gi + storageClass: gp3 + accessModes: + - ReadWriteOnce + + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 250m + memory: 512Mi + + podSecurityContext: {} + + containerSecurityContext: {} + +# Network Policy (disabled for staging) +networkPolicy: + enabled: false + +# Pod Disruption Budget (disabled for single replica) +podDisruptionBudget: + web: + enabled: false + sidekiq: + enabled: false + +# Autoscaling (disabled for staging) +autoscaling: + enabled: false diff --git a/_deprecated/charts/discourse/values.yaml b/_deprecated/charts/discourse/values.yaml new file mode 100644 index 0000000..28628af --- /dev/null +++ b/_deprecated/charts/discourse/values.yaml @@ -0,0 +1,260 @@ +global: + nameOverride: "" + fullnameOverride: "" + +image: + repository: discourse/discourse + tag: beta + pullPolicy: IfNotPresent + +imagePullSecrets: [] + +serviceAccount: + create: true + name: "" + annotations: {} + # eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME + +podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: OnRootMismatch + +securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + capabilities: + drop: + - ALL + +config: + discourseHostname: forum.example.com + discourseDbHost: "" + discourseDbName: discourse + discourseDbUsername: discourse + discourseDbPort: 5432 + discourseRedisHost: "" + discourseRedisPort: 6379 + discourseEnableCors: true + discourseCorsOrigin: "*" + discourseServeStaticAssets: false + discourseS3Enabled: true + discourseUseS3: true + discourseS3Region: us-east-1 + discourseS3Bucket: forum-uploads + discourseS3BackupBucket: forum-backups + discourseS3UploadsPrefix: "" + discourseS3BackupsPrefix: "" + discourseS3UseIamProfile: false + discourseS3Endpoint: "" + discourseDeveloperEmails: admin@example.com + discourseMaxMindLicenseKey: "" + smtpAddress: smtp.example.com + smtpPort: 587 + smtpUserName: smtp-user + smtpDomain: example.com + smtpEnableStartTls: true + +secrets: + dbPassword: "" + redisPassword: "" + s3AccessKeyId: "" + s3SecretAccessKey: "" + smtpPassword: "" + +uploads: + s3ConfigSecretName: "" + +web: + replicaCount: 1 + command: + - /sbin/boot + env: + - name: RAILS_ENV + value: production + resources: + requests: + cpu: 1000m + memory: 2Gi + limits: + cpu: 2000m + memory: 4Gi + livenessProbe: + enabled: true + httpGet: + path: /srv/status + port: http + initialDelaySeconds: 60 + periodSeconds: 30 + readinessProbe: + enabled: true + httpGet: + path: /srv/status + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + extraEnvFrom: [] + hpa: + enabled: false + minReplicas: 2 + maxReplicas: 5 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: null + +sidekiq: + replicaCount: 1 + command: + - /sbin/boot + env: + - name: DISCOURSE_SIDEKIQ + value: "1" + - name: RAILS_ENV + value: production + resources: + requests: + cpu: 1000m + memory: 2Gi + limits: + cpu: 2000m + memory: 4Gi + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + extraEnvFrom: [] + +service: + type: ClusterIP + port: 80 + annotations: {} + +ingress: + enabled: true + className: "" + annotations: {} + hosts: + - host: forum.example.com + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: discourse-tls + # hosts: + # - forum.example.com + # Certificate manager integration (optional) + # Automatically creates a Certificate resource using cert-manager + certManager: + enabled: false + # issuerName: letsencrypt-prod + # issuerKind: ClusterIssuer + # secretName: "" # defaults to -tls + # duration: 2160h # 90 days + # renewBefore: 720h # 30 days + +postgresql: + enabled: true + servicePort: 5432 + replicaCount: 1 + image: + repository: postgres + tag: "14" + pullPolicy: IfNotPresent + persistence: + enabled: true + size: 10Gi + storageClass: "" + accessModes: + - ReadWriteOnce + existingClaim: "" + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + cpu: 500m + memory: 2Gi + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + parameters: + max_connections: "200" + podSecurityContext: {} + containerSecurityContext: {} + extraEnv: [] + +redis: + enabled: true + servicePort: 6379 + image: + repository: redis + tag: "7" + pullPolicy: IfNotPresent + persistence: + enabled: true + size: 8Gi + storageClass: "" + accessModes: + - ReadWriteOnce + existingClaim: "" + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + podAnnotations: {} + nodeSelector: {} + tolerations: [] + affinity: {} + podSecurityContext: {} + containerSecurityContext: {} + extraEnv: [] + +networkPolicy: + enabled: false + +podDisruptionBudget: + web: + enabled: false + minAvailable: 1 + sidekiq: + enabled: false + minAvailable: 1 + +autoscaling: + enabled: false + +# External Secrets configuration (optional) +# Used when env variables have type: parameterStore +externalSecrets: {} + # clusterSecretStoreName: aws-parameter-store + # refreshInterval: 1m + +# Environment variables with flexible sourcing +# Supports multiple types: kv, parameterStore, secret, configmapRef +env: {} + # Example configurations: + # CUSTOM_VAR: + # type: kv + # value: "hardcoded-value" + # DB_PASSWORD: + # type: parameterStore + # name: db-password + # parameter_name: /discourse/prod/db-password + # API_KEY: + # type: secret + # name: discourse-api-keys + # key: api-key + # CONFIG_VALUE: + # type: configmapRef + # name: discourse-config + # key: config-value