Discourse: move from Bitnami chart to launcher-built image

The Bitnami chart and images stop at 3.5.0. Run Discourse 2026.10.0 from
an image built with the official launcher, on PostgreSQL 18, reusing the
existing uploads volume, Redis and secrets.

Update the Dex sign-in step for the new image paths, drop the removed
LDAP setting, and keep chat off now that it is bundled in core. The image
adds a real-IP rule so visitors are not all rate limited as the ingress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-08 15:32:46 -05:00
co-authored by Claude Opus 5.5
parent 507b2225b1
commit e91586b968
5 changed files with 266 additions and 83 deletions
+107
View File
@@ -0,0 +1,107 @@
# Discourse v2026.10.0, built with the official launcher (see web_only.yml).
# Reuses the existing Bitnami-era uploads volume, Redis and Kubernetes secrets.
apiVersion: apps/v1
kind: Deployment
metadata:
name: discourse-web
namespace: discourse
labels:
app.kubernetes.io/name: discourse-web
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: discourse-web
template:
metadata:
labels:
app.kubernetes.io/name: discourse-web
spec:
# The image is 3.77 GB and most nodes have only 3-8 GB free; pulling it
# elsewhere risks DiskPressure and evicting the MetalLB speakers.
nodeSelector:
kubernetes.io/hostname: alpha-worker-0
initContainers:
# The launcher image runs Discourse as uid 1000; Bitnami used 999.
- name: fix-ownership
image: gitea.eom.dev/devops/discourse-web:v2026.10.0
command: ["sh", "-c", "chown -R 1000:1000 /shared/uploads /shared/backups"]
volumeMounts:
- name: discourse-data
mountPath: /shared/uploads
subPath: discourse/public/uploads
- name: discourse-data
mountPath: /shared/backups
subPath: discourse/public/backups
containers:
- name: discourse
image: gitea.eom.dev/devops/discourse-web:v2026.10.0
command: ["/sbin/boot"]
ports:
- name: http
containerPort: 80
env:
- { name: RAILS_ENV, value: production }
- { name: LANG, value: en_US.UTF-8 }
- { name: LC_ALL, value: en_US.UTF-8 }
- { name: MIGRATE_ON_BOOT, value: "1" }
- { name: PRECOMPILE_ON_BOOT, value: "1" }
- { name: CREATE_DB_ON_BOOT, value: "0" }
- { name: UNICORN_WORKERS, value: "2" }
- { name: UNICORN_SIDEKIQS, value: "1" }
- { name: DISCOURSE_HOSTNAME, value: discourse.eom.dev }
- { name: DISCOURSE_DB_SOCKET, value: "" }
- { name: DISCOURSE_DB_HOST, value: discourse-postgres18 }
- { name: DISCOURSE_DB_NAME, value: bitnami_application }
- { name: DISCOURSE_DB_USERNAME, value: bn_discourse }
- name: DISCOURSE_DB_PASSWORD
valueFrom:
secretKeyRef: { name: discourse-postgresql, key: password }
- { name: DISCOURSE_REDIS_HOST, value: discourse-redis-master }
- name: DISCOURSE_REDIS_PASSWORD
valueFrom:
secretKeyRef: { name: discourse-redis, key: redis-password }
- { name: DISCOURSE_SMTP_ADDRESS, value: postfix.eom.dev }
- { name: DISCOURSE_SMTP_PORT, value: "587" }
- { name: DISCOURSE_SMTP_USER_NAME, value: discourse }
- name: DISCOURSE_SMTP_PASSWORD
valueFrom:
secretKeyRef: { name: discourse-discourse, key: smtp-password }
startupProbe:
httpGet: &status
path: /srv/status
port: http
httpHeaders:
- { name: Host, value: discourse.eom.dev }
- { name: X-Forwarded-Proto, value: https }
periodSeconds: 10
failureThreshold: 180
readinessProbe:
httpGet: *status
periodSeconds: 10
failureThreshold: 6
livenessProbe:
httpGet: *status
periodSeconds: 20
failureThreshold: 6
resources:
requests:
cpu: 250m
memory: 1Gi
volumeMounts:
- name: shared
mountPath: /shared
- name: discourse-data
mountPath: /shared/uploads
subPath: discourse/public/uploads
- name: discourse-data
mountPath: /shared/backups
subPath: discourse/public/backups
volumes:
- name: shared
emptyDir: {}
- name: discourse-data
persistentVolumeClaim:
claimName: discourse