Bump remaining apps: major version slots and infrastructure
New version slots (major version jumps): - gitea: 1.24.3 -> 28.2.0 (slot 1 -> 28) - ghost: 5.130.6 -> 6.72.0 (slot 5 -> 6) - formbricks: 3.6.0 -> 6.1.0 (slot 3 -> 6) - mattermost: 10.8.1 -> 12.0.1 (slot 10 -> 12) - zulip: 9.4 -> 12.3 (slot 9 -> 12) - immich: 1.135.3 -> 3.3.5 (slot 1 -> 3) - openproject: 16.1.1 -> 17.9.3 (slot 16 -> 17) - listmonk: 5.0.3 -> 6.1.0 (slot 5 -> 6) - discourse: 3.5.3 -> 2026.10.0 (slot 3 -> 2026, calver) Same-slot large bumps: - vllm: 0.9.2 -> 0.32.0 - longhorn: v1.8.1 -> v1.13.0 Infrastructure: - cert-manager: v1.17.2 -> v1.21.2 - coredns: v1.12.0 -> v1.14.7 - externaldns: v0.13.4 -> v0.23.0 - metallb: v0.15.0 -> v0.16.1 - mysql: 9.1.0 -> 9.7.4 - node-feature-discovery: v0.17.3 -> v0.20.1 - nvidia-device-plugin: v0.17.1 -> v0.20.1
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
version: v1.17.2-1
|
||||
version: v1.21.2
|
||||
requires:
|
||||
- name: traefik
|
||||
defaultConfig:
|
||||
|
||||
@@ -12981,7 +12981,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: cert-manager-cainjector
|
||||
image: "quay.io/jetstack/cert-manager-cainjector:v1.17.2"
|
||||
image: "quay.io/jetstack/cert-manager-cainjector:v1.21.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --v=2
|
||||
@@ -13044,7 +13044,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: cert-manager-controller
|
||||
image: "quay.io/jetstack/cert-manager-controller:v1.17.2"
|
||||
image: "quay.io/jetstack/cert-manager-controller:v1.21.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --v=2
|
||||
@@ -13126,7 +13126,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: cert-manager-webhook
|
||||
image: "quay.io/jetstack/cert-manager-webhook:v1.17.2"
|
||||
image: "quay.io/jetstack/cert-manager-webhook:v1.21.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --v=2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v1.12.0-1
|
||||
version: v1.14.7
|
||||
requires:
|
||||
- name: metallb
|
||||
defaultConfig:
|
||||
|
||||
@@ -3,4 +3,4 @@ is: discourse
|
||||
description: Discourse is a modern, open-source discussion platform designed for online communities and forums.
|
||||
category: community
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/discourse.svg
|
||||
latest: "3"
|
||||
latest: "2026"
|
||||
|
||||
35
discourse/versions/2026/README.md
Normal file
35
discourse/versions/2026/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Discourse
|
||||
|
||||
Discourse is a modern, open-source discussion platform designed for online communities and forums.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing application data
|
||||
- **Redis** - Used for caching and background jobs
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings configured through your instance's `config.yaml`:
|
||||
|
||||
- **domain** - Where Discourse will be accessible (default: `discourse.{your-cloud-domain}`)
|
||||
- **adminEmail** - Admin account email (defaults to your operator email)
|
||||
- **adminUsername** - Admin account username (default: `admin`)
|
||||
- **siteName** - Your community name (default: `Community`)
|
||||
- **SMTP** - Email delivery settings inherited from your Wild Cloud instance
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, Discourse will be available at:
|
||||
- `https://discourse.{your-cloud-domain}`
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add discourse
|
||||
wild app deploy discourse
|
||||
```
|
||||
|
||||
2. Log in with the admin credentials configured during setup
|
||||
|
||||
3. Complete the setup wizard to configure your community
|
||||
78
discourse/versions/2026/db-init-job.yaml
Normal file
78
discourse/versions/2026/db-init-job.yaml
Normal file
@@ -0,0 +1,78 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: discourse-db-init
|
||||
namespace: discourse
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: db-init
|
||||
image: postgres:16-alpine
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
env:
|
||||
- name: PGHOST
|
||||
value: "{{ .db.host }}"
|
||||
- name: PGPORT
|
||||
value: "5432"
|
||||
- name: PGUSER
|
||||
value: postgres
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: postgres.password
|
||||
- name: DISCOURSE_DB_USER
|
||||
value: "{{ .db.user }}"
|
||||
- name: DISCOURSE_DB_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DISCOURSE_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: dbPassword
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo "Initializing Discourse database..."
|
||||
|
||||
# Create database if it doesn't exist
|
||||
if ! psql -lqt | cut -d \| -f 1 | grep -qw "$DISCOURSE_DB_NAME"; then
|
||||
echo "Creating database $DISCOURSE_DB_NAME..."
|
||||
createdb "$DISCOURSE_DB_NAME"
|
||||
else
|
||||
echo "Database $DISCOURSE_DB_NAME already exists."
|
||||
fi
|
||||
|
||||
# Create user if it doesn't exist and grant permissions
|
||||
psql -d "$DISCOURSE_DB_NAME" -c "
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$DISCOURSE_DB_USER') THEN
|
||||
CREATE USER $DISCOURSE_DB_USER WITH PASSWORD '$DISCOURSE_DB_PASSWORD';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
ALTER USER $DISCOURSE_DB_USER WITH PASSWORD '$DISCOURSE_DB_PASSWORD';
|
||||
GRANT ALL PRIVILEGES ON DATABASE $DISCOURSE_DB_NAME TO $DISCOURSE_DB_USER;
|
||||
GRANT ALL ON SCHEMA public TO $DISCOURSE_DB_USER;
|
||||
GRANT USAGE ON SCHEMA public TO $DISCOURSE_DB_USER;
|
||||
"
|
||||
|
||||
echo "Database initialization completed."
|
||||
304
discourse/versions/2026/deployment.yaml
Normal file
304
discourse/versions/2026/deployment.yaml
Normal file
@@ -0,0 +1,304 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: discourse
|
||||
namespace: discourse
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: web
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountName: discourse
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: Always
|
||||
initContainers:
|
||||
- name: discourse-migrate
|
||||
image: discourse/discourse:2026.10.0
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- CHOWN
|
||||
- FOWNER
|
||||
- SETGID
|
||||
- SETUID
|
||||
- DAC_OVERRIDE
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: false
|
||||
runAsUser: 0
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
cd /var/www/discourse
|
||||
export HOME=/root
|
||||
git config --global --add safe.directory /var/www/discourse
|
||||
bundle exec rake db:migrate
|
||||
bundle exec rake assets:precompile
|
||||
env:
|
||||
- name: RAILS_ENV
|
||||
value: "production"
|
||||
- name: DISCOURSE_DB_HOST
|
||||
value: {{ .db.host }}
|
||||
- name: DISCOURSE_DB_PORT
|
||||
value: "{{ .db.port }}"
|
||||
- name: DISCOURSE_DB_NAME
|
||||
value: {{ .db.name }}
|
||||
- name: DISCOURSE_DB_USERNAME
|
||||
value: {{ .db.user }}
|
||||
- name: DISCOURSE_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: dbPassword
|
||||
- name: DISCOURSE_REDIS_HOST
|
||||
value: {{ .redis.host }}
|
||||
- name: DISCOURSE_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: redis.password
|
||||
- name: DISCOURSE_HOSTNAME
|
||||
value: {{ .domain }}
|
||||
- name: DISCOURSE_SECRET_KEY_BASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: secretKeyBase
|
||||
volumeMounts:
|
||||
- name: discourse-data
|
||||
mountPath: /shared
|
||||
containers:
|
||||
- name: discourse
|
||||
image: discourse/discourse:2026.10.0
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
command:
|
||||
- /sbin/boot
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- CHOWN
|
||||
- FOWNER
|
||||
- SETGID
|
||||
- SETUID
|
||||
- DAC_OVERRIDE
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: false
|
||||
runAsUser: 0
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
env:
|
||||
- name: RAILS_ENV
|
||||
value: "production"
|
||||
# Discourse database configuration
|
||||
- name: DISCOURSE_DB_HOST
|
||||
value: {{ .db.host }}
|
||||
- name: DISCOURSE_DB_PORT
|
||||
value: "{{ .db.port }}"
|
||||
- name: DISCOURSE_DB_NAME
|
||||
value: {{ .db.name }}
|
||||
- name: DISCOURSE_DB_USERNAME
|
||||
value: {{ .db.user }}
|
||||
- name: DISCOURSE_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: dbPassword
|
||||
# Redis configuration
|
||||
- name: DISCOURSE_REDIS_HOST
|
||||
value: {{ .redis.host }}
|
||||
- name: DISCOURSE_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: redis.password
|
||||
# Site configuration
|
||||
- name: DISCOURSE_HOSTNAME
|
||||
value: {{ .domain }}
|
||||
- name: DISCOURSE_DEVELOPER_EMAILS
|
||||
value: {{ .adminEmail }}
|
||||
- name: DISCOURSE_SECRET_KEY_BASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: secretKeyBase
|
||||
# SMTP configuration
|
||||
- name: DISCOURSE_SMTP_ADDRESS
|
||||
value: {{ .smtp.host }}
|
||||
- name: DISCOURSE_SMTP_PORT
|
||||
value: "{{ .smtp.port }}"
|
||||
- name: DISCOURSE_SMTP_USER_NAME
|
||||
value: {{ .smtp.user }}
|
||||
- name: DISCOURSE_SMTP_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: smtpPassword
|
||||
- name: DISCOURSE_SMTP_ENABLE_START_TLS
|
||||
value: "{{ .smtp.startTls }}"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /srv/status
|
||||
port: http
|
||||
initialDelaySeconds: 500
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /srv/status
|
||||
port: http
|
||||
initialDelaySeconds: 360
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
ephemeral-storage: 10Gi
|
||||
memory: 8Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 512Mi
|
||||
volumeMounts:
|
||||
- name: discourse-data
|
||||
mountPath: /shared
|
||||
- name: sidekiq
|
||||
image: discourse/discourse:2026.10.0
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- CHOWN
|
||||
- FOWNER
|
||||
- SETGID
|
||||
- SETUID
|
||||
- DAC_OVERRIDE
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: false
|
||||
runAsUser: 0
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- "cd /var/www/discourse && export HOME=/root && exec bundle exec sidekiq"
|
||||
env:
|
||||
- name: RAILS_ENV
|
||||
value: "production"
|
||||
# Discourse database configuration
|
||||
- name: DISCOURSE_DB_HOST
|
||||
value: {{ .db.host }}
|
||||
- name: DISCOURSE_DB_PORT
|
||||
value: "{{ .db.port }}"
|
||||
- name: DISCOURSE_DB_NAME
|
||||
value: {{ .db.name }}
|
||||
- name: DISCOURSE_DB_USERNAME
|
||||
value: {{ .db.user }}
|
||||
- name: DISCOURSE_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: dbPassword
|
||||
# Redis configuration
|
||||
- name: DISCOURSE_REDIS_HOST
|
||||
value: {{ .redis.host }}
|
||||
- name: DISCOURSE_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: redis.password
|
||||
# Site configuration
|
||||
- name: DISCOURSE_HOSTNAME
|
||||
value: {{ .domain }}
|
||||
- name: DISCOURSE_DEVELOPER_EMAILS
|
||||
value: {{ .adminEmail }}
|
||||
- name: DISCOURSE_SECRET_KEY_BASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: secretKeyBase
|
||||
# SMTP configuration
|
||||
- name: DISCOURSE_SMTP_ADDRESS
|
||||
value: {{ .smtp.host }}
|
||||
- name: DISCOURSE_SMTP_PORT
|
||||
value: "{{ .smtp.port }}"
|
||||
- name: DISCOURSE_SMTP_USER_NAME
|
||||
value: {{ .smtp.user }}
|
||||
- name: DISCOURSE_SMTP_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: discourse-secrets
|
||||
key: smtpPassword
|
||||
- name: DISCOURSE_SMTP_ENABLE_START_TLS
|
||||
value: "{{ .smtp.startTls }}"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- "pgrep -f sidekiq"
|
||||
initialDelaySeconds: 500
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- "pgrep -f sidekiq"
|
||||
initialDelaySeconds: 180
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
ephemeral-storage: 2Gi
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 512Mi
|
||||
volumeMounts:
|
||||
- name: discourse-data
|
||||
mountPath: /shared
|
||||
volumes:
|
||||
- name: discourse-data
|
||||
persistentVolumeClaim:
|
||||
claimName: discourse-data
|
||||
20
discourse/versions/2026/ingress.yaml
Normal file
20
discourse/versions/2026/ingress.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# Source: discourse/templates/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: discourse
|
||||
namespace: "{{ .namespace }}"
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: "{{ .domain }}"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
backend:
|
||||
service:
|
||||
name: discourse
|
||||
port:
|
||||
name: http
|
||||
17
discourse/versions/2026/kustomization.yaml
Normal file
17
discourse/versions/2026/kustomization.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: discourse
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: discourse
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- serviceaccount.yaml
|
||||
- pvc.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- db-init-job.yaml
|
||||
39
discourse/versions/2026/manifest.yaml
Normal file
39
discourse/versions/2026/manifest.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
version: 2026.10.0
|
||||
requires:
|
||||
- name: postgres
|
||||
- name: redis
|
||||
- name: smtp
|
||||
defaultConfig:
|
||||
namespace: discourse
|
||||
storage: 2Gi
|
||||
adminEmail: '{{ .operator.email }}'
|
||||
adminUsername: admin
|
||||
siteName: Community
|
||||
domain: discourse.{{ .cloud.domain }}
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
name: discourse
|
||||
user: discourse
|
||||
redis:
|
||||
host: '{{ .apps.redis.host }}'
|
||||
smtp:
|
||||
enabled: false
|
||||
host: '{{ .apps.smtp.host }}'
|
||||
port: '{{ .apps.smtp.port }}'
|
||||
user: '{{ .apps.smtp.user }}'
|
||||
from: '{{ .apps.smtp.from }}'
|
||||
tls: '{{ .apps.smtp.tls }}'
|
||||
startTls: '{{ .apps.smtp.startTls }}'
|
||||
defaultSecrets:
|
||||
- key: adminPassword
|
||||
- key: secretKeyBase
|
||||
default: '{{ random.Hex 32 }}'
|
||||
- key: smtpPassword
|
||||
- key: dbPassword
|
||||
- key: dbUrl
|
||||
default: postgres://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host
|
||||
}}:{{ .app.db.port }}/{{ .app.db.name }}?sslmode=disable
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
- redis.password
|
||||
4
discourse/versions/2026/namespace.yaml
Normal file
4
discourse/versions/2026/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
13
discourse/versions/2026/pvc.yaml
Normal file
13
discourse/versions/2026/pvc.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: discourse-data
|
||||
namespace: discourse
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
storageClassName: longhorn
|
||||
18
discourse/versions/2026/service.yaml
Normal file
18
discourse/versions/2026/service.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# Source: discourse/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: discourse
|
||||
namespace: discourse
|
||||
spec:
|
||||
type: ClusterIP
|
||||
sessionAffinity: None
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
nodePort: null
|
||||
selector:
|
||||
component: web
|
||||
8
discourse/versions/2026/serviceaccount.yaml
Normal file
8
discourse/versions/2026/serviceaccount.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# Source: discourse/templates/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: discourse
|
||||
namespace: discourse
|
||||
automountServiceAccountToken: false
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: external-dns
|
||||
image: registry.k8s.io/external-dns/external-dns:v0.13.4
|
||||
image: registry.k8s.io/external-dns/external-dns:v0.23.0
|
||||
args:
|
||||
- --source=service
|
||||
- --source=ingress
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v0.13.4-6
|
||||
version: v0.23.0
|
||||
deploymentName: external-dns
|
||||
requires:
|
||||
- name: cert-manager
|
||||
|
||||
@@ -3,4 +3,4 @@ is: formbricks
|
||||
description: Formbricks is an open-source survey and form platform for collecting and analyzing user feedback. A self-hosted alternative to Typeform and SurveyMonkey.
|
||||
category: business
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/formbricks.svg
|
||||
latest: "3"
|
||||
latest: "6"
|
||||
|
||||
36
formbricks/versions/6/README.md
Normal file
36
formbricks/versions/6/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Formbricks
|
||||
|
||||
Formbricks is an open-source survey and feedback platform for building in-app microsurveys, NPS scores, and user research forms.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing surveys and responses
|
||||
- **Redis** - Used for caching and background jobs
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings in `config.yaml`:
|
||||
|
||||
- **domain** - Where Formbricks will be accessible
|
||||
- **storage** - Persistent volume size (default: `2Gi`)
|
||||
- **db.name** - Database name (default: `formbricks`)
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add formbricks
|
||||
wild app deploy formbricks
|
||||
```
|
||||
|
||||
2. Visit the app URL and sign up to create your admin account.
|
||||
|
||||
3. The first user to sign up becomes the organization owner.
|
||||
|
||||
4. Create your first survey from the dashboard and embed it in your apps using the provided JavaScript snippet.
|
||||
|
||||
## Notes
|
||||
|
||||
- Formbricks can be embedded in web apps or used as a standalone survey link
|
||||
- The `nextauthSecret` and `encryptionKey` are auto-generated in `secrets.yaml`
|
||||
- The `cronSecret` secures the internal cron endpoint used for scheduled tasks
|
||||
61
formbricks/versions/6/db-init-job.yaml
Normal file
61
formbricks/versions/6/db-init-job.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: formbricks-db-init
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: db-init
|
||||
image: postgres:17
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOST} -U postgres <<EOF
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USER}') THEN
|
||||
CREATE USER ${DB_USER} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
ELSE
|
||||
ALTER USER ${DB_USER} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
SELECT 'CREATE DATABASE ${DB_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_NAME}')\gexec
|
||||
ALTER DATABASE ${DB_NAME} OWNER TO ${DB_USER};
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};
|
||||
EOF
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOST} -U postgres -d ${DB_NAME} -c "GRANT ALL ON SCHEMA public TO ${DB_USER};"
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOST} -U postgres -d ${DB_NAME} -c "CREATE EXTENSION IF NOT EXISTS vector;"
|
||||
env:
|
||||
- name: POSTGRES_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: postgres.password
|
||||
- name: DB_HOST
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DB_USER
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: dbPassword
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
restartPolicy: OnFailure
|
||||
102
formbricks/versions/6/deployment.yaml
Normal file
102
formbricks/versions/6/deployment.yaml
Normal file
@@ -0,0 +1,102 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: formbricks
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: web
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: false
|
||||
runAsUser: 0
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: formbricks
|
||||
image: formbricks/formbricks:6.1.0
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3000
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: NODE_OPTIONS
|
||||
value: "--max-old-space-size=768"
|
||||
- name: WEBAPP_URL
|
||||
value: "https://{{ .domain }}"
|
||||
- name: NEXTAUTH_URL
|
||||
value: "https://{{ .domain }}"
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: dbUrl
|
||||
- name: NEXTAUTH_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: nextauthSecret
|
||||
- name: ENCRYPTION_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: encryptionKey
|
||||
- name: CRON_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: cronSecret
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: formbricks-secrets
|
||||
key: redis.password
|
||||
- name: REDIS_URL
|
||||
value: "redis://:$(REDIS_PASSWORD)@{{ .redis.host }}:6379"
|
||||
- name: EMAIL_VERIFICATION_DISABLED
|
||||
value: "1"
|
||||
- name: PASSWORD_RESET_DISABLED
|
||||
value: "1"
|
||||
resources:
|
||||
limits:
|
||||
cpu: "1"
|
||||
ephemeral-storage: 1Gi
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: formbricks-uploads
|
||||
mountPath: /home/nextjs/apps/web/uploads
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 3000
|
||||
initialDelaySeconds: 90
|
||||
timeoutSeconds: 5
|
||||
periodSeconds: 15
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 3000
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: false
|
||||
volumes:
|
||||
- name: formbricks-uploads
|
||||
persistentVolumeClaim:
|
||||
claimName: formbricks-uploads
|
||||
restartPolicy: Always
|
||||
18
formbricks/versions/6/ingress.yaml
Normal file
18
formbricks/versions/6/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: formbricks
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: {{ .domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: formbricks
|
||||
port:
|
||||
number: 80
|
||||
16
formbricks/versions/6/kustomization.yaml
Normal file
16
formbricks/versions/6/kustomization.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: {{ .namespace }}
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: formbricks
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- pvc.yaml
|
||||
- db-init-job.yaml
|
||||
26
formbricks/versions/6/manifest.yaml
Normal file
26
formbricks/versions/6/manifest.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
version: 6.1.0
|
||||
requires:
|
||||
- name: postgres
|
||||
- name: redis
|
||||
defaultConfig:
|
||||
namespace: formbricks
|
||||
domain: formbricks.{{ .cloud.domain }}
|
||||
storage: 2Gi
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
name: formbricks
|
||||
user: formbricks
|
||||
redis:
|
||||
host: '{{ .apps.redis.host }}'
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
- key: dbUrl
|
||||
default: postgresql://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host
|
||||
}}:{{ .app.db.port }}/{{ .app.db.name }}?sslmode=disable
|
||||
- key: nextauthSecret
|
||||
- key: encryptionKey
|
||||
- key: cronSecret
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
- redis.password
|
||||
4
formbricks/versions/6/namespace.yaml
Normal file
4
formbricks/versions/6/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .namespace }}
|
||||
11
formbricks/versions/6/pvc.yaml
Normal file
11
formbricks/versions/6/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: formbricks-uploads
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
13
formbricks/versions/6/service.yaml
Normal file
13
formbricks/versions/6/service.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: formbricks
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
selector:
|
||||
component: web
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
protocol: TCP
|
||||
@@ -3,4 +3,4 @@ is: ghost
|
||||
description: Ghost is a powerful app for new-media creators to publish, share, and grow a business around their content.
|
||||
category: social
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/ghost.png
|
||||
latest: "5"
|
||||
latest: "6"
|
||||
|
||||
33
ghost/versions/6/README.md
Normal file
33
ghost/versions/6/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Ghost
|
||||
|
||||
Ghost is a powerful app for new-media creators to publish, share, and grow a business around their content. It provides a clean writing experience with built-in membership and subscription features.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **MySQL** - Database for storing content and configuration
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings configured through your instance's `config.yaml`:
|
||||
|
||||
- **domain** - Where Ghost will be accessible (default: `ghost.{your-cloud-domain}`)
|
||||
- **blogTitle** - Your blog's title (default: `My Blog`)
|
||||
- **adminEmail** - Admin account email (defaults to your operator email)
|
||||
- **storage** - Persistent volume size for content (default: `10Gi`)
|
||||
- **SMTP** - Email delivery settings inherited from your Wild Cloud instance
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, Ghost will be available at:
|
||||
- `https://ghost.{your-cloud-domain}` - Public blog
|
||||
- `https://ghost.{your-cloud-domain}/ghost` - Admin panel
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add ghost
|
||||
wild app deploy ghost
|
||||
```
|
||||
|
||||
2. Navigate to the admin panel and create your first post
|
||||
45
ghost/versions/6/db-init-job.yaml
Normal file
45
ghost/versions/6/db-init-job.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: ghost-db-init
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
containers:
|
||||
- name: db-init
|
||||
image: mysql:9.1.0
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
mysql -h ${DB_HOSTNAME} -P ${DB_PORT} -u root -p${MYSQL_ROOT_PASSWORD} <<EOF
|
||||
CREATE DATABASE IF NOT EXISTS ${DB_DATABASE_NAME};
|
||||
CREATE USER IF NOT EXISTS '${DB_USERNAME}'@'%' IDENTIFIED BY '${DB_PASSWORD}';
|
||||
ALTER USER '${DB_USERNAME}'@'%' IDENTIFIED BY '${DB_PASSWORD}';
|
||||
GRANT ALL PRIVILEGES ON ${DB_DATABASE_NAME}.* TO '${DB_USERNAME}'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
EOF
|
||||
env:
|
||||
- name: MYSQL_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ghost-secrets
|
||||
key: mysql.rootPassword
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_PORT
|
||||
value: "{{ .db.port }}"
|
||||
- name: DB_DATABASE_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ghost-secrets
|
||||
key: dbPassword
|
||||
restartPolicy: OnFailure
|
||||
105
ghost/versions/6/deployment.yaml
Normal file
105
ghost/versions/6/deployment.yaml
Normal file
@@ -0,0 +1,105 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ghost
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: web
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: ghost
|
||||
image: ghost:6.72.0-alpine
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 2368
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: NODE_ENV
|
||||
value: production
|
||||
- name: url
|
||||
value: "https://{{ .domain }}"
|
||||
- name: database__client
|
||||
value: mysql
|
||||
- name: database__connection__host
|
||||
value: "{{ .db.host }}"
|
||||
- name: database__connection__port
|
||||
value: "{{ .db.port }}"
|
||||
- name: database__connection__database
|
||||
value: "{{ .db.name }}"
|
||||
- name: database__connection__user
|
||||
value: "{{ .db.user }}"
|
||||
- name: database__connection__password
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ghost-secrets
|
||||
key: dbPassword
|
||||
- name: mail__transport
|
||||
value: SMTP
|
||||
- name: mail__options__host
|
||||
value: "{{ .smtp.host }}"
|
||||
- name: mail__options__port
|
||||
value: "{{ .smtp.port }}"
|
||||
- name: mail__options__auth__user
|
||||
value: "{{ .smtp.user }}"
|
||||
- name: mail__options__auth__pass
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ghost-secrets
|
||||
key: smtpPassword
|
||||
- name: mail__from
|
||||
value: "{{ .smtp.from }}"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
ephemeral-storage: 2Gi
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: ghost-data
|
||||
mountPath: /var/lib/ghost/content
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /ghost/api/admin/site/
|
||||
port: 2368
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 5
|
||||
periodSeconds: 30
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ghost/api/admin/site/
|
||||
port: 2368
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
periodSeconds: 15
|
||||
failureThreshold: 3
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
volumes:
|
||||
- name: ghost-data
|
||||
persistentVolumeClaim:
|
||||
claimName: ghost-data
|
||||
restartPolicy: Always
|
||||
18
ghost/versions/6/ingress.yaml
Normal file
18
ghost/versions/6/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ghost
|
||||
namespace: ghost
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: {{ .domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: ghost
|
||||
port:
|
||||
number: 80
|
||||
16
ghost/versions/6/kustomization.yaml
Normal file
16
ghost/versions/6/kustomization.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: ghost
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: ghost
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- db-init-job.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- pvc.yaml
|
||||
23
ghost/versions/6/manifest.yaml
Normal file
23
ghost/versions/6/manifest.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
version: 6.72.0
|
||||
requires:
|
||||
- name: mysql
|
||||
- name: smtp
|
||||
defaultConfig:
|
||||
namespace: ghost
|
||||
domain: ghost.{{ .cloud.domain }}
|
||||
storage: 2Gi
|
||||
db:
|
||||
host: '{{ .apps.mysql.host }}'
|
||||
port: '3306'
|
||||
name: ghost
|
||||
user: ghost
|
||||
smtp:
|
||||
host: '{{ .apps.smtp.host }}'
|
||||
port: '{{ .apps.smtp.port }}'
|
||||
from: '{{ .apps.smtp.from }}'
|
||||
user: '{{ .apps.smtp.user }}'
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
- key: smtpPassword
|
||||
requiredSecrets:
|
||||
- mysql.rootPassword
|
||||
4
ghost/versions/6/namespace.yaml
Normal file
4
ghost/versions/6/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
11
ghost/versions/6/pvc.yaml
Normal file
11
ghost/versions/6/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ghost-data
|
||||
namespace: ghost
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
14
ghost/versions/6/service.yaml
Normal file
14
ghost/versions/6/service.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ghost
|
||||
namespace: ghost
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: 2368
|
||||
selector:
|
||||
component: web
|
||||
@@ -3,4 +3,4 @@ is: gitea
|
||||
description: Gitea is a painless self-hosted Git service written in Go
|
||||
category: developer
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/gitea.svg
|
||||
latest: "1"
|
||||
latest: "28"
|
||||
|
||||
85
gitea/versions/28/README.md
Normal file
85
gitea/versions/28/README.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Gitea Configuration
|
||||
|
||||
This Gitea deployment uses a hybrid configuration approach combining environment variables with Gitea's self-managed configuration file.
|
||||
|
||||
## Configuration Architecture
|
||||
|
||||
### Environment Variables (gitea.env)
|
||||
Non-secret configuration is stored in `gitea.env` and automatically loaded via kustomize's `configMapGenerator`. This includes:
|
||||
- Server settings (domain, URLs, ports)
|
||||
- Database connection details (except password)
|
||||
- SMTP settings (except password)
|
||||
- Service settings (registration, notifications)
|
||||
- Repository and storage paths
|
||||
|
||||
### Kubernetes Secrets (gitea-secrets)
|
||||
Sensitive configuration is stored in the `gitea-secrets` secret and managed by the wild-cloud deployment system:
|
||||
- `adminPassword` - Gitea admin user password
|
||||
- `secretKey` - Application secret key
|
||||
- `jwtSecret` - JWT signing secret
|
||||
- `dbPassword` - Database password
|
||||
- `smtpPassword` - SMTP authentication password
|
||||
|
||||
Secrets are defined in `secrets.yaml` and listed in `manifest.yaml` under `defaultSecrets`. When deploying, the system automatically ensures all required secrets exist in the `gitea-secrets` secret before deployment.
|
||||
|
||||
### Persistent Configuration (app.ini)
|
||||
Gitea manages its own `app.ini` file on persistent storage for:
|
||||
- Generated security tokens
|
||||
- Runtime configuration changes made via web UI
|
||||
- Database migration state
|
||||
- User-modified settings
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Startup**: Kustomize generates a ConfigMap from `gitea.env`
|
||||
2. **Environment Loading**: Pod loads non-secret config from ConfigMap via `envFrom`
|
||||
3. **Secret Loading**: Pod loads sensitive config from Kubernetes secrets via `env`
|
||||
4. **Configuration Merge**: Gitea's environment-to-ini process merges environment variables into `app.ini`
|
||||
5. **Persistence**: Gitea writes the merged configuration plus generated tokens to persistent storage
|
||||
|
||||
## Making Configuration Changes
|
||||
|
||||
### Non-Secret Settings
|
||||
1. Edit `gitea.env` with your changes
|
||||
2. Deploy the app via the web app, CLI, or API to apply changes
|
||||
3. Pod will restart and pick up new configuration
|
||||
|
||||
### Secret Settings
|
||||
1. Edit `secrets.yaml` with your secret values
|
||||
2. Ensure the secret key is listed in `manifest.yaml` under `defaultSecrets`
|
||||
3. Deploy the app via the web app, CLI, or API - this will automatically update the `gitea-secrets` secret and restart the pod
|
||||
|
||||
### Web UI Changes
|
||||
Configuration changes made through Gitea's admin web interface are automatically persisted to the `app.ini` file on persistent storage and will survive pod restarts.
|
||||
|
||||
## Configuration Precedence
|
||||
|
||||
1. **Kubernetes Secrets** (highest priority)
|
||||
2. **Environment Variables** (from gitea.env)
|
||||
3. **Persistent app.ini** (lowest priority)
|
||||
|
||||
Environment variables override file settings, and secrets override everything.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Current Configuration
|
||||
```bash
|
||||
# View environment variables
|
||||
kubectl describe pod -n gitea -l app=gitea | grep -A 20 "Environment"
|
||||
|
||||
# View current app.ini
|
||||
kubectl exec -it deployment/gitea -n gitea -- cat /data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
### Configuration Not Applied
|
||||
- Verify the ConfigMap was generated: `kubectl get configmap -n gitea`
|
||||
- Check pod restart: `kubectl get pods -n gitea`
|
||||
- Review startup logs: `kubectl logs -n gitea -l app=gitea`
|
||||
|
||||
|
||||
## External Dependencies
|
||||
|
||||
- **Database**: PostgreSQL instance in `postgres` namespace
|
||||
- **Storage**: Longhorn distributed storage
|
||||
- **Ingress**: Traefik with Let's Encrypt certificates
|
||||
- **DNS**: External-DNS with Cloudflare integration
|
||||
51
gitea/versions/28/db-init-job.yaml
Normal file
51
gitea/versions/28/db-init-job.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: gitea-db-init
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
containers:
|
||||
- name: db-init
|
||||
image: postgres:17
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres <<EOF
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USERNAME}') THEN
|
||||
CREATE USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
ELSE
|
||||
ALTER USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
SELECT 'CREATE DATABASE ${DB_DATABASE_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_DATABASE_NAME}')\gexec
|
||||
ALTER DATABASE ${DB_DATABASE_NAME} OWNER TO ${DB_USERNAME};
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${DB_DATABASE_NAME} TO ${DB_USERNAME};
|
||||
EOF
|
||||
env:
|
||||
- name: POSTGRES_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secrets
|
||||
key: password
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_DATABASE_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: dbPassword
|
||||
restartPolicy: OnFailure
|
||||
99
gitea/versions/28/deployment.yaml
Normal file
99
gitea/versions/28/deployment.yaml
Normal file
@@ -0,0 +1,99 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: gitea
|
||||
component: web
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- name: gitea
|
||||
image: "gitea/gitea:28.2.0"
|
||||
imagePullPolicy: IfNotPresent
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: gitea-env
|
||||
env:
|
||||
- name: GITEA_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: adminPassword
|
||||
- name: GITEA__security__SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: secretKey
|
||||
- name: GITEA__security__INTERNAL_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: jwtSecret
|
||||
- name: GITEA__database__PASSWD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: dbPassword
|
||||
- name: GITEA__mailer__PASSWD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: gitea-secrets
|
||||
key: smtpPassword
|
||||
ports:
|
||||
- name: ssh
|
||||
containerPort: 2222
|
||||
- name: http
|
||||
containerPort: 3000
|
||||
livenessProbe:
|
||||
failureThreshold: 10
|
||||
initialDelaySeconds: 200
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: http
|
||||
timeoutSeconds: 1
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: http
|
||||
timeoutSeconds: 1
|
||||
resources:
|
||||
{}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
readOnlyRootFilesystem: false
|
||||
volumeMounts:
|
||||
- name: temp
|
||||
mountPath: /tmp
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: temp
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: gitea-data
|
||||
60
gitea/versions/28/gitea.env
Normal file
60
gitea/versions/28/gitea.env
Normal file
@@ -0,0 +1,60 @@
|
||||
SSH_LISTEN_PORT=2222
|
||||
SSH_PORT=22
|
||||
GITEA_WORK_DIR=/data
|
||||
GITEA_TEMP=/tmp/gitea
|
||||
TMPDIR=/tmp/gitea
|
||||
GITEA_ADMIN_USERNAME={{ .adminUser }}
|
||||
GITEA_ADMIN_PASSWORD_MODE=keepUpdated
|
||||
|
||||
# Core app settings
|
||||
GITEA____APP_NAME={{ .appName }}
|
||||
GITEA____RUN_MODE=prod
|
||||
GITEA____RUN_USER=git
|
||||
|
||||
# Security settings
|
||||
GITEA__security__INSTALL_LOCK=true
|
||||
GITEA__security__PASSWORD_HASH_ALGO=pbkdf2
|
||||
|
||||
# Database settings (except password which comes from secret)
|
||||
GITEA__database__DB_TYPE=postgres
|
||||
GITEA__database__HOST={{ .db.host }}:{{ .db.port }}
|
||||
GITEA__database__NAME={{ .db.name }}
|
||||
GITEA__database__USER={{ .db.user }}
|
||||
GITEA__database__SSL_MODE=disable
|
||||
GITEA__database__LOG_SQL=false
|
||||
|
||||
# Server settings
|
||||
GITEA__server__DOMAIN={{ .domain }}
|
||||
GITEA__server__HTTP_PORT=3000
|
||||
GITEA__server__ROOT_URL=https://{{ .domain }}/
|
||||
GITEA__server__DISABLE_SSH=false
|
||||
GITEA__server__SSH_DOMAIN={{ .domain }}
|
||||
GITEA__server__SSH_PORT=22
|
||||
GITEA__server__SSH_LISTEN_PORT=2222
|
||||
GITEA__server__LFS_START_SERVER=true
|
||||
GITEA__server__OFFLINE_MODE=true
|
||||
|
||||
# Service settings
|
||||
GITEA__service__REGISTER_EMAIL_CONFIRM=true
|
||||
GITEA__service__DISABLE_REGISTRATION=false
|
||||
GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION=false
|
||||
GITEA__service__ENABLE_NOTIFY_MAIL=true
|
||||
GITEA__service__ENABLE_BASIC_AUTHENTICATION=false
|
||||
GITEA__service__ENABLE_REVERSE_PROXY_AUTHENTICATION=false
|
||||
GITEA__service__ENABLE_CAPTCHA=false
|
||||
GITEA__service__REQUIRE_SIGNIN_VIEW=false
|
||||
GITEA__service__DEFAULT_KEEP_EMAIL_PRIVATE=false
|
||||
GITEA__service__DEFAULT_ALLOW_CREATE_ORGANIZATION=true
|
||||
GITEA__service__DEFAULT_ENABLE_TIMETRACKING=true
|
||||
GITEA__service__NO_REPLY_ADDRESS=noreply.localhost
|
||||
|
||||
# Webhook settings
|
||||
GITEA__webhook__ALLOWED_HOST_LIST=*
|
||||
|
||||
# Mailer settings (enabled via env vars, password from secret)
|
||||
GITEA__mailer__ENABLED=true
|
||||
GITEA__mailer__SMTP_ADDR={{ .smtp.host }}
|
||||
GITEA__mailer__SMTP_PORT={{ .smtp.port }}
|
||||
GITEA__mailer__FROM={{ .smtp.from }}
|
||||
GITEA__mailer__USER={{ .smtp.user }}
|
||||
|
||||
18
gitea/versions/28/ingress.yaml
Normal file
18
gitea/versions/28/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: gitea-public
|
||||
namespace: gitea
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: "{{ .domain }}"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: gitea-http
|
||||
port:
|
||||
number: 3000
|
||||
20
gitea/versions/28/kustomization.yaml
Normal file
20
gitea/versions/28/kustomization.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: gitea
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: gitea
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- pvc.yaml
|
||||
- db-init-job.yaml
|
||||
configMapGenerator:
|
||||
- name: gitea-env
|
||||
envs:
|
||||
- gitea.env
|
||||
29
gitea/versions/28/manifest.yaml
Normal file
29
gitea/versions/28/manifest.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
version: 28.2.0
|
||||
requires:
|
||||
- name: postgres
|
||||
- name: smtp
|
||||
defaultConfig:
|
||||
namespace: gitea
|
||||
appName: Gitea
|
||||
domain: gitea.{{ .cloud.domain }}
|
||||
storage: 2Gi
|
||||
adminUser: admin
|
||||
adminEmail: '{{ .operator.email }}'
|
||||
db:
|
||||
name: gitea
|
||||
user: gitea
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
smtp:
|
||||
host: '{{ .apps.smtp.host }}'
|
||||
port: '{{ .apps.smtp.port }}'
|
||||
user: '{{ .apps.smtp.user }}'
|
||||
from: '{{ .apps.smtp.from }}'
|
||||
defaultSecrets:
|
||||
- key: adminPassword
|
||||
- key: dbPassword
|
||||
- key: secretKey
|
||||
- key: jwtSecret
|
||||
- key: smtpPassword
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
4
gitea/versions/28/namespace.yaml
Normal file
4
gitea/versions/28/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
12
gitea/versions/28/pvc.yaml
Normal file
12
gitea/versions/28/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: gitea-data
|
||||
namespace: gitea
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: longhorn
|
||||
resources:
|
||||
requests:
|
||||
storage: "{{ .storage }}"
|
||||
28
gitea/versions/28/service.yaml
Normal file
28
gitea/versions/28/service.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-http
|
||||
namespace: gitea
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 3000
|
||||
targetPort: 3000
|
||||
selector:
|
||||
component: web
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-ssh
|
||||
namespace: gitea
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- name: ssh
|
||||
port: 22
|
||||
targetPort: 2222
|
||||
protocol: TCP
|
||||
selector:
|
||||
component: web
|
||||
@@ -3,4 +3,4 @@ is: immich
|
||||
description: Immich is a self-hosted photo and video backup solution that allows you to store, manage, and share your media files securely.
|
||||
category: media
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/immich.svg
|
||||
latest: "1"
|
||||
latest: "3"
|
||||
|
||||
41
immich/versions/3/README.md
Normal file
41
immich/versions/3/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Immich
|
||||
|
||||
Immich is a self-hosted photo and video backup solution that allows you to store, manage, and share your media files securely. It provides a mobile-first experience similar to Google Photos.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing metadata and search indexes
|
||||
- **Redis** - Used for caching and background job queuing
|
||||
|
||||
## Components
|
||||
|
||||
Immich runs two services:
|
||||
|
||||
- **Server** - Main API and web server
|
||||
- **Machine Learning** - Handles facial recognition and smart search
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings configured through your instance's `config.yaml`:
|
||||
|
||||
- **domain** - Where Immich will be accessible (default: `immich.{your-cloud-domain}`)
|
||||
- **storage** - Persistent volume for photos and videos (default: `250Gi`)
|
||||
- **cacheStorage** - Persistent volume for ML cache (default: `10Gi`)
|
||||
- **timezone** - Server timezone (default: `UTC`)
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, Immich will be available at:
|
||||
- `https://immich.{your-cloud-domain}`
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add immich
|
||||
wild app deploy immich
|
||||
```
|
||||
|
||||
2. Create your account through the web interface
|
||||
|
||||
3. Download the Immich mobile app and connect it to your server for automatic photo backup
|
||||
68
immich/versions/3/db-init-job.yaml
Normal file
68
immich/versions/3/db-init-job.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: immich-db-init
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: db-init
|
||||
image: postgres:17
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres <<EOF
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USERNAME}') THEN
|
||||
CREATE USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
ELSE
|
||||
ALTER USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
SELECT 'CREATE DATABASE ${DB_DATABASE_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_DATABASE_NAME}')\gexec
|
||||
ALTER DATABASE ${DB_DATABASE_NAME} OWNER TO ${DB_USERNAME};
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${DB_DATABASE_NAME} TO ${DB_USERNAME};
|
||||
EOF
|
||||
|
||||
# Connect to the immich database and enable required extensions
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres -d ${DB_DATABASE_NAME} <<EOF
|
||||
DO \$\$
|
||||
BEGIN
|
||||
-- Create vector extension if it doesn't exist
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'vector') THEN
|
||||
CREATE EXTENSION vector;
|
||||
END IF;
|
||||
|
||||
-- Create cube extension if it doesn't exist
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'cube') THEN
|
||||
CREATE EXTENSION cube;
|
||||
END IF;
|
||||
|
||||
-- Create earthdistance extension if it doesn't exist (depends on cube)
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'earthdistance') THEN
|
||||
CREATE EXTENSION earthdistance;
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
EOF
|
||||
env:
|
||||
- name: POSTGRES_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: postgres.password
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_DATABASE_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: dbPassword
|
||||
restartPolicy: OnFailure
|
||||
45
immich/versions/3/deployment-machine-learning.yaml
Normal file
45
immich/versions/3/deployment-machine-learning.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: immich-machine-learning
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: immich-machine-learning
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: immich-machine-learning
|
||||
component: machine-learning
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- image: "ghcr.io/immich-app/immich-machine-learning:v3.3.5"
|
||||
name: immich-machine-learning
|
||||
ports:
|
||||
- containerPort: 3003
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: TZ
|
||||
value: "UTC"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
readOnlyRootFilesystem: false
|
||||
volumeMounts:
|
||||
- mountPath: /cache
|
||||
name: immich-cache
|
||||
readOnly: false
|
||||
volumes:
|
||||
- name: immich-cache
|
||||
persistentVolumeClaim:
|
||||
claimName: immich-cache-pvc
|
||||
68
immich/versions/3/deployment-microservices.yaml
Normal file
68
immich/versions/3/deployment-microservices.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: immich-microservices
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: immich-microservices
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: immich-microservices
|
||||
component: microservices
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- image: "ghcr.io/immich-app/immich-server:v3.3.5"
|
||||
name: immich-microservices
|
||||
env:
|
||||
- name: REDIS_HOSTNAME
|
||||
value: "{{ .redis.host }}"
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: redis.password
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: dbPassword
|
||||
- name: TZ
|
||||
value: "UTC"
|
||||
- name: IMMICH_WORKERS_EXCLUDE
|
||||
value: api
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
readOnlyRootFilesystem: false
|
||||
volumeMounts:
|
||||
- mountPath: /usr/src/app/upload
|
||||
name: immich-storage
|
||||
readOnly: false
|
||||
volumes:
|
||||
- name: immich-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: immich-pvc
|
||||
affinity:
|
||||
podAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
app: immich
|
||||
component: server
|
||||
topologyKey: kubernetes.io/hostname
|
||||
63
immich/versions/3/deployment-server.yaml
Normal file
63
immich/versions/3/deployment-server.yaml
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: immich-server
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: immich-server
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: immich-server
|
||||
component: server
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- image: "ghcr.io/immich-app/immich-server:v3.3.5"
|
||||
name: immich-server
|
||||
ports:
|
||||
- containerPort: 2283
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: REDIS_HOSTNAME
|
||||
value: "{{ .redis.host }}"
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: redis.password
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: immich-secrets
|
||||
key: dbPassword
|
||||
- name: TZ
|
||||
value: "UTC"
|
||||
- name: IMMICH_WORKERS_EXCLUDE
|
||||
value: microservices
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
readOnlyRootFilesystem: false
|
||||
volumeMounts:
|
||||
- mountPath: /usr/src/app/upload
|
||||
name: immich-storage
|
||||
readOnly: false
|
||||
volumes:
|
||||
- name: immich-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: immich-pvc
|
||||
18
immich/versions/3/ingress.yaml
Normal file
18
immich/versions/3/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: immich-public
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: "{{ .domain }}"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: immich-server
|
||||
port:
|
||||
number: 3001
|
||||
18
immich/versions/3/kustomization.yaml
Normal file
18
immich/versions/3/kustomization.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: immich
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: immich
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- deployment-server.yaml
|
||||
- deployment-machine-learning.yaml
|
||||
- deployment-microservices.yaml
|
||||
- ingress.yaml
|
||||
- namespace.yaml
|
||||
- pvc.yaml
|
||||
- service.yaml
|
||||
- db-init-job.yaml
|
||||
20
immich/versions/3/manifest.yaml
Normal file
20
immich/versions/3/manifest.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
version: 3.3.5
|
||||
requires:
|
||||
- name: redis
|
||||
- name: postgres
|
||||
defaultConfig:
|
||||
namespace: immich
|
||||
storage: 5Gi
|
||||
cacheStorage: 5Gi
|
||||
domain: immich.{{ .cloud.domain }}
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
name: immich
|
||||
user: immich
|
||||
redis:
|
||||
host: '{{ .apps.redis.host }}'
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
requiredSecrets:
|
||||
- redis.password
|
||||
- postgres.password
|
||||
4
immich/versions/3/namespace.yaml
Normal file
4
immich/versions/3/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
24
immich/versions/3/pvc.yaml
Normal file
24
immich/versions/3/pvc.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: immich-pvc
|
||||
spec:
|
||||
storageClassName: longhorn
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: immich-cache-pvc
|
||||
spec:
|
||||
storageClassName: longhorn
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .cacheStorage }}
|
||||
33
immich/versions/3/service.yaml
Normal file
33
immich/versions/3/service.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: immich-server
|
||||
namespace: immich
|
||||
labels:
|
||||
app: immich-server
|
||||
spec:
|
||||
ports:
|
||||
- port: 3001
|
||||
targetPort: 2283
|
||||
selector:
|
||||
app: immich
|
||||
component: server
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: immich-machine-learning
|
||||
namespace: immich
|
||||
labels:
|
||||
app: immich-machine-learning
|
||||
spec:
|
||||
ports:
|
||||
- port: 3003
|
||||
selector:
|
||||
app: immich
|
||||
component: machine-learning
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
@@ -3,4 +3,4 @@ is: listmonk
|
||||
description: Listmonk is a standalone, self-hosted, newsletter and mailing list manager. It is fast, feature-rich, and packed into a single binary.
|
||||
category: communication
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/listmonk.svg
|
||||
latest: "5"
|
||||
latest: "6"
|
||||
|
||||
31
listmonk/versions/6/README.md
Normal file
31
listmonk/versions/6/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Listmonk
|
||||
|
||||
Listmonk is a standalone, self-hosted newsletter and mailing list manager. It is fast, feature-rich, and packed into a single binary.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing subscribers and campaigns
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings configured through your instance's `config.yaml`:
|
||||
|
||||
- **domain** - Where Listmonk will be accessible (default: `listmonk.{your-cloud-domain}`)
|
||||
- **storage** - Persistent volume size (default: `1Gi`)
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, Listmonk will be available at:
|
||||
- `https://listmonk.{your-cloud-domain}`
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add listmonk
|
||||
wild app deploy listmonk
|
||||
```
|
||||
|
||||
2. Log in to the admin interface and configure your SMTP settings for sending emails
|
||||
|
||||
3. Create your first mailing list and start adding subscribers
|
||||
66
listmonk/versions/6/db-init-job.yaml
Normal file
66
listmonk/versions/6/db-init-job.yaml
Normal file
@@ -0,0 +1,66 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: listmonk-db-init
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: postgres-init
|
||||
image: postgres:15
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
env:
|
||||
- name: PGHOST
|
||||
value: {{ .db.host }}
|
||||
- name: PGUSER
|
||||
value: postgres
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: listmonk-secrets
|
||||
key: postgres.password
|
||||
- name: DB_NAME
|
||||
value: {{ .db.name }}
|
||||
- name: DB_USER
|
||||
value: {{ .db.user }}
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: listmonk-secrets
|
||||
key: dbPassword
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
until pg_isready; do
|
||||
echo "PostgreSQL is not ready - sleeping"
|
||||
sleep 2
|
||||
done
|
||||
echo "PostgreSQL is ready"
|
||||
|
||||
echo "Creating database and user for Listmonk..."
|
||||
psql -c "CREATE DATABASE ${DB_NAME};" || echo "Database ${DB_NAME} already exists"
|
||||
psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" || echo "User ${DB_USER} already exists"
|
||||
psql -c "ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';"
|
||||
psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};"
|
||||
psql -d ${DB_NAME} -c "GRANT ALL ON SCHEMA public TO ${DB_USER};"
|
||||
echo "Database initialization complete"
|
||||
88
listmonk/versions/6/deployment.yaml
Normal file
88
listmonk/versions/6/deployment.yaml
Normal file
@@ -0,0 +1,88 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: listmonk
|
||||
namespace: listmonk
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: web
|
||||
spec:
|
||||
securityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: listmonk
|
||||
image: listmonk/listmonk:v6.1.0
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "./listmonk --install --idempotent --yes && ./listmonk --upgrade --yes && ./listmonk"]
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 9000
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: LISTMONK_app__address
|
||||
value: "0.0.0.0:9000"
|
||||
- name: LISTMONK_app__root_url
|
||||
value: "https://{{ .domain }}"
|
||||
- name: LISTMONK_db__host
|
||||
value: {{ .db.host }}
|
||||
- name: LISTMONK_db__port
|
||||
value: "{{ .db.port }}"
|
||||
- name: LISTMONK_db__user
|
||||
value: {{ .db.user }}
|
||||
- name: LISTMONK_db__database
|
||||
value: {{ .db.name }}
|
||||
- name: LISTMONK_db__ssl_mode
|
||||
value: disable
|
||||
- name: LISTMONK_db__password
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: listmonk-secrets
|
||||
key: dbPassword
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
ephemeral-storage: 1Gi
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 128Mi
|
||||
volumeMounts:
|
||||
- name: listmonk-data
|
||||
mountPath: /listmonk/data
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 9000
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 5
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 9000
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
volumes:
|
||||
- name: listmonk-data
|
||||
persistentVolumeClaim:
|
||||
claimName: listmonk-data
|
||||
restartPolicy: Always
|
||||
18
listmonk/versions/6/ingress.yaml
Normal file
18
listmonk/versions/6/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: listmonk
|
||||
namespace: listmonk
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: {{ .domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: listmonk
|
||||
port:
|
||||
number: 80
|
||||
16
listmonk/versions/6/kustomization.yaml
Normal file
16
listmonk/versions/6/kustomization.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: listmonk
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: listmonk
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- db-init-job.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- pvc.yaml
|
||||
19
listmonk/versions/6/manifest.yaml
Normal file
19
listmonk/versions/6/manifest.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
version: 6.1.0
|
||||
requires:
|
||||
- name: postgres
|
||||
defaultConfig:
|
||||
namespace: listmonk
|
||||
domain: listmonk.{{ .cloud.domain }}
|
||||
storage: 1Gi
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
name: listmonk
|
||||
user: listmonk
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
- key: dbUrl
|
||||
default: postgres://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host
|
||||
}}:{{ .app.db.port }}/{{ .app.db.name }}?sslmode=disable
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
4
listmonk/versions/6/namespace.yaml
Normal file
4
listmonk/versions/6/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
11
listmonk/versions/6/pvc.yaml
Normal file
11
listmonk/versions/6/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: listmonk-data
|
||||
namespace: listmonk
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
14
listmonk/versions/6/service.yaml
Normal file
14
listmonk/versions/6/service.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: listmonk
|
||||
namespace: listmonk
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
component: web
|
||||
@@ -4950,7 +4950,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: longhorn-manager
|
||||
image: longhornio/longhorn-manager:v1.8.1
|
||||
image: longhornio/longhorn-manager:v1.13.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
privileged: true
|
||||
@@ -4963,13 +4963,13 @@ spec:
|
||||
- --instance-manager-image
|
||||
- "longhornio/longhorn-instance-manager:v1.8.1"
|
||||
- --share-manager-image
|
||||
- "longhornio/longhorn-share-manager:v1.8.1"
|
||||
- "longhornio/longhorn-share-manager:v1.13.0"
|
||||
- --backing-image-manager-image
|
||||
- "longhornio/backing-image-manager:v1.8.1"
|
||||
- --support-bundle-manager-image
|
||||
- "longhornio/support-bundle-kit:v0.0.52"
|
||||
- --manager-image
|
||||
- "longhornio/longhorn-manager:v1.8.1"
|
||||
- "longhornio/longhorn-manager:v1.13.0"
|
||||
- --service-account
|
||||
- longhorn-service-account
|
||||
- --upgrade-version-check
|
||||
@@ -5023,7 +5023,7 @@ spec:
|
||||
fieldPath: spec.nodeName
|
||||
- name: pre-pull-share-manager-image
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: longhornio/longhorn-share-manager:v1.8.1
|
||||
image: longhornio/longhorn-share-manager:v1.13.0
|
||||
command: ["sh", "-c", "echo share-manager image pulled && sleep infinity"]
|
||||
volumes:
|
||||
- name: boot
|
||||
@@ -5076,18 +5076,18 @@ spec:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: wait-longhorn-manager
|
||||
image: longhornio/longhorn-manager:v1.8.1
|
||||
image: longhornio/longhorn-manager:v1.13.0
|
||||
command: ['sh', '-c', 'while [ $(curl -m 1 -s -o /dev/null -w "%{http_code}" http://longhorn-backend:9500/v1) != "200" ]; do echo waiting; sleep 2; done']
|
||||
containers:
|
||||
- name: longhorn-driver-deployer
|
||||
image: longhornio/longhorn-manager:v1.8.1
|
||||
image: longhornio/longhorn-manager:v1.13.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- longhorn-manager
|
||||
- -d
|
||||
- deploy-driver
|
||||
- --manager-image
|
||||
- "longhornio/longhorn-manager:v1.8.1"
|
||||
- "longhornio/longhorn-manager:v1.13.0"
|
||||
- --manager-url
|
||||
- http://longhorn-backend:9500/v1
|
||||
env:
|
||||
@@ -5159,7 +5159,7 @@ spec:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers:
|
||||
- name: longhorn-ui
|
||||
image: longhornio/longhorn-ui:v1.8.1
|
||||
image: longhornio/longhorn-ui:v1.13.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- name : nginx-cache
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v1.8.1-5
|
||||
version: v1.13.0
|
||||
deploymentName: longhorn-ui
|
||||
requires:
|
||||
- name: nfs
|
||||
|
||||
@@ -3,4 +3,4 @@ is: mattermost
|
||||
description: Mattermost is a self-hosted, open-source team messaging platform offering secure channels, file sharing, and integrations as a Slack alternative.
|
||||
category: communication
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mattermost.svg
|
||||
latest: "10"
|
||||
latest: "12"
|
||||
|
||||
33
mattermost/versions/12/README.md
Normal file
33
mattermost/versions/12/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Mattermost
|
||||
|
||||
Mattermost is an open-source team messaging platform, a self-hosted alternative to Slack.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing messages and team data
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings in `config.yaml`:
|
||||
|
||||
- **domain** - Where Mattermost will be accessible
|
||||
- **storage** - Persistent volume size (default: `2Gi`)
|
||||
- **db.name** - Database name (default: `mattermost`)
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add mattermost
|
||||
wild app deploy mattermost
|
||||
```
|
||||
|
||||
2. Visit the app URL — on first load you will be prompted to create an administrator account (email + password).
|
||||
|
||||
3. After creating the admin account, complete the onboarding wizard to set up your first team.
|
||||
|
||||
## Notes
|
||||
|
||||
- The setup wizard only runs on first launch
|
||||
- Email invitations require SMTP to be configured in **System Console → Environment → SMTP**
|
||||
- Push notifications for mobile apps require a push proxy (or Mattermost Cloud push notification service)
|
||||
59
mattermost/versions/12/db-init-job.yaml
Normal file
59
mattermost/versions/12/db-init-job.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: mattermost-db-init
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: postgres-init
|
||||
image: postgres:15
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
env:
|
||||
- name: PGHOST
|
||||
value: {{ .db.host }}
|
||||
- name: PGUSER
|
||||
value: postgres
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mattermost-secrets
|
||||
key: postgres.password
|
||||
- name: DB_NAME
|
||||
value: {{ .db.name }}
|
||||
- name: DB_USER
|
||||
value: {{ .db.user }}
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mattermost-secrets
|
||||
key: dbPassword
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
until pg_isready; do sleep 2; done
|
||||
psql -c "CREATE DATABASE ${DB_NAME};" || echo "Database already exists"
|
||||
psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" || echo "User already exists"
|
||||
psql -c "ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';"
|
||||
psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};"
|
||||
psql -d ${DB_NAME} -c "GRANT ALL ON SCHEMA public TO ${DB_USER};"
|
||||
echo "Done"
|
||||
93
mattermost/versions/12/deployment.yaml
Normal file
93
mattermost/versions/12/deployment.yaml
Normal file
@@ -0,0 +1,93 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mattermost
|
||||
namespace: mattermost
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
component: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: web
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 2000
|
||||
runAsGroup: 2000
|
||||
fsGroup: 2000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: mattermost
|
||||
image: mattermost/mattermost-team-edition:12.0.1
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8065
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: MM_SERVICESETTINGS_SITEURL
|
||||
value: https://{{ .domain }}
|
||||
- name: MM_SQLSETTINGS_DRIVERNAME
|
||||
value: postgres
|
||||
- name: MM_SQLSETTINGS_DATASOURCE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mattermost-secrets
|
||||
key: dbUrl
|
||||
- name: MM_FILESETTINGS_DIRECTORY
|
||||
value: /mattermost/data/
|
||||
- name: MM_PLUGINSETTINGS_PLUGINDIRECTORY
|
||||
value: /mattermost/plugins
|
||||
- name: MM_CLIENTPLUGINSSETTINGS_PLUGINDIRECTORY
|
||||
value: /mattermost/client/plugins
|
||||
- name: MM_LOGSETTINGS_CONSOLELEVEL
|
||||
value: INFO
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
ephemeral-storage: 1Gi
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 50m
|
||||
ephemeral-storage: 50Mi
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: mattermost-data
|
||||
mountPath: /mattermost/data
|
||||
- name: mattermost-plugins
|
||||
mountPath: /mattermost/plugins
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/v4/system/ping
|
||||
port: 8065
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
periodSeconds: 15
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/v4/system/ping
|
||||
port: 8065
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
volumes:
|
||||
- name: mattermost-data
|
||||
persistentVolumeClaim:
|
||||
claimName: mattermost-data
|
||||
- name: mattermost-plugins
|
||||
persistentVolumeClaim:
|
||||
claimName: mattermost-plugins
|
||||
restartPolicy: Always
|
||||
18
mattermost/versions/12/ingress.yaml
Normal file
18
mattermost/versions/12/ingress.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mattermost
|
||||
namespace: mattermost
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: {{ .domain }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: mattermost
|
||||
port:
|
||||
number: 80
|
||||
16
mattermost/versions/12/kustomization.yaml
Normal file
16
mattermost/versions/12/kustomization.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: mattermost
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: mattermost
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- db-init-job.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- pvc.yaml
|
||||
19
mattermost/versions/12/manifest.yaml
Normal file
19
mattermost/versions/12/manifest.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
version: 12.0.1
|
||||
requires:
|
||||
- name: postgres
|
||||
defaultConfig:
|
||||
namespace: mattermost
|
||||
domain: mattermost.{{ .cloud.domain }}
|
||||
storage: 2Gi
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
name: mattermost
|
||||
user: mattermost
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
- key: dbUrl
|
||||
default: postgres://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host
|
||||
}}:{{ .app.db.port }}/{{ .app.db.name }}?sslmode=disable&connect_timeout=10
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
4
mattermost/versions/12/namespace.yaml
Normal file
4
mattermost/versions/12/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: mattermost
|
||||
23
mattermost/versions/12/pvc.yaml
Normal file
23
mattermost/versions/12/pvc.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mattermost-data
|
||||
namespace: mattermost
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .storage }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mattermost-plugins
|
||||
namespace: mattermost
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
13
mattermost/versions/12/service.yaml
Normal file
13
mattermost/versions/12/service.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mattermost
|
||||
namespace: mattermost
|
||||
spec:
|
||||
selector:
|
||||
component: web
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8065
|
||||
protocol: TCP
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v0.15.0-1
|
||||
version: v0.16.1
|
||||
deploymentName: controller
|
||||
defaultConfig:
|
||||
namespace: metallb-system
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: 9.1.0-4
|
||||
version: 9.7.4
|
||||
defaultConfig:
|
||||
namespace: mysql
|
||||
host: mysql.mysql.svc.cluster.local
|
||||
|
||||
@@ -29,7 +29,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: mysql
|
||||
image: mysql:9.1.0
|
||||
image: mysql:9.7.4
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
@@ -18,7 +18,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: worker
|
||||
image: registry.k8s.io/nfd/node-feature-discovery:v0.17.3
|
||||
image: registry.k8s.io/nfd/node-feature-discovery:v0.20.1
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v0.17.3
|
||||
version: v0.20.1
|
||||
deploymentName: node-feature-discovery-master
|
||||
defaultConfig:
|
||||
namespace: node-feature-discovery
|
||||
|
||||
@@ -19,7 +19,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: master
|
||||
image: registry.k8s.io/nfd/node-feature-discovery:v0.17.3
|
||||
image: registry.k8s.io/nfd/node-feature-discovery:v0.20.1
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
|
||||
@@ -50,7 +50,7 @@ spec:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- image: nvcr.io/nvidia/k8s-device-plugin:v0.17.1
|
||||
- image: nvcr.io/nvidia/k8s-device-plugin:v0.20.1
|
||||
name: nvidia-device-plugin-ctr
|
||||
env:
|
||||
- name: MPS_ROOT
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v0.17.1-1
|
||||
version: v0.20.1
|
||||
deploymentName: nvidia-device-plugin-daemonset
|
||||
requires:
|
||||
- name: node-feature-discovery
|
||||
|
||||
@@ -3,4 +3,4 @@ is: openproject
|
||||
description: OpenProject is an open-source project management software that provides comprehensive features for project planning, tracking, and collaboration.
|
||||
category: productivity
|
||||
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/openproject.svg
|
||||
latest: "16"
|
||||
latest: "17"
|
||||
|
||||
34
openproject/versions/17/README.md
Normal file
34
openproject/versions/17/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# OpenProject
|
||||
|
||||
OpenProject is an open-source project management software that provides comprehensive features for project planning, tracking, and collaboration.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **PostgreSQL** - Database for storing project data
|
||||
- **Memcached** - Caching layer for improved performance
|
||||
|
||||
## Configuration
|
||||
|
||||
Key settings configured through your instance's `config.yaml`:
|
||||
|
||||
- **domain** - Where OpenProject will be accessible (default: `openproject.{your-cloud-domain}`)
|
||||
- **adminUserEmail** - Admin account email (defaults to your operator email)
|
||||
- **seedLocale** - Default language (default: `en`)
|
||||
- **storage** - Persistent volume size (default: `5Gi`)
|
||||
|
||||
## Access
|
||||
|
||||
After deployment, OpenProject will be available at:
|
||||
- `https://openproject.{your-cloud-domain}`
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Add and deploy the app:
|
||||
```bash
|
||||
wild app add openproject
|
||||
wild app deploy openproject
|
||||
```
|
||||
|
||||
2. Log in with the admin credentials (password reset will be required on first login)
|
||||
|
||||
3. Create your first project and invite team members
|
||||
24
openproject/versions/17/configmap_core.yaml
Normal file
24
openproject/versions/17/configmap_core.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
# Source: openproject/templates/secret_core.yaml
|
||||
apiVersion: "v1"
|
||||
kind: "ConfigMap"
|
||||
metadata:
|
||||
name: "openproject-core"
|
||||
data:
|
||||
DATABASE_HOST: "{{ .db.host }}"
|
||||
DATABASE_PORT: "{{ .db.port }}"
|
||||
DATABASE_NAME: "{{ .db.name }}"
|
||||
DATABASE_USERNAME: "{{ .db.user }}"
|
||||
DATABASE_URL: "postgresql://{{ .db.user }}@{{ .db.host }}:{{ .db.port }}/{{ .db.name }}"
|
||||
OPENPROJECT_SEED_ADMIN_USER_PASSWORD_RESET: "true"
|
||||
OPENPROJECT_SEED_ADMIN_USER_NAME: "{{ .adminUserName }}"
|
||||
OPENPROJECT_SEED_ADMIN_USER_MAIL: "{{ .adminUserEmail }}"
|
||||
OPENPROJECT_HTTPS: "true"
|
||||
OPENPROJECT_SEED_LOCALE: "en"
|
||||
OPENPROJECT_HOST__NAME: "{{ .domain }}"
|
||||
OPENPROJECT_HSTS: "true"
|
||||
OPENPROJECT_RAILS__CACHE__STORE: "memcache"
|
||||
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: ""
|
||||
POSTGRES_STATEMENT_TIMEOUT: "120s"
|
||||
WEB_CONCURRENCY: "1"
|
||||
...
|
||||
9
openproject/versions/17/configmap_memcached.yaml
Normal file
9
openproject/versions/17/configmap_memcached.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Source: openproject/templates/secret_memcached.yaml
|
||||
apiVersion: "v1"
|
||||
kind: "ConfigMap"
|
||||
metadata:
|
||||
name: "openproject-memcached"
|
||||
data:
|
||||
OPENPROJECT_CACHE__MEMCACHE__SERVER: "{{ .memcached.host }}:{{ .memcached.port }}"
|
||||
...
|
||||
51
openproject/versions/17/db-init-job.yaml
Normal file
51
openproject/versions/17/db-init-job.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: openproject-db-init
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: db-init
|
||||
spec:
|
||||
containers:
|
||||
- name: db-init
|
||||
image: postgres:17
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- |
|
||||
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres <<EOF
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USERNAME}') THEN
|
||||
CREATE USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
ELSE
|
||||
ALTER USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
SELECT 'CREATE DATABASE ${DB_DATABASE_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_DATABASE_NAME}')\gexec
|
||||
ALTER DATABASE ${DB_DATABASE_NAME} OWNER TO ${DB_USERNAME};
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${DB_DATABASE_NAME} TO ${DB_USERNAME};
|
||||
EOF
|
||||
env:
|
||||
- name: POSTGRES_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secrets
|
||||
key: password
|
||||
- name: DB_HOSTNAME
|
||||
value: "{{ .db.host }}"
|
||||
- name: DB_DATABASE_NAME
|
||||
value: "{{ .db.name }}"
|
||||
- name: DB_USERNAME
|
||||
value: "{{ .db.user }}"
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openproject-secrets
|
||||
key: dbPassword
|
||||
restartPolicy: OnFailure
|
||||
20
openproject/versions/17/ingress.yaml
Normal file
20
openproject/versions/17/ingress.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# Source: openproject/templates/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: openproject
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: "{{ .domain }}"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: openproject
|
||||
port:
|
||||
name: http
|
||||
...
|
||||
21
openproject/versions/17/kustomization.yaml
Normal file
21
openproject/versions/17/kustomization.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: openproject
|
||||
labels:
|
||||
- includeSelectors: true
|
||||
pairs:
|
||||
app: openproject
|
||||
managedBy: kustomize
|
||||
partOf: wild-cloud
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- serviceaccount.yaml
|
||||
- configmap_core.yaml
|
||||
- configmap_memcached.yaml
|
||||
- persistentvolumeclaim.yaml
|
||||
- service.yaml
|
||||
- db-init-job.yaml
|
||||
- web-deployment.yaml
|
||||
- worker-deployment.yaml
|
||||
- seeder-job.yaml
|
||||
- ingress.yaml
|
||||
23
openproject/versions/17/manifest.yaml
Normal file
23
openproject/versions/17/manifest.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
version: 17.9.3
|
||||
requires:
|
||||
- name: postgres
|
||||
- name: memcached
|
||||
defaultConfig:
|
||||
namespace: openproject
|
||||
storage: 2Gi
|
||||
adminUserName: OpenProject Admin
|
||||
adminUserEmail: '{{ .operator.email }}'
|
||||
domain: openproject.{{ .cloud.domain }}
|
||||
db:
|
||||
host: '{{ .apps.postgres.host }}'
|
||||
port: '{{ .apps.postgres.port }}'
|
||||
name: openproject
|
||||
user: openproject
|
||||
memcached:
|
||||
host: '{{ .apps.memcached.host }}'
|
||||
port: '{{ .apps.memcached.port }}'
|
||||
defaultSecrets:
|
||||
- key: dbPassword
|
||||
- key: adminPassword
|
||||
requiredSecrets:
|
||||
- postgres.password
|
||||
4
openproject/versions/17/namespace.yaml
Normal file
4
openproject/versions/17/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ .namespace }}"
|
||||
12
openproject/versions/17/persistentvolumeclaim.yaml
Normal file
12
openproject/versions/17/persistentvolumeclaim.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
# Source: openproject/templates/persistentvolumeclaim.yaml
|
||||
apiVersion: "v1"
|
||||
kind: "PersistentVolumeClaim"
|
||||
metadata:
|
||||
name: openproject
|
||||
spec:
|
||||
accessModes: [ReadWriteMany]
|
||||
resources:
|
||||
requests:
|
||||
storage: "{{ .storage }}"
|
||||
...
|
||||
138
openproject/versions/17/seeder-job.yaml
Normal file
138
openproject/versions/17/seeder-job.yaml
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
# Source: openproject/templates/seeder-job.yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: openproject-seeder-1
|
||||
labels:
|
||||
component: seeder
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 86400
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: seeder
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
volumes:
|
||||
- name: tmp
|
||||
# we can't use emptyDir due to the sticky bit issue
|
||||
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
||||
ephemeral:
|
||||
volumeClaimTemplate:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
- name: app-tmp
|
||||
# we can't use emptyDir due to the sticky bit / world writable issue
|
||||
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
||||
ephemeral:
|
||||
volumeClaimTemplate:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
- name: "data"
|
||||
persistentVolumeClaim:
|
||||
claimName: openproject
|
||||
initContainers:
|
||||
- name: check-db-ready
|
||||
image: "postgres:17"
|
||||
imagePullPolicy: Always
|
||||
command: [
|
||||
'sh',
|
||||
'-c',
|
||||
'until pg_isready -h $DATABASE_HOST -p $DATABASE_PORT -U openproject; do echo "waiting for database $DATABASE_HOST:$DATABASE_PORT"; sleep 2; done;'
|
||||
]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: openproject-core
|
||||
- configMapRef:
|
||||
name: openproject-memcached
|
||||
env:
|
||||
- name: OPENPROJECT_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openproject-secrets
|
||||
key: dbPassword
|
||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openproject-secrets
|
||||
key: adminPassword
|
||||
resources:
|
||||
limits:
|
||||
memory: 200Mi
|
||||
requests:
|
||||
memory: 200Mi
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /app/tmp
|
||||
name: app-tmp
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: seeder
|
||||
image: "openproject/openproject:17.9.3-slim"
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- bash
|
||||
- /app/docker/prod/seeder
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: openproject-core
|
||||
- configMapRef:
|
||||
name: openproject-memcached
|
||||
env:
|
||||
- name: OPENPROJECT_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openproject-secrets
|
||||
key: dbPassword
|
||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openproject-secrets
|
||||
key: adminPassword
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /app/tmp
|
||||
name: app-tmp
|
||||
- name: "data"
|
||||
mountPath: "/var/openproject/assets"
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
restartPolicy: OnFailure
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user