Compare commits
1
Commits
507b2225b1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e91586b968
|
@@ -6,12 +6,13 @@ SIGNUP_URL = "https://www.eom.dev/members"
|
||||
|
||||
# OIDC is the only login method left, so with auth_immediately the
|
||||
# Log In button redirects straight to Dex. Accounts link by email.
|
||||
SiteSetting.ldap_enabled = false
|
||||
SiteSetting.enable_local_logins = false
|
||||
SiteSetting.auth_immediately = true
|
||||
# New members sign up at www.eom.dev; Discourse must still create their
|
||||
# account on first Dex login.
|
||||
SiteSetting.allow_new_registrations = true
|
||||
# Chat is bundled in core and on by default; this forum does not use it.
|
||||
SiteSetting.chat_enabled = false
|
||||
|
||||
head_tag = <<~HTML
|
||||
<script>
|
||||
@@ -40,5 +41,5 @@ Theme.where(component: false).find_each do |theme|
|
||||
theme.add_relative_theme!(:child, component)
|
||||
end
|
||||
|
||||
puts "ldap_enabled=#{SiteSetting.ldap_enabled} component=#{component.id} " \
|
||||
puts "enable_local_logins=#{SiteSetting.enable_local_logins} component=#{component.id} " \
|
||||
"parents=#{component.parent_themes.pluck(:name).join(', ')}"
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,73 @@
|
||||
# PostgreSQL 18 with pgvector for Discourse. Runs alongside the old Bitnami
|
||||
# PostgreSQL 17 StatefulSet, whose volume stays untouched for rollback.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: discourse-postgres18
|
||||
namespace: discourse
|
||||
labels:
|
||||
app.kubernetes.io/name: discourse-postgres18
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app.kubernetes.io/name: discourse-postgres18
|
||||
ports:
|
||||
- name: postgresql
|
||||
port: 5432
|
||||
targetPort: postgresql
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: discourse-postgres18
|
||||
namespace: discourse
|
||||
labels:
|
||||
app.kubernetes.io/name: discourse-postgres18
|
||||
spec:
|
||||
serviceName: discourse-postgres18
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: discourse-postgres18
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: discourse-postgres18
|
||||
spec:
|
||||
containers:
|
||||
- name: postgresql
|
||||
image: pgvector/pgvector:pg18
|
||||
ports:
|
||||
- name: postgresql
|
||||
containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: postgres
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-postgresql
|
||||
key: postgres-password
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres", "-h", "127.0.0.1"]
|
||||
periodSeconds: 10
|
||||
failureThreshold: 6
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres", "-h", "127.0.0.1"]
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 6
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: nfs-client
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Ti
|
||||
@@ -0,0 +1,36 @@
|
||||
# Build-only config for the eom.dev Discourse image. No secrets belong here:
|
||||
# database, Redis and SMTP credentials are supplied at runtime by Kubernetes.
|
||||
templates:
|
||||
- "templates/web.template.yml"
|
||||
- "templates/web.ratelimited.template.yml"
|
||||
|
||||
params:
|
||||
version: v2026.10.0
|
||||
|
||||
env:
|
||||
LC_ALL: en_US.UTF-8
|
||||
LANG: en_US.UTF-8
|
||||
LANGUAGE: en_US.UTF-8
|
||||
DISCOURSE_HOSTNAME: discourse.eom.dev
|
||||
DISABLE_LETSENCRYPT: 1
|
||||
|
||||
# Everything else the forum uses (openid-connect, reactions, math, post-voting,
|
||||
# adplugin, subscriptions, chat) is bundled in core at this version.
|
||||
hooks:
|
||||
after_code:
|
||||
- exec:
|
||||
cd: $home/plugins
|
||||
cmd:
|
||||
- git clone https://github.com/discourse/discourse-activity-pub.git
|
||||
- git clone https://github.com/discourse/discourse-prometheus.git
|
||||
|
||||
run:
|
||||
# ingress-nginx terminates TLS, so trust its X-Forwarded-For only from the pod
|
||||
# network. Without this every visitor shares the ingress IP and hits rate limits.
|
||||
- file:
|
||||
path: /etc/nginx/conf.d/outlets/server/real-ip.conf
|
||||
chmod: 644
|
||||
contents: |
|
||||
set_real_ip_from 10.244.0.0/16;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
+47
-81
@@ -1,90 +1,57 @@
|
||||
---
|
||||
# tasks file for discourse
|
||||
#
|
||||
# Discourse runs from an image built with the official launcher; the Bitnami
|
||||
# chart stops at 3.5.0. To upgrade, change params.version in
|
||||
# files/discourse/web_only.yml, then from a discourse_docker checkout:
|
||||
# cp <role>/files/discourse/web_only.yml containers/web_only.yml
|
||||
# launcher build --set base_image=<base_image from templates/web.template.yml>-web-only \
|
||||
# --tag gitea.eom.dev/devops/discourse-web:<version> web_only --output=type=docker
|
||||
# Push it, update the image tag in files/discourse/discourse-web.yaml, and re-run.
|
||||
#
|
||||
# Pushing through the gitea ingress needs proxy-body-size raised and
|
||||
# proxy-request-buffering "off" for the push, then restored. With buffering on,
|
||||
# ingress-nginx writes layers to its node's small disk; on 2026-11-08 that caused
|
||||
# DiskPressure, evicted the MetalLB speaker, and took the public sites down.
|
||||
#
|
||||
# Redis, the secrets, the uploads PVC, the Service and the Ingress still come from
|
||||
# the original Helm release, which must stay installed but is no longer upgraded.
|
||||
- name: Deploy PostgreSQL 18 for Discourse
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
src: "{{ role_path }}/files/discourse/postgres18.yaml"
|
||||
|
||||
- name: Deploy Discourse
|
||||
kubernetes.core.helm:
|
||||
name: discourse
|
||||
chart_ref: bitnami/discourse
|
||||
release_namespace: discourse
|
||||
create_namespace: true
|
||||
values:
|
||||
auth:
|
||||
email: discourse@eom.dev
|
||||
username: discourse_admin
|
||||
password: "{{ discourse_admin_password }}"
|
||||
host: "https://discourse.eom.dev"
|
||||
siteName: 'Discourse'
|
||||
smtp:
|
||||
enabled: true
|
||||
host: "postfix.eom.dev"
|
||||
port: "587"
|
||||
protocol: "tls"
|
||||
user: "discourse"
|
||||
password: "{{ discourse_admin_password }}"
|
||||
image:
|
||||
debug: false
|
||||
repository: bitnamilegacy/discourse
|
||||
tag: 3.4.7-debian-12-r0
|
||||
service:
|
||||
externalTrafficPolicy: Local
|
||||
discourse:
|
||||
skipInstall: false
|
||||
plugins:
|
||||
- https://github.com/discourse/discourse-adplugin
|
||||
- https://github.com/discourse/discourse-subscriptions
|
||||
- https://github.com/discourse/discourse-activity-pub
|
||||
- https://github.com/discourse/discourse-openid-connect
|
||||
# discourse-ldap-auth removed: its login cannot be disabled by setting,
|
||||
# and sign-in goes through Dex (discourse-openid-connect) only.
|
||||
- https://github.com/discourse/discourse-math
|
||||
- https://github.com/discourse/discourse-post-voting
|
||||
- https://github.com/discourse/discourse-prometheus
|
||||
- https://github.com/discourse/discourse-reactions
|
||||
command:
|
||||
- /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
rm -r /opt/bitnami/discourse/plugins/chat
|
||||
chown -R discourse:root /opt/bitnami/discourse/plugins
|
||||
/opt/bitnami/scripts/discourse/entrypoint.sh /opt/bitnami/scripts/discourse/run.sh
|
||||
persistPlugins: false
|
||||
compatiblePlugins: true
|
||||
resourcesPreset: none
|
||||
persistence:
|
||||
size: 2Ti
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: "nginx"
|
||||
hostname: discourse.eom.dev
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: ca-issuer
|
||||
nginx.ingress.kubernetes.io/proxy-set-header: "X-Forwarded-Proto $scheme"
|
||||
tls: true
|
||||
postgresql:
|
||||
enabled: true
|
||||
image:
|
||||
repository: bitnamilegacy/postgresql
|
||||
auth:
|
||||
enablePostgresUser: true
|
||||
postgresPassword: "{{ discourse_admin_password }}"
|
||||
password: "{{ discourse_admin_password }}"
|
||||
primary:
|
||||
persistence:
|
||||
size: 2Ti
|
||||
redis:
|
||||
enabled: true
|
||||
image:
|
||||
repository: bitnamilegacy/redis
|
||||
auth:
|
||||
password: "{{ discourse_admin_password }}"
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
src: "{{ role_path }}/files/discourse/discourse-web.yaml"
|
||||
wait: true
|
||||
wait_condition:
|
||||
type: Available
|
||||
status: "True"
|
||||
wait_timeout: 1800
|
||||
|
||||
- name: Point the Discourse Service at the launcher-built pods
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
merge_type: merge
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: discourse
|
||||
namespace: discourse
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: discourse-web
|
||||
app.kubernetes.io/instance: null
|
||||
|
||||
- name: Find the Discourse pod
|
||||
kubernetes.core.k8s_info:
|
||||
kind: Pod
|
||||
namespace: discourse
|
||||
label_selectors:
|
||||
- app.kubernetes.io/instance=discourse
|
||||
- app.kubernetes.io/name=discourse
|
||||
- app.kubernetes.io/name=discourse-web
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
register: discourse_pods
|
||||
@@ -103,8 +70,7 @@
|
||||
pod: "{{ discourse_pods.resources[0].metadata.name }}"
|
||||
container: discourse
|
||||
command: >-
|
||||
bash -c 'cd /opt/bitnami/discourse && PATH=/opt/bitnami/ruby/bin:$PATH
|
||||
RAILS_ENV=production bundle exec ruby -e
|
||||
"require \"/opt/bitnami/discourse/config/environment\"; load \"/tmp/discourse-sso.rb\""'
|
||||
bash -c 'cd /var/www/discourse && su discourse -c
|
||||
"RAILS_ENV=production bundle exec rails runner /tmp/discourse-sso.rb"'
|
||||
register: discourse_sso
|
||||
changed_when: false
|
||||
|
||||
Reference in New Issue
Block a user