v2 app deployment--templating mainly in manifest now.
This commit is contained in:
143
ADDING-APPS.md
143
ADDING-APPS.md
@@ -26,8 +26,9 @@ description: Immich is a self-hosted photo and video backup solution that allows
|
|||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
icon: https://immich.app/assets/images/logo.png
|
icon: https://immich.app/assets/images/logo.png
|
||||||
requires:
|
requires:
|
||||||
- name: redis
|
- name: pg
|
||||||
- name: postgres
|
alias: db # Use a different reference name in templates
|
||||||
|
- name: redis # 'alias' and 'installedAs' default to 'name' value
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
serverImage: ghcr.io/immich-app/immich-server:release
|
serverImage: ghcr.io/immich-app/immich-server:release
|
||||||
mlImage: ghcr.io/immich-app/immich-machine-learning:release
|
mlImage: ghcr.io/immich-app/immich-machine-learning:release
|
||||||
@@ -36,13 +37,21 @@ defaultConfig:
|
|||||||
mlPort: 3003
|
mlPort: 3003
|
||||||
storage: 250Gi
|
storage: 250Gi
|
||||||
cacheStorage: 10Gi
|
cacheStorage: 10Gi
|
||||||
redisHostname: redis.redis.svc.cluster.local
|
redisHostname: "{{ .apps.redis.host }}" # Can reference 'requires' app configurations
|
||||||
dbHostname: postgres.postgres.svc.cluster.local
|
dbHostname: "{{ .apps.pg.host }}"
|
||||||
dbUsername: immich
|
db: # Configuration can be nested
|
||||||
|
name: immich
|
||||||
|
user: immich
|
||||||
|
host: "{{ .apps.pg.host }}"
|
||||||
|
port: "{{ .apps.pg.port }}"
|
||||||
domain: immich.{{ .cloud.domain }}
|
domain: immich.{{ .cloud.domain }}
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- apps.immich.dbPassword
|
- key: password # Random value will be generated if empty
|
||||||
- apps.postgres.password
|
- key: dbUrl
|
||||||
|
default: "postgresql://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host }}:{{ .app.db.port }}/{{ .app.db.name }}?pool=30" # Can reference secrets and config as long as they have been defined before this line. Reference config with {{ .app.? }} and secrets with {{ .secrets.? }}
|
||||||
|
requiredSecrets:
|
||||||
|
- db.password # References postgres app via 'db' alias
|
||||||
|
- redis.auth # References redis app via 'redis' name (no alias)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Manifest Fields
|
#### Manifest Fields
|
||||||
@@ -53,11 +62,31 @@ defaultSecrets:
|
|||||||
| `description` | Yes | Brief app description shown in listings |
|
| `description` | Yes | Brief app description shown in listings |
|
||||||
| `version` | Yes | App version (follow upstream versioning) |
|
| `version` | Yes | App version (follow upstream versioning) |
|
||||||
| `icon` | No | URL to app icon for UI display |
|
| `icon` | No | URL to app icon for UI display |
|
||||||
| `requires` | No | List of dependency apps (e.g., `postgres`, `redis`) |
|
| `requires` | No | List of dependency apps with optional aliases |
|
||||||
| `defaultConfig` | Yes | Default configuration values merged into operator's `config.yaml` |
|
| `defaultConfig` | Yes | Default configuration values merged into operator's `config.yaml` |
|
||||||
| `defaultSecrets` | No | List of secrets in dotted-path format (e.g., `apps.appname.dbPassword`) |
|
| `defaultSecrets` | No | This app's secrets (no 'default' = auto-generated) |
|
||||||
|
| `requiredSecrets` | No | List of secrets from dependency apps (format: `<app-ref>.<key>`) |
|
||||||
|
|
||||||
**Important:** All configuration keys referenced in templates (via `{{ .apps.appname.key }}`) must be defined in `defaultConfig` or be standard Wild Cloud variables.
|
**Dependency Configuration:**
|
||||||
|
- Each dependency in `requires` can have:
|
||||||
|
- `name`: The actual app name to depend on
|
||||||
|
- `alias`: Optional reference name for templates (defaults to `name`)
|
||||||
|
|
||||||
|
**Manifest Template Variable Sources:**
|
||||||
|
1. Standard Wild Cloud variables: `{{ .cloud.* }}`, `{{ .cluster.* }}`, `{{ .operator.* }}`
|
||||||
|
2. App-specific variables: `{{ .app.* }}` - resolved from current app's config
|
||||||
|
3. Dependency variables: `{{ .apps.<ref>.* }}` - resolved using app reference mapping
|
||||||
|
4. App-specific secrets (in 'defaultSecrets' ONLY): `{{ secrets.* }}`
|
||||||
|
|
||||||
|
**Manifest App Reference Resolution:**
|
||||||
|
When you use `{{ .apps.<ref>.* }}` in templates:
|
||||||
|
1. System checks if `<ref>` matches any dependency's `alias` field
|
||||||
|
2. If no alias match, checks if `<ref>` matches any dependency's `name` field
|
||||||
|
3. Uses the `installedAs` value (automatically added when the app is added) to find actual app configuration in `config.yaml`
|
||||||
|
|
||||||
|
All manifest template variables must be defined in one of these locations.
|
||||||
|
|
||||||
|
**Important:** In the rest of the app templates, ALL configuration keys referenced in templates (via `{{ .key }}`) must be defined in `defaultConfig`. Only the app config is available to app templates.
|
||||||
|
|
||||||
### Kustomization (`kustomization.yaml`)
|
### Kustomization (`kustomization.yaml`)
|
||||||
|
|
||||||
@@ -111,21 +140,7 @@ This means individual resources can use simple, component-specific selectors lik
|
|||||||
|
|
||||||
### Gomplate Templating
|
### Gomplate Templating
|
||||||
|
|
||||||
Resource files in this repository are **templates** that get compiled when users add apps via the web app, CLI, or API. Use gomplate syntax to reference configuration:
|
Resource files in this repository are **templates** that get compiled when users add apps via the web app, CLI, or API. Only variables defined in the manifest file's 'defaultConfig' section are available to the resource templates. Use gomplate syntax to reference configuration:
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Common template variables
|
|
||||||
domain: {{ .cloud.domain }} # Operator's domain
|
|
||||||
email: {{ .operator.email }} # Operator's email
|
|
||||||
image: {{ .apps.myapp.serverImage }} # App-specific config
|
|
||||||
dbHost: {{ .apps.myapp.dbHostname }} # App-specific config
|
|
||||||
```
|
|
||||||
|
|
||||||
**Template variable sources:**
|
|
||||||
1. Standard Wild Cloud variables (`{{ .cloud.* }}`, `{{ .operator.* }}`)
|
|
||||||
2. App-specific variables defined in your manifest's `defaultConfig`
|
|
||||||
|
|
||||||
All template variables must be defined in one of these locations. The compiled files are placed in the instance's directory as standard Kubernetes manifests.
|
|
||||||
|
|
||||||
### External DNS
|
### External DNS
|
||||||
|
|
||||||
@@ -133,12 +148,47 @@ Ingress resources should include external-dns annotations for automatic DNS mana
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .domain }}
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: 'domain' must be defined in the app manifest's 'defaultConfig' section.
|
||||||
|
|
||||||
This creates a CNAME from the app subdomain to the cluster domain (e.g., `myapp.cloud.example.com` → `cloud.example.com`).
|
This creates a CNAME from the app subdomain to the cluster domain (e.g., `myapp.cloud.example.com` → `cloud.example.com`).
|
||||||
|
|
||||||
|
## App Dependencies and Reference Mapping
|
||||||
|
|
||||||
|
### How Dependency References Work
|
||||||
|
|
||||||
|
When an app depends on other apps, the reference system allows flexibility in naming while maintaining clear relationships:
|
||||||
|
|
||||||
|
1. **Define dependencies** in your manifest with optional aliases:
|
||||||
|
```yaml
|
||||||
|
requires:
|
||||||
|
- name: postgres # Actual app to depend on
|
||||||
|
alias: db # Optional: how to reference it in templates
|
||||||
|
- name: redis # No alias means use 'redis' as reference
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **At installation time**, the system:
|
||||||
|
- Prompts user to map dependencies to actual installed apps
|
||||||
|
- Sets `installedAs` field in the local app manifest to track the mapping
|
||||||
|
- Example: User might have `postgres-primary` installed, mapped to the `db` dependency
|
||||||
|
|
||||||
|
### Example: Multiple Database Instances
|
||||||
|
|
||||||
|
If a user has multiple PostgreSQL instances:
|
||||||
|
```yaml
|
||||||
|
# User's config.yaml
|
||||||
|
apps:
|
||||||
|
postgres-primary:
|
||||||
|
hostname: primary.postgres.svc.cluster.local
|
||||||
|
postgres-analytics:
|
||||||
|
hostname: analytics.postgres.svc.cluster.local
|
||||||
|
```
|
||||||
|
|
||||||
|
When adding an app that requires postgres, they can choose which instance to use, and the system tracks this in the manifest's `installedAs` field.
|
||||||
|
|
||||||
## Database Patterns
|
## Database Patterns
|
||||||
|
|
||||||
### Database Initialization Jobs
|
### Database Initialization Jobs
|
||||||
@@ -211,13 +261,16 @@ spec:
|
|||||||
|
|
||||||
### Secrets Management
|
### Secrets Management
|
||||||
|
|
||||||
Secrets use a **full dotted-path naming convention** to prevent naming conflicts:
|
Secrets are managed through two mechanisms: default secrets for the app itself and required secrets from dependencies.
|
||||||
|
|
||||||
**In manifest:**
|
**In manifest:**
|
||||||
```yaml
|
```yaml
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- apps.myapp.dbPassword
|
key: dbPassword # This app's database password
|
||||||
- apps.postgres.password
|
key: apiKey # This app's API key
|
||||||
|
requiredSecrets:
|
||||||
|
- db.password # Password from postgres dependency (aliased as 'db')
|
||||||
|
- redis.auth # Auth from redis dependency
|
||||||
```
|
```
|
||||||
|
|
||||||
**In resources:**
|
**In resources:**
|
||||||
@@ -227,14 +280,26 @@ env:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: myapp-secrets
|
name: myapp-secrets
|
||||||
key: apps.myapp.dbPassword # Full dotted path, not just "dbPassword"
|
key: dbPassword # Points to the default secret
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: myapp-secrets
|
||||||
|
key: db.password # Points to the required secret
|
||||||
```
|
```
|
||||||
|
|
||||||
**Secret workflow:**
|
**Secret workflow:**
|
||||||
1. List secrets in manifest's `defaultSecrets`
|
1. Define app's own secrets in `defaultSecrets` (key, default mappings)
|
||||||
2. When adding an app, the system generates random values in the instance's `secrets.yaml`
|
2. Reference dependency secrets in `requiredSecrets` (list)
|
||||||
3. When deploying, the system creates a Kubernetes Secret named `<app-name>-secrets`
|
3. When adding an app, the system:
|
||||||
4. Resources reference secrets using full dotted paths
|
- Generates random values for empty `defaultSecrets`
|
||||||
|
- Copies referenced secrets from dependencies
|
||||||
|
- Stores all in the instance's `secrets.yaml`
|
||||||
|
4. When deploying, creates a Kubernetes Secret named `<app-name>-secrets` containing:
|
||||||
|
- All `defaultSecrets` with key format: `<key>`
|
||||||
|
- All `requiredSecrets` with key format: `<app-ref>.<key>`
|
||||||
|
|
||||||
|
**Key collision handling:** If the same key exists in both `defaultSecrets` and `requiredSecrets`, the `requiredSecrets` value takes precedence. Authors should ensure their local secrets don't collide with their required secrets.
|
||||||
|
|
||||||
**Important:** Never commit `secrets.yaml` to Git. Templates should only reference secrets, never contain actual secret values.
|
**Important:** Never commit `secrets.yaml` to Git. Templates should only reference secrets, never contain actual secret values.
|
||||||
|
|
||||||
@@ -308,9 +373,11 @@ Before submitting a new or modified app, verify:
|
|||||||
- [ ] **Manifest**
|
- [ ] **Manifest**
|
||||||
- [ ] `name` matches directory name
|
- [ ] `name` matches directory name
|
||||||
- [ ] All required fields present (`name`, `description`, `version`, `defaultConfig`)
|
- [ ] All required fields present (`name`, `description`, `version`, `defaultConfig`)
|
||||||
- [ ] All template variables defined in `defaultConfig` or are standard Wild Cloud variables
|
- [ ] All template variables defined in `defaultConfig`
|
||||||
- [ ] Secrets use dotted-path format (e.g., `apps.appname.secretname`)
|
- [ ] `defaultSecrets` uses maps with 'key' and 'default' attributes
|
||||||
- [ ] Dependencies listed in `requires` (if any)
|
- [ ] `requiredSecrets` references use `<app-ref>.<key>` format
|
||||||
|
- [ ] Dependencies listed in `requires` with optional `alias` fields
|
||||||
|
- [ ] Manifest template references match dependency aliases or names
|
||||||
|
|
||||||
- [ ] **Kustomization**
|
- [ ] **Kustomization**
|
||||||
- [ ] Includes standard Wild Cloud labels with `includeSelectors: true`
|
- [ ] Includes standard Wild Cloud labels with `includeSelectors: true`
|
||||||
@@ -318,8 +385,6 @@ Before submitting a new or modified app, verify:
|
|||||||
- [ ] All resource files listed under `resources:`
|
- [ ] All resource files listed under `resources:`
|
||||||
|
|
||||||
- [ ] **Resources**
|
- [ ] **Resources**
|
||||||
- [ ] All hardcoded values replaced with gomplate variables
|
|
||||||
- [ ] Secrets reference full dotted paths
|
|
||||||
- [ ] Security contexts on all pods (both pod-level and container-level)
|
- [ ] Security contexts on all pods (both pod-level and container-level)
|
||||||
- [ ] Simple component labels, no Helm-style labels
|
- [ ] Simple component labels, no Helm-style labels
|
||||||
- [ ] Ingresses include external-dns annotations
|
- [ ] Ingresses include external-dns annotations
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
# Source: discourse/templates/configmaps.yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: discourse
|
|
||||||
namespace: discourse
|
|
||||||
data:
|
|
||||||
DISCOURSE_HOSTNAME: "{{ .apps.discourse.domain }}"
|
|
||||||
DISCOURSE_SKIP_INSTALL: "no"
|
|
||||||
DISCOURSE_SITE_NAME: "{{ .apps.discourse.siteName }}"
|
|
||||||
DISCOURSE_USERNAME: "{{ .apps.discourse.adminUsername }}"
|
|
||||||
DISCOURSE_EMAIL: "{{ .apps.discourse.adminEmail }}"
|
|
||||||
|
|
||||||
DISCOURSE_REDIS_HOST: "{{ .apps.discourse.redisHostname }}"
|
|
||||||
DISCOURSE_REDIS_PORT_NUMBER: "6379"
|
|
||||||
|
|
||||||
DISCOURSE_DATABASE_HOST: "{{ .apps.discourse.dbHostname }}"
|
|
||||||
DISCOURSE_DATABASE_PORT_NUMBER: "5432"
|
|
||||||
DISCOURSE_DATABASE_NAME: "{{ .apps.discourse.dbName }}"
|
|
||||||
DISCOURSE_DATABASE_USER: "{{ .apps.discourse.dbUsername }}"
|
|
||||||
|
|
||||||
DISCOURSE_SMTP_HOST: "{{ .apps.discourse.smtp.host }}"
|
|
||||||
DISCOURSE_SMTP_PORT: "{{ .apps.discourse.smtp.port }}"
|
|
||||||
DISCOURSE_SMTP_USER: "{{ .apps.discourse.smtp.user }}"
|
|
||||||
DISCOURSE_SMTP_PROTOCOL: "tls"
|
|
||||||
DISCOURSE_SMTP_AUTH: "login"
|
|
||||||
|
|
||||||
# DISCOURSE_PRECOMPILE_ASSETS: "false"
|
|
||||||
# DISCOURSE_SKIP_INSTALL: "no"
|
|
||||||
# DISCOURSE_SKIP_BOOTSTRAP: "yes"
|
|
||||||
@@ -27,7 +27,7 @@ spec:
|
|||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
env:
|
env:
|
||||||
- name: PGHOST
|
- name: PGHOST
|
||||||
value: "{{ .apps.discourse.dbHostname }}"
|
value: "{{ .dbHostname }}"
|
||||||
- name: PGPORT
|
- name: PGPORT
|
||||||
value: "5432"
|
value: "5432"
|
||||||
- name: PGUSER
|
- name: PGUSER
|
||||||
@@ -36,16 +36,16 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.postgres.password
|
key: postgres.password
|
||||||
- name: DISCOURSE_DB_USER
|
- name: DISCOURSE_DB_USER
|
||||||
value: "{{ .apps.discourse.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DISCOURSE_DB_NAME
|
- name: DISCOURSE_DB_NAME
|
||||||
value: "{{ .apps.discourse.dbName }}"
|
value: "{{ .dbName }}"
|
||||||
- name: DISCOURSE_DB_PASSWORD
|
- name: DISCOURSE_DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.discourse.dbPassword
|
key: dbPassword
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
# Source: discourse/templates/deployment.yaml
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -18,219 +17,133 @@ spec:
|
|||||||
component: web
|
component: web
|
||||||
spec:
|
spec:
|
||||||
automountServiceAccountToken: false
|
automountServiceAccountToken: false
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
preferredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- podAffinityTerm:
|
|
||||||
labelSelector:
|
|
||||||
matchLabels:
|
|
||||||
component: web
|
|
||||||
topologyKey: kubernetes.io/hostname
|
|
||||||
weight: 1
|
|
||||||
|
|
||||||
serviceAccountName: discourse
|
serviceAccountName: discourse
|
||||||
securityContext:
|
securityContext:
|
||||||
fsGroup: 0
|
fsGroup: 0
|
||||||
fsGroupChangePolicy: Always
|
fsGroupChangePolicy: Always
|
||||||
supplementalGroups: []
|
|
||||||
sysctls: []
|
|
||||||
initContainers:
|
|
||||||
containers:
|
containers:
|
||||||
- name: discourse
|
- name: discourse
|
||||||
image: docker.io/bitnami/discourse:3.4.7-debian-12-r0
|
image: tiredofit/discourse:latest
|
||||||
imagePullPolicy: "IfNotPresent"
|
imagePullPolicy: "IfNotPresent"
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
capabilities:
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
add:
|
add:
|
||||||
- CHOWN
|
- CHOWN
|
||||||
- SYS_CHROOT
|
- DAC_OVERRIDE
|
||||||
- FOWNER
|
- FOWNER
|
||||||
- SETGID
|
- SETGID
|
||||||
- SETUID
|
- SETUID
|
||||||
- DAC_OVERRIDE
|
|
||||||
drop:
|
|
||||||
- ALL
|
|
||||||
privileged: false
|
privileged: false
|
||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
runAsGroup: 0
|
|
||||||
runAsNonRoot: false
|
runAsNonRoot: false
|
||||||
runAsUser: 0
|
runAsUser: 0
|
||||||
seLinuxOptions: {}
|
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
env:
|
env:
|
||||||
- name: BITNAMI_DEBUG
|
# Admin configuration
|
||||||
value: "false"
|
- name: ADMIN_USER
|
||||||
- name: DISCOURSE_PASSWORD
|
value: {{ .adminUsername }}
|
||||||
|
- name: ADMIN_EMAIL
|
||||||
|
value: {{ .adminEmail }}
|
||||||
|
- name: ADMIN_PASS
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.discourse.adminPassword
|
key: adminPassword
|
||||||
- name: DISCOURSE_PORT_NUMBER
|
# Site configuration
|
||||||
value: "8080"
|
- name: SITE_TITLE
|
||||||
- name: DISCOURSE_EXTERNAL_HTTP_PORT_NUMBER
|
value: {{ .siteName }}
|
||||||
value: "80"
|
- name: HOSTNAME
|
||||||
- name: DISCOURSE_DATABASE_PASSWORD
|
value: {{ .domain }}
|
||||||
|
# Database configuration
|
||||||
|
- name: DB_HOST
|
||||||
|
value: {{ .dbHostname }}
|
||||||
|
- name: DB_PORT
|
||||||
|
value: "{{ .dbPort }}"
|
||||||
|
- name: DB_NAME
|
||||||
|
value: {{ .dbName }}
|
||||||
|
- name: DB_USER
|
||||||
|
value: {{ .dbUsername }}
|
||||||
|
- name: DB_PASS
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.discourse.dbPassword
|
key: dbPassword
|
||||||
- name: POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD
|
# Redis configuration
|
||||||
|
- name: REDIS_HOST
|
||||||
|
value: {{ .redisHostname }}
|
||||||
|
- name: REDIS_PASS
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.discourse.dbPassword
|
key: redis.password
|
||||||
- name: DISCOURSE_REDIS_PASSWORD
|
# SMTP configuration
|
||||||
|
- name: SMTP_ENABLED
|
||||||
|
value: "{{ .smtp.enabled }}"
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: {{ .smtp.host }}
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: "{{ .smtp.port }}"
|
||||||
|
- name: SMTP_USER
|
||||||
|
value: {{ .smtp.user }}
|
||||||
|
- name: SMTP_PASS
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: discourse-secrets
|
name: discourse-secrets
|
||||||
key: apps.redis.password
|
key: smtpPassword
|
||||||
- name: DISCOURSE_SECRET_KEY_BASE
|
- name: SMTP_TLS
|
||||||
valueFrom:
|
value: "{{ .smtp.tls }}"
|
||||||
secretKeyRef:
|
# Container timezone
|
||||||
name: discourse-secrets
|
- name: TZ
|
||||||
key: apps.discourse.secretKeyBase
|
value: {{ .timezone }}
|
||||||
- name: DISCOURSE_SMTP_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.smtpPassword
|
|
||||||
- name: SMTP_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.smtpPassword
|
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: discourse
|
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8080
|
containerPort: 3000
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
httpGet:
|
||||||
|
path: /
|
||||||
port: http
|
port: http
|
||||||
initialDelaySeconds: 500
|
initialDelaySeconds: 420
|
||||||
periodSeconds: 10
|
periodSeconds: 30
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 10
|
||||||
successThreshold: 1
|
successThreshold: 1
|
||||||
failureThreshold: 6
|
failureThreshold: 6
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /srv/status
|
path: /
|
||||||
port: http
|
port: http
|
||||||
initialDelaySeconds: 180
|
initialDelaySeconds: 360
|
||||||
periodSeconds: 10
|
periodSeconds: 30
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 10
|
||||||
successThreshold: 1
|
successThreshold: 1
|
||||||
failureThreshold: 6
|
failureThreshold: 6
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 1
|
cpu: 2000m
|
||||||
ephemeral-storage: 2Gi
|
ephemeral-storage: 10Gi
|
||||||
memory: 8Gi # for precompiling assets!
|
memory: 4Gi
|
||||||
requests:
|
requests:
|
||||||
cpu: 750m
|
cpu: 500m
|
||||||
ephemeral-storage: 50Mi
|
ephemeral-storage: 50Mi
|
||||||
memory: 1Gi
|
memory: 1Gi
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: discourse-data
|
- name: discourse-logs
|
||||||
mountPath: /bitnami/discourse
|
mountPath: /data/logs
|
||||||
subPath: discourse
|
- name: discourse-uploads
|
||||||
- name: sidekiq
|
mountPath: /data/uploads
|
||||||
image: docker.io/bitnami/discourse:3.4.7-debian-12-r0
|
- name: discourse-backups
|
||||||
imagePullPolicy: "IfNotPresent"
|
mountPath: /data/backups
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
capabilities:
|
|
||||||
add:
|
|
||||||
- CHOWN
|
|
||||||
- SYS_CHROOT
|
|
||||||
- FOWNER
|
|
||||||
- SETGID
|
|
||||||
- SETUID
|
|
||||||
- DAC_OVERRIDE
|
|
||||||
drop:
|
|
||||||
- ALL
|
|
||||||
privileged: false
|
|
||||||
readOnlyRootFilesystem: false
|
|
||||||
runAsGroup: 0
|
|
||||||
runAsNonRoot: false
|
|
||||||
runAsUser: 0
|
|
||||||
seLinuxOptions: {}
|
|
||||||
seccompProfile:
|
|
||||||
type: RuntimeDefault
|
|
||||||
command:
|
|
||||||
- /opt/bitnami/scripts/discourse/entrypoint.sh
|
|
||||||
args:
|
|
||||||
- /opt/bitnami/scripts/discourse-sidekiq/run.sh
|
|
||||||
env:
|
|
||||||
- name: BITNAMI_DEBUG
|
|
||||||
value: "false"
|
|
||||||
- name: DISCOURSE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.adminPassword
|
|
||||||
- name: DISCOURSE_POSTGRESQL_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.dbPassword
|
|
||||||
- name: DISCOURSE_REDIS_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.redis.password
|
|
||||||
- name: DISCOURSE_SECRET_KEY_BASE
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.secretKeyBase
|
|
||||||
- name: DISCOURSE_SMTP_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.smtpPassword
|
|
||||||
- name: SMTP_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: discourse-secrets
|
|
||||||
key: apps.discourse.smtpPassword
|
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: discourse
|
|
||||||
livenessProbe:
|
|
||||||
exec:
|
|
||||||
command: ["/bin/sh", "-c", "pgrep -f ^sidekiq"]
|
|
||||||
initialDelaySeconds: 500
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 5
|
|
||||||
successThreshold: 1
|
|
||||||
failureThreshold: 6
|
|
||||||
readinessProbe:
|
|
||||||
exec:
|
|
||||||
command: ["/bin/sh", "-c", "pgrep -f ^sidekiq"]
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 5
|
|
||||||
successThreshold: 1
|
|
||||||
failureThreshold: 6
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 500m
|
|
||||||
ephemeral-storage: 2Gi
|
|
||||||
memory: 768Mi
|
|
||||||
requests:
|
|
||||||
cpu: 375m
|
|
||||||
ephemeral-storage: 50Mi
|
|
||||||
memory: 512Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: discourse-data
|
|
||||||
mountPath: /bitnami/discourse
|
|
||||||
subPath: discourse
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: discourse-data
|
- name: discourse-logs
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: discourse
|
claimName: discourse-logs
|
||||||
|
- name: discourse-uploads
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: discourse-uploads
|
||||||
|
- name: discourse-backups
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: discourse-backups
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ apiVersion: networking.k8s.io/v1
|
|||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: discourse
|
name: discourse
|
||||||
namespace: "discourse"
|
namespace: "{{ .namespace }}"
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
external-dns.alpha.kubernetes.io/target: "{{ .cloud.domain }}"
|
external-dns.alpha.kubernetes.io/target: "{{ .externalDnsDomain }}"
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: "{{ .apps.discourse.domain }}"
|
- host: "{{ .domain }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -22,5 +22,5 @@ spec:
|
|||||||
name: http
|
name: http
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- "{{ .apps.discourse.domain }}"
|
- "{{ .domain }}"
|
||||||
secretName: wildcard-external-wild-cloud-tls
|
secretName: wildcard-external-wild-cloud-tls
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ labels:
|
|||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- serviceaccount.yaml
|
- serviceaccount.yaml
|
||||||
- configmap.yaml
|
|
||||||
- pvc.yaml
|
- pvc.yaml
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
name: discourse
|
name: discourse
|
||||||
description: Discourse is a modern, open-source discussion platform designed for online communities and forums.
|
description: Discourse is a modern, open-source discussion platform designed for online communities and forums.
|
||||||
version: 3.4.7
|
version: 3.5.3
|
||||||
icon: https://www.discourse.org/img/icon.png
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/discourse.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
- name: redis
|
- name: redis
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: discourse
|
||||||
|
externalDnsDomain: "{{ .cloud.domain }}"
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
port: 8080
|
port: 3000
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
adminEmail: admin@{{ .cloud.domain }}
|
adminEmail: "{{ .operator.email }}"
|
||||||
adminUsername: admin
|
adminUsername: admin
|
||||||
siteName: "Community"
|
siteName: "Community"
|
||||||
domain: discourse.{{ .cloud.domain }}
|
domain: discourse.{{ .cloud.domain }}
|
||||||
dbHostname: postgres.postgres.svc.cluster.local
|
dbHostname: "{{ .apps.postgres.host }}"
|
||||||
|
dbPort: "{{ .apps.postgres.port }}"
|
||||||
dbUsername: discourse
|
dbUsername: discourse
|
||||||
dbName: discourse
|
dbName: discourse
|
||||||
redisHostname: redis.redis.svc.cluster.local
|
redisHostname: "{{ .apps.redis.host }}"
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
smtp:
|
smtp:
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -24,13 +27,16 @@ defaultConfig:
|
|||||||
port: "{{ .cloud.smtp.port }}"
|
port: "{{ .cloud.smtp.port }}"
|
||||||
user: "{{ .cloud.smtp.user }}"
|
user: "{{ .cloud.smtp.user }}"
|
||||||
from: "{{ .cloud.smtp.from }}"
|
from: "{{ .cloud.smtp.from }}"
|
||||||
tls: {{ .cloud.smtp.tls }}
|
tls: "{{ .cloud.smtp.tls }}"
|
||||||
startTls: {{ .cloud.smtp.startTls }}
|
startTls: "{{ .cloud.smtp.startTls }}"
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- - key: apps.discourse.adminPassword
|
- key: adminPassword
|
||||||
- - key: apps.discourse.dbPassword
|
- key: secretKeyBase
|
||||||
- - key: apps.discourse.dbUrl
|
default: "{{ random.AlphaNum 64 }}"
|
||||||
- - key: apps.redis.password
|
- key: smtpPassword
|
||||||
- - key: apps.discourse.secretKeyBase
|
- key: dbPassword
|
||||||
- - key: apps.discourse.smtpPassword
|
- key: dbUrl
|
||||||
- - key: apps.postgres.password
|
default: "postgres://{{ .app.dbUsername }}:{{ .secrets.dbPassword }}@{{ .app.dbHostname }}:{{ .app.dbPort }}/{{ .app.dbName }}?sslmode=disable"
|
||||||
|
requiredSecrets:
|
||||||
|
- postgres.password
|
||||||
|
- redis.password
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: discourse
|
name: "{{ .namespace }}"
|
||||||
|
|||||||
@@ -1,13 +1,39 @@
|
|||||||
---
|
---
|
||||||
# Source: discourse/templates/pvc.yaml
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: discourse
|
name: discourse-logs
|
||||||
namespace: discourse
|
namespace: discourse
|
||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- "ReadWriteOnce"
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: "{{ .apps.discourse.storage }}"
|
storage: 2Gi
|
||||||
|
storageClassName: longhorn
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: discourse-uploads
|
||||||
|
namespace: discourse
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .storage }}
|
||||||
|
storageClassName: longhorn
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: discourse-backups
|
||||||
|
namespace: discourse
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: longhorn
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: example-admin
|
name: example-admin
|
||||||
namespace: example-admin
|
|
||||||
labels:
|
labels:
|
||||||
app: example-admin
|
app: example-admin
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ apiVersion: networking.k8s.io/v1
|
|||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: example-admin
|
name: example-admin
|
||||||
namespace: example-admin
|
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: example-admin.{{ .cloud.internalDomain }}
|
- host: "{{ .host }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -18,5 +17,5 @@ spec:
|
|||||||
number: 80
|
number: 80
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- example-admin.{{ .cloud.internalDomain }}
|
- "{{ .host }}"
|
||||||
secretName: wildcard-internal-wild-cloud-tls
|
secretName: wildcard-internal-wild-cloud-tls
|
||||||
|
|||||||
@@ -3,4 +3,7 @@ install: true
|
|||||||
description: An example application that is deployed with internal-only access.
|
description: An example application that is deployed with internal-only access.
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: example-admin
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
|
host: '{{ .host }}'
|
||||||
tlsSecretName: wildcard-internal-wild-cloud-tls
|
tlsSecretName: wildcard-internal-wild-cloud-tls
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: example-admin
|
name: "{{ .namespace }}"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ kind: Ingress
|
|||||||
metadata:
|
metadata:
|
||||||
name: example-app
|
name: example-app
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: "{{ .cloud.externalDnsTarget }}"
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: false
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: false
|
||||||
|
|
||||||
# Optional: Enable HTTPS redirection
|
# Optional: Enable HTTPS redirection
|
||||||
@@ -15,7 +15,7 @@ metadata:
|
|||||||
# traefik.ingress.kubernetes.io/auth-secret: basic-auth
|
# traefik.ingress.kubernetes.io/auth-secret: basic-auth
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: example-app.{{ .cloud.domain }}
|
- host: "{{ .host }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -27,5 +27,5 @@ spec:
|
|||||||
number: 80
|
number: 80
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- example-app.{{ .cloud.domain }}
|
- "{{ .host }}"
|
||||||
secretName: wildcard-wild-cloud-tls
|
secretName: wildcard-wild-cloud-tls
|
||||||
|
|||||||
@@ -3,4 +3,7 @@ install: true
|
|||||||
description: An example application that is deployed with public access.
|
description: An example application that is deployed with public access.
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: example-app
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
|
host: example-app.{{ .cloud.domain }}
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: example-app
|
name: "{{ .namespace }}"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: db-init
|
- name: db-init
|
||||||
image: {{ .apps.mysql.image }}
|
image: mysql:9.1.0
|
||||||
command: ["/bin/bash", "-c"]
|
command: ["/bin/bash", "-c"]
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -27,18 +27,18 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: mysql-secrets
|
name: mysql-secrets
|
||||||
key: apps.mysql.rootPassword
|
key: rootPassword
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.ghost.dbHost }}"
|
value: "{{ .dbHost }}"
|
||||||
- name: DB_PORT
|
- name: DB_PORT
|
||||||
value: "{{ .apps.ghost.dbPort }}"
|
value: "{{ .dbPort }}"
|
||||||
- name: DB_DATABASE_NAME
|
- name: DB_DATABASE_NAME
|
||||||
value: "{{ .apps.ghost.dbName }}"
|
value: "{{ .dbName }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.ghost.dbUser }}"
|
value: "{{ .dbUser }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: ghost-secrets
|
name: ghost-secrets
|
||||||
key: apps.ghost.dbPassword
|
key: dbPassword
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
@@ -17,10 +17,10 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: ghost
|
- name: ghost
|
||||||
image: {{ .apps.ghost.image }}
|
image: {{ .image }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: {{ .apps.ghost.port }}
|
containerPort: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
env:
|
env:
|
||||||
- name: BITNAMI_DEBUG
|
- name: BITNAMI_DEBUG
|
||||||
@@ -28,33 +28,33 @@ spec:
|
|||||||
- name: ALLOW_EMPTY_PASSWORD
|
- name: ALLOW_EMPTY_PASSWORD
|
||||||
value: "yes"
|
value: "yes"
|
||||||
- name: GHOST_DATABASE_HOST
|
- name: GHOST_DATABASE_HOST
|
||||||
value: {{ .apps.ghost.dbHost }}
|
value: {{ .dbHost }}
|
||||||
- name: GHOST_DATABASE_PORT_NUMBER
|
- name: GHOST_DATABASE_PORT_NUMBER
|
||||||
value: "{{ .apps.ghost.dbPort }}"
|
value: "{{ .dbPort }}"
|
||||||
- name: GHOST_DATABASE_NAME
|
- name: GHOST_DATABASE_NAME
|
||||||
value: {{ .apps.ghost.dbName }}
|
value: {{ .dbName }}
|
||||||
- name: GHOST_DATABASE_USER
|
- name: GHOST_DATABASE_USER
|
||||||
value: {{ .apps.ghost.dbUser }}
|
value: {{ .dbUser }}
|
||||||
- name: GHOST_DATABASE_PASSWORD
|
- name: GHOST_DATABASE_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: ghost-secrets
|
name: ghost-secrets
|
||||||
key: apps.ghost.dbPassword
|
key: dbPassword
|
||||||
- name: GHOST_HOST
|
- name: GHOST_HOST
|
||||||
value: {{ .apps.ghost.domain }}
|
value: {{ .domain }}
|
||||||
- name: GHOST_PORT_NUMBER
|
- name: GHOST_PORT_NUMBER
|
||||||
value: "{{ .apps.ghost.port }}"
|
value: "{{ .port }}"
|
||||||
- name: GHOST_USERNAME
|
- name: GHOST_USERNAME
|
||||||
value: {{ .apps.ghost.adminUser }}
|
value: {{ .adminUser }}
|
||||||
- name: GHOST_PASSWORD
|
- name: GHOST_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: ghost-secrets
|
name: ghost-secrets
|
||||||
key: apps.ghost.adminPassword
|
key: adminPassword
|
||||||
- name: GHOST_EMAIL
|
- name: GHOST_EMAIL
|
||||||
value: {{ .apps.ghost.adminEmail }}
|
value: {{ .adminEmail }}
|
||||||
- name: GHOST_BLOG_TITLE
|
- name: GHOST_BLOG_TITLE
|
||||||
value: {{ .apps.ghost.blogTitle }}
|
value: {{ .blogTitle }}
|
||||||
- name: GHOST_ENABLE_HTTPS
|
- name: GHOST_ENABLE_HTTPS
|
||||||
value: "yes"
|
value: "yes"
|
||||||
- name: GHOST_EXTERNAL_HTTP_PORT_NUMBER
|
- name: GHOST_EXTERNAL_HTTP_PORT_NUMBER
|
||||||
@@ -66,18 +66,18 @@ spec:
|
|||||||
- name: GHOST_SMTP_SERVICE
|
- name: GHOST_SMTP_SERVICE
|
||||||
value: SMTP
|
value: SMTP
|
||||||
- name: GHOST_SMTP_HOST
|
- name: GHOST_SMTP_HOST
|
||||||
value: {{ .apps.ghost.smtp.host }}
|
value: {{ .smtp.host }}
|
||||||
- name: GHOST_SMTP_PORT
|
- name: GHOST_SMTP_PORT
|
||||||
value: "{{ .apps.ghost.smtp.port }}"
|
value: "{{ .smtp.port }}"
|
||||||
- name: GHOST_SMTP_USER
|
- name: GHOST_SMTP_USER
|
||||||
value: {{ .apps.ghost.smtp.user }}
|
value: {{ .smtp.user }}
|
||||||
- name: GHOST_SMTP_PASSWORD
|
- name: GHOST_SMTP_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: ghost-secrets
|
name: ghost-secrets
|
||||||
key: apps.ghost.smtpPassword
|
key: smtpPassword
|
||||||
- name: GHOST_SMTP_FROM_ADDRESS
|
- name: GHOST_SMTP_FROM_ADDRESS
|
||||||
value: {{ .apps.ghost.smtp.from }}
|
value: {{ .smtp.from }}
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 375m
|
cpu: 375m
|
||||||
@@ -92,7 +92,7 @@ spec:
|
|||||||
mountPath: /bitnami/ghost
|
mountPath: /bitnami/ghost
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .apps.ghost.port }}
|
port: {{ .port }}
|
||||||
initialDelaySeconds: 120
|
initialDelaySeconds: 120
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ metadata:
|
|||||||
kubernetes.io/ingress.class: "traefik"
|
kubernetes.io/ingress.class: "traefik"
|
||||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
external-dns.alpha.kubernetes.io/ttl: "60"
|
external-dns.alpha.kubernetes.io/ttl: "60"
|
||||||
traefik.ingress.kubernetes.io/redirect-entry-point: https
|
traefik.ingress.kubernetes.io/redirect-entry-point: https
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: {{ .apps.ghost.domain }}
|
- host: {{ .domain }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -24,5 +24,5 @@ spec:
|
|||||||
number: 80
|
number: 80
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- {{ .apps.ghost.domain }}
|
- {{ .domain }}
|
||||||
secretName: {{ .apps.ghost.tlsSecretName }}
|
secretName: {{ .tlsSecretName }}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
name: ghost
|
name: ghost
|
||||||
description: Ghost is a powerful app for new-media creators to publish, share, and grow a business around their content.
|
description: Ghost is a powerful app for new-media creators to publish, share, and
|
||||||
|
grow a business around their content.
|
||||||
version: 5.118.1
|
version: 5.118.1
|
||||||
icon: https://ghost.org/images/logos/ghost-logo-orb.png
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/ghost.png
|
||||||
requires:
|
requires:
|
||||||
- name: mysql
|
- name: mysql
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: ghost
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
image: docker.io/bitnami/ghost:5.118.1-debian-12-r0
|
image: docker.io/bitnami/ghost:5.118.1-debian-12-r0
|
||||||
domain: ghost.{{ .cloud.domain }}
|
domain: ghost.{{ .cloud.domain }}
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
@@ -15,16 +18,17 @@ defaultConfig:
|
|||||||
dbName: ghost
|
dbName: ghost
|
||||||
dbUser: ghost
|
dbUser: ghost
|
||||||
adminUser: admin
|
adminUser: admin
|
||||||
adminEmail: "admin@{{ .cloud.domain }}"
|
adminEmail: {{ .operator.email }}
|
||||||
blogTitle: "My Blog"
|
blogTitle: My Blog
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
|
||||||
smtp:
|
smtp:
|
||||||
host: "{{ .cloud.smtp.host }}"
|
host: '{{ .cloud.smtp.host }}'
|
||||||
port: "{{ .cloud.smtp.port }}"
|
port: '{{ .cloud.smtp.port }}'
|
||||||
from: "{{ .cloud.smtp.from }}"
|
from: '{{ .cloud.smtp.from }}'
|
||||||
user: "{{ .cloud.smtp.user }}"
|
user: '{{ .cloud.smtp.user }}'
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.ghost.adminPassword
|
- key: adminPassword
|
||||||
- key: apps.ghost.dbPassword
|
- key: dbPassword
|
||||||
- key: apps.ghost.smtpPassword
|
- key: smtpPassword
|
||||||
|
requiredSecrets:
|
||||||
|
- mysql.rootPassword
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: ghost
|
name: "{{ .namespace }}"
|
||||||
@@ -8,4 +8,4 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.ghost.storage }}
|
storage: {{ .storage }}
|
||||||
@@ -9,6 +9,6 @@ spec:
|
|||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: {{ .apps.ghost.port }}
|
targetPort: {{ .port }}
|
||||||
selector:
|
selector:
|
||||||
component: web
|
component: web
|
||||||
@@ -12,7 +12,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: db-init
|
- name: db-init
|
||||||
image: {{ .apps.postgres.image }}
|
image: postgres:17
|
||||||
command: ["/bin/bash", "-c"]
|
command: ["/bin/bash", "-c"]
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -36,16 +36,16 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: postgres-secrets
|
name: postgres-secrets
|
||||||
key: apps.postgres.password
|
key: password
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.gitea.dbHost }}"
|
value: "{{ .dbHost }}"
|
||||||
- name: DB_DATABASE_NAME
|
- name: DB_DATABASE_NAME
|
||||||
value: "{{ .apps.gitea.dbName }}"
|
value: "{{ .dbName }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.gitea.dbUser }}"
|
value: "{{ .dbUser }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.dbPassword
|
key: dbPassword
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
@@ -23,7 +23,7 @@ spec:
|
|||||||
terminationGracePeriodSeconds: 60
|
terminationGracePeriodSeconds: 60
|
||||||
containers:
|
containers:
|
||||||
- name: gitea
|
- name: gitea
|
||||||
image: "{{ .apps.gitea.image }}"
|
image: "{{ .image }}"
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
@@ -33,27 +33,27 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.adminPassword
|
key: adminPassword
|
||||||
- name: GITEA__security__SECRET_KEY
|
- name: GITEA__security__SECRET_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.secretKey
|
key: secretKey
|
||||||
- name: GITEA__security__INTERNAL_TOKEN
|
- name: GITEA__security__INTERNAL_TOKEN
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.jwtSecret
|
key: jwtSecret
|
||||||
- name: GITEA__database__PASSWD
|
- name: GITEA__database__PASSWD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.dbPassword
|
key: dbPassword
|
||||||
- name: GITEA__mailer__PASSWD
|
- name: GITEA__mailer__PASSWD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: gitea-secrets
|
name: gitea-secrets
|
||||||
key: apps.gitea.smtpPassword
|
key: smtpPassword
|
||||||
ports:
|
ports:
|
||||||
- name: ssh
|
- name: ssh
|
||||||
containerPort: 2222
|
containerPort: 2222
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ SSH_PORT=22
|
|||||||
GITEA_WORK_DIR=/data
|
GITEA_WORK_DIR=/data
|
||||||
GITEA_TEMP=/tmp/gitea
|
GITEA_TEMP=/tmp/gitea
|
||||||
TMPDIR=/tmp/gitea
|
TMPDIR=/tmp/gitea
|
||||||
GITEA_ADMIN_USERNAME={{ .apps.gitea.adminUser }}
|
GITEA_ADMIN_USERNAME={{ .adminUser }}
|
||||||
GITEA_ADMIN_PASSWORD_MODE=keepUpdated
|
GITEA_ADMIN_PASSWORD_MODE=keepUpdated
|
||||||
|
|
||||||
# Core app settings
|
# Core app settings
|
||||||
GITEA____APP_NAME={{ .apps.gitea.appName }}
|
GITEA____APP_NAME={{ .appName }}
|
||||||
GITEA____RUN_MODE={{ .apps.gitea.runMode }}
|
GITEA____RUN_MODE={{ .runMode }}
|
||||||
GITEA____RUN_USER=git
|
GITEA____RUN_USER=git
|
||||||
|
|
||||||
# Security settings
|
# Security settings
|
||||||
@@ -17,19 +17,19 @@ GITEA__security__PASSWORD_HASH_ALGO=pbkdf2
|
|||||||
|
|
||||||
# Database settings (except password which comes from secret)
|
# Database settings (except password which comes from secret)
|
||||||
GITEA__database__DB_TYPE=postgres
|
GITEA__database__DB_TYPE=postgres
|
||||||
GITEA__database__HOST={{ .apps.gitea.dbHost }}:{{ .apps.gitea.dbPort }}
|
GITEA__database__HOST={{ .dbHost }}:{{ .dbPort }}
|
||||||
GITEA__database__NAME={{ .apps.gitea.dbName }}
|
GITEA__database__NAME={{ .dbName }}
|
||||||
GITEA__database__USER={{ .apps.gitea.dbUser }}
|
GITEA__database__USER={{ .dbUser }}
|
||||||
GITEA__database__SSL_MODE=disable
|
GITEA__database__SSL_MODE=disable
|
||||||
GITEA__database__LOG_SQL=false
|
GITEA__database__LOG_SQL=false
|
||||||
|
|
||||||
# Server settings
|
# Server settings
|
||||||
GITEA__server__DOMAIN={{ .apps.gitea.domain }}
|
GITEA__server__DOMAIN={{ .domain }}
|
||||||
GITEA__server__HTTP_PORT={{ .apps.gitea.port }}
|
GITEA__server__HTTP_PORT={{ .port }}
|
||||||
GITEA__server__ROOT_URL=https://{{ .apps.gitea.domain }}/
|
GITEA__server__ROOT_URL=https://{{ .domain }}/
|
||||||
GITEA__server__DISABLE_SSH=false
|
GITEA__server__DISABLE_SSH=false
|
||||||
GITEA__server__SSH_DOMAIN={{ .apps.gitea.domain }}
|
GITEA__server__SSH_DOMAIN={{ .domain }}
|
||||||
GITEA__server__SSH_PORT={{ .apps.gitea.sshPort }}
|
GITEA__server__SSH_PORT={{ .sshPort }}
|
||||||
GITEA__server__SSH_LISTEN_PORT=2222
|
GITEA__server__SSH_LISTEN_PORT=2222
|
||||||
GITEA__server__LFS_START_SERVER=true
|
GITEA__server__LFS_START_SERVER=true
|
||||||
GITEA__server__OFFLINE_MODE=true
|
GITEA__server__OFFLINE_MODE=true
|
||||||
@@ -53,8 +53,8 @@ GITEA__webhook__ALLOWED_HOST_LIST=*
|
|||||||
|
|
||||||
# Mailer settings (enabled via env vars, password from secret)
|
# Mailer settings (enabled via env vars, password from secret)
|
||||||
GITEA__mailer__ENABLED=true
|
GITEA__mailer__ENABLED=true
|
||||||
GITEA__mailer__SMTP_ADDR={{ .apps.gitea.smtp.host }}
|
GITEA__mailer__SMTP_ADDR={{ .smtp.host }}
|
||||||
GITEA__mailer__SMTP_PORT={{ .apps.gitea.smtp.port }}
|
GITEA__mailer__SMTP_PORT={{ .smtp.port }}
|
||||||
GITEA__mailer__FROM={{ .apps.gitea.smtp.from }}
|
GITEA__mailer__FROM={{ .smtp.from }}
|
||||||
GITEA__mailer__USER={{ .apps.gitea.smtp.user }}
|
GITEA__mailer__USER={{ .smtp.user }}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ metadata:
|
|||||||
namespace: gitea
|
namespace: gitea
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
external-dns.alpha.kubernetes.io/target: "{{ .cloud.domain }}"
|
external-dns.alpha.kubernetes.io/target: "{{ .externalDnsDomain }}"
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: "{{ .apps.gitea.domain }}"
|
- host: "{{ .domain }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -19,6 +19,6 @@ spec:
|
|||||||
port:
|
port:
|
||||||
number: 3000
|
number: 3000
|
||||||
tls:
|
tls:
|
||||||
- secretName: "{{ .apps.gitea.tlsSecretName }}"
|
- secretName: "{{ .tlsSecretName }}"
|
||||||
hosts:
|
hosts:
|
||||||
- "{{ .apps.gitea.domain }}"
|
- "{{ .domain }}"
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
name: gitea
|
name: gitea
|
||||||
description: Gitea is a painless self-hosted Git service written in Go
|
description: Gitea is a painless self-hosted Git service written in Go
|
||||||
version: 1.24.3
|
version: 1.24.3
|
||||||
icon: https://github.com/go-gitea/gitea/raw/main/assets/logo.png
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/gitea.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: gitea
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
image: gitea/gitea:1.24.3
|
image: gitea/gitea:1.24.3
|
||||||
appName: Gitea
|
appName: Gitea
|
||||||
domain: gitea.{{ .cloud.domain }}
|
domain: gitea.{{ .cloud.domain }}
|
||||||
@@ -16,18 +18,20 @@ defaultConfig:
|
|||||||
dbUser: gitea
|
dbUser: gitea
|
||||||
dbHost: postgres.postgres.svc.cluster.local
|
dbHost: postgres.postgres.svc.cluster.local
|
||||||
adminUser: admin
|
adminUser: admin
|
||||||
adminEmail: "admin@{{ .cloud.domain }}"
|
adminEmail: "{{ .operator.email }}"
|
||||||
dbPort: 5432
|
dbPort: 5432
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
runMode: prod
|
runMode: prod
|
||||||
smtp:
|
smtp:
|
||||||
host: "{{ .cloud.smtp.host }}"
|
host: '{{ .cloud.smtp.host }}'
|
||||||
port: "{{ .cloud.smtp.port }}"
|
port: '{{ .cloud.smtp.port }}'
|
||||||
user: "{{ .cloud.smtp.user }}"
|
user: '{{ .cloud.smtp.user }}'
|
||||||
from: "{{ .cloud.smtp.from }}"
|
from: '{{ .cloud.smtp.from }}'
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.gitea.adminPassword
|
- key: adminPassword
|
||||||
- key: apps.gitea.dbPassword
|
- key: dbPassword
|
||||||
- key: apps.gitea.secretKey
|
- key: secretKey
|
||||||
- key: apps.gitea.jwtSecret
|
- key: jwtSecret
|
||||||
- key: apps.gitea.smtpPassword
|
- key: smtpPassword
|
||||||
|
requiredSecrets:
|
||||||
|
- postgres.password
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: gitea
|
name: "{{ .namespace }}"
|
||||||
@@ -9,4 +9,4 @@ spec:
|
|||||||
storageClassName: longhorn
|
storageClassName: longhorn
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: "{{ .apps.gitea.storage }}"
|
storage: "{{ .storage }}"
|
||||||
@@ -8,7 +8,7 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 3000
|
port: 3000
|
||||||
targetPort: {{ .apps.gitea.port }}
|
targetPort: {{ .port }}
|
||||||
selector:
|
selector:
|
||||||
component: web
|
component: web
|
||||||
---
|
---
|
||||||
@@ -21,7 +21,7 @@ spec:
|
|||||||
type: LoadBalancer
|
type: LoadBalancer
|
||||||
ports:
|
ports:
|
||||||
- name: ssh
|
- name: ssh
|
||||||
port: {{ .apps.gitea.sshPort }}
|
port: {{ .sshPort }}
|
||||||
targetPort: 2222
|
targetPort: 2222
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: db-init
|
- name: db-init
|
||||||
image: {{ .apps.postgres.image }}
|
image: postgres:17
|
||||||
command: ["/bin/bash", "-c"]
|
command: ["/bin/bash", "-c"]
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -53,16 +53,16 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.postgres.password
|
key: postgres.password
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.immich.dbHostname }}"
|
value: "{{ .dbHostname }}"
|
||||||
- name: DB_DATABASE_NAME
|
- name: DB_DATABASE_NAME
|
||||||
value: "{{ .apps.immich.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.immich.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.immich.dbPassword
|
key: dbPassword
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ spec:
|
|||||||
component: machine-learning
|
component: machine-learning
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: "{{ .apps.immich.mlImage }}"
|
- image: "{{ .mlImage }}"
|
||||||
name: immich-machine-learning
|
name: immich-machine-learning
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .apps.immich.mlPort }}
|
- containerPort: {{ .mlPort }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
env:
|
env:
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: "{{ .apps.immich.timezone }}"
|
value: "{{ .timezone }}"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /cache
|
- mountPath: /cache
|
||||||
name: immich-cache
|
name: immich-cache
|
||||||
|
|||||||
@@ -20,27 +20,27 @@ spec:
|
|||||||
component: microservices
|
component: microservices
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: "{{ .apps.immich.serverImage }}"
|
- image: "{{ .serverImage }}"
|
||||||
name: immich-microservices
|
name: immich-microservices
|
||||||
env:
|
env:
|
||||||
- name: REDIS_HOSTNAME
|
- name: REDIS_HOSTNAME
|
||||||
value: "{{ .apps.immich.redisHostname }}"
|
value: "{{ .redisHostname }}"
|
||||||
- name: REDIS_PASSWORD
|
- name: REDIS_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.redis.password
|
key: redis.password
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.immich.dbHostname }}"
|
value: "{{ .dbHostname }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.immich.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.immich.dbPassword
|
key: dbPassword
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: "{{ .apps.immich.timezone }}"
|
value: "{{ .timezone }}"
|
||||||
- name: IMMICH_WORKERS_EXCLUDE
|
- name: IMMICH_WORKERS_EXCLUDE
|
||||||
value: api
|
value: api
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|||||||
@@ -20,30 +20,30 @@ spec:
|
|||||||
component: server
|
component: server
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: "{{ .apps.immich.serverImage }}"
|
- image: "{{ .serverImage }}"
|
||||||
name: immich-server
|
name: immich-server
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .apps.immich.serverPort }}
|
- containerPort: {{ .serverPort }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
env:
|
env:
|
||||||
- name: REDIS_HOSTNAME
|
- name: REDIS_HOSTNAME
|
||||||
value: "{{ .apps.immich.redisHostname }}"
|
value: "{{ .redisHostname }}"
|
||||||
- name: REDIS_PASSWORD
|
- name: REDIS_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.redis.password
|
key: redis.password
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.immich.dbHostname }}"
|
value: "{{ .dbHostname }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.immich.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: immich-secrets
|
name: immich-secrets
|
||||||
key: apps.immich.dbPassword
|
key: dbPassword
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: "{{ .apps.immich.timezone }}"
|
value: "{{ .timezone }}"
|
||||||
- name: IMMICH_WORKERS_EXCLUDE
|
- name: IMMICH_WORKERS_EXCLUDE
|
||||||
value: microservices
|
value: microservices
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ kind: Ingress
|
|||||||
metadata:
|
metadata:
|
||||||
name: immich-public
|
name: immich-public
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/target: "{{ .cloud.domain }}"
|
external-dns.alpha.kubernetes.io/target: "{{ .externalDnsDomain }}"
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: "{{ .apps.immich.domain }}"
|
- host: "{{ .domain }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -21,4 +21,4 @@ spec:
|
|||||||
tls:
|
tls:
|
||||||
- secretName: wildcard-wild-cloud-tls
|
- secretName: wildcard-wild-cloud-tls
|
||||||
hosts:
|
hosts:
|
||||||
- "{{ .apps.immich.domain }}"
|
- "{{ .domain }}"
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
name: immich
|
name: immich
|
||||||
install: true
|
install: true
|
||||||
description: Immich is a self-hosted photo and video backup solution that allows you to store, manage, and share your media files securely.
|
description: Immich is a self-hosted photo and video backup solution that allows you
|
||||||
version: 1.0.0
|
to store, manage, and share your media files securely.
|
||||||
icon: https://immich.app/assets/images/logo.png
|
version: release
|
||||||
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/immich.svg
|
||||||
requires:
|
requires:
|
||||||
- name: redis
|
- name: redis
|
||||||
- name: postgres
|
- name: postgres
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: immich
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
serverImage: ghcr.io/immich-app/immich-server:release
|
serverImage: ghcr.io/immich-app/immich-server:release
|
||||||
mlImage: ghcr.io/immich-app/immich-machine-learning:release
|
mlImage: ghcr.io/immich-app/immich-machine-learning:release
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
@@ -20,6 +23,7 @@ defaultConfig:
|
|||||||
domain: immich.{{ .cloud.domain }}
|
domain: immich.{{ .cloud.domain }}
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.immich.dbPassword
|
- key: dbPassword
|
||||||
- key: apps.postgres.password
|
requiredSecrets:
|
||||||
- key: apps.redis.password
|
- redis.password
|
||||||
|
- postgres.password
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: immich
|
name: "{{ .namespace }}"
|
||||||
@@ -9,7 +9,7 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.immich.storage }}
|
storage: {{ .storage }}
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
@@ -21,4 +21,4 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.immich.cacheStorage }}
|
storage: {{ .cacheStorage }}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 3001
|
- port: 3001
|
||||||
targetPort: {{ .apps.immich.serverPort }}
|
targetPort: {{ .serverPort }}
|
||||||
selector:
|
selector:
|
||||||
app: immich
|
app: immich
|
||||||
component: server
|
component: server
|
||||||
@@ -25,7 +25,7 @@ metadata:
|
|||||||
app: immich-machine-learning
|
app: immich-machine-learning
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .apps.immich.mlPort }}
|
- port: {{ .mlPort }}
|
||||||
selector:
|
selector:
|
||||||
app: immich
|
app: immich
|
||||||
component: machine-learning
|
component: machine-learning
|
||||||
|
|||||||
@@ -26,23 +26,23 @@ spec:
|
|||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
env:
|
env:
|
||||||
- name: PGHOST
|
- name: PGHOST
|
||||||
value: {{ .apps.keila.dbHostname }}
|
value: {{ .dbHostname }}
|
||||||
- name: PGUSER
|
- name: PGUSER
|
||||||
value: postgres
|
value: postgres
|
||||||
- name: PGPASSWORD
|
- name: PGPASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.postgres.password
|
key: postgres.password
|
||||||
- name: DB_NAME
|
- name: DB_NAME
|
||||||
value: {{ .apps.keila.dbName }}
|
value: {{ .dbName }}
|
||||||
- name: DB_USER
|
- name: DB_USER
|
||||||
value: {{ .apps.keila.dbUsername }}
|
value: {{ .dbUsername }}
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.keila.dbPassword
|
key: dbPassword
|
||||||
command:
|
command:
|
||||||
- /bin/bash
|
- /bin/bash
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -14,54 +14,54 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: keila
|
- name: keila
|
||||||
image: {{ .apps.keila.image }}
|
image: "{{ .image }}"
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .apps.keila.port }}
|
- containerPort: {{ .port }}
|
||||||
env:
|
env:
|
||||||
- name: DB_URL
|
- name: DB_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.keila.dbUrl
|
key: dbUrl
|
||||||
- name: URL_HOST
|
- name: URL_HOST
|
||||||
value: {{ .apps.keila.domain }}
|
value: "{{ .domain }}"
|
||||||
- name: URL_SCHEMA
|
- name: URL_SCHEMA
|
||||||
value: https
|
value: https
|
||||||
- name: URL_PORT
|
- name: URL_PORT
|
||||||
value: "443"
|
value: "443"
|
||||||
- name: PORT
|
- name: PORT
|
||||||
value: "{{ .apps.keila.port }}"
|
value: "{{ .port }}"
|
||||||
- name: SECRET_KEY_BASE
|
- name: SECRET_KEY_BASE
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.keila.secretKeyBase
|
key: secretKeyBase
|
||||||
- name: MAILER_SMTP_HOST
|
- name: MAILER_SMTP_HOST
|
||||||
value: {{ .apps.keila.smtp.host }}
|
value: "{{ .smtp.host }}"
|
||||||
- name: MAILER_SMTP_PORT
|
- name: MAILER_SMTP_PORT
|
||||||
value: "{{ .apps.keila.smtp.port }}"
|
value: "{{ .smtp.port }}"
|
||||||
- name: MAILER_ENABLE_SSL
|
- name: MAILER_ENABLE_SSL
|
||||||
value: "{{ .apps.keila.smtp.tls }}"
|
value: "{{ .smtp.tls }}"
|
||||||
- name: MAILER_ENABLE_STARTTLS
|
- name: MAILER_ENABLE_STARTTLS
|
||||||
value: "{{ .apps.keila.smtp.startTls }}"
|
value: "{{ .smtp.startTls }}"
|
||||||
- name: MAILER_SMTP_USER
|
- name: MAILER_SMTP_USER
|
||||||
value: {{ .apps.keila.smtp.user }}
|
value: "{{ .smtp.user }}"
|
||||||
- name: MAILER_SMTP_PASSWORD
|
- name: MAILER_SMTP_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.keila.smtpPassword
|
key: smtpPassword
|
||||||
- name: MAILER_SMTP_FROM_EMAIL
|
- name: MAILER_SMTP_FROM_EMAIL
|
||||||
value: {{ .apps.keila.smtp.from }}
|
value: "{{ .smtp.from }}"
|
||||||
- name: DISABLE_REGISTRATION
|
- name: DISABLE_REGISTRATION
|
||||||
value: "{{ .apps.keila.disableRegistration }}"
|
value: "{{ .disableRegistration }}"
|
||||||
- name: KEILA_USER
|
- name: KEILA_USER
|
||||||
value: "{{ .apps.keila.adminUser }}"
|
value: "{{ .adminUser }}"
|
||||||
- name: KEILA_PASSWORD
|
- name: KEILA_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: keila-secrets
|
name: keila-secrets
|
||||||
key: apps.keila.adminPassword
|
key: adminPassword
|
||||||
- name: USER_CONTENT_DIR
|
- name: USER_CONTENT_DIR
|
||||||
value: /var/lib/keila/uploads
|
value: /var/lib/keila/uploads
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
@@ -70,13 +70,13 @@ spec:
|
|||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /
|
path: /
|
||||||
port: {{ .apps.keila.port }}
|
port: {{ .port }}
|
||||||
initialDelaySeconds: 30
|
initialDelaySeconds: 30
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /
|
path: /
|
||||||
port: {{ .apps.keila.port }}
|
port: {{ .port }}
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
|
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
traefik.ingress.kubernetes.io/router.middlewares: keila-cors@kubernetescrd
|
traefik.ingress.kubernetes.io/router.middlewares: keila-cors@kubernetescrd
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: {{ .apps.keila.domain }}
|
- host: {{ .domain }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -23,4 +23,4 @@ spec:
|
|||||||
tls:
|
tls:
|
||||||
- secretName: "wildcard-wild-cloud-tls"
|
- secretName: "wildcard-wild-cloud-tls"
|
||||||
hosts:
|
hosts:
|
||||||
- "{{ .apps.keila.domain }}"
|
- "{{ .domain }}"
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
name: keila
|
name: keila
|
||||||
description: Keila is an open-source email marketing platform that allows you to send newsletters and manage mailing lists with privacy and control.
|
description: Keila is an open-source email marketing platform that allows you to send newsletters and manage mailing lists with privacy and control.
|
||||||
version: 1.0.0
|
version: 0.17.1
|
||||||
icon: https://www.keila.io/images/logo.svg
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/keila.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
image: pentacent/keila:latest
|
namespace: keila
|
||||||
|
externalDnsDomain: "{{ .cloud.domain }}"
|
||||||
|
image: pentacent/keila:0.17.1
|
||||||
port: 4000
|
port: 4000
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
domain: keila.{{ .cloud.domain }}
|
domain: keila.{{ .cloud.domain }}
|
||||||
dbHostname: postgres.postgres.svc.cluster.local
|
dbHostname: "{{ .apps.postgres.host }}"
|
||||||
|
dbPort: "{{ .apps.postgres.port }}"
|
||||||
dbName: keila
|
dbName: keila
|
||||||
dbUsername: keila
|
dbUsername: keila
|
||||||
disableRegistration: "true"
|
disableRegistration: "true"
|
||||||
@@ -20,12 +23,15 @@ defaultConfig:
|
|||||||
port: "{{ .cloud.smtp.port }}"
|
port: "{{ .cloud.smtp.port }}"
|
||||||
from: "{{ .cloud.smtp.from }}"
|
from: "{{ .cloud.smtp.from }}"
|
||||||
user: "{{ .cloud.smtp.user }}"
|
user: "{{ .cloud.smtp.user }}"
|
||||||
tls: {{ .cloud.smtp.tls }}
|
tls: "{{ .cloud.smtp.tls }}"
|
||||||
startTls: {{ .cloud.smtp.startTls }}
|
startTls: "{{ .cloud.smtp.startTls }}"
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.keila.secretKeyBase
|
- key: secretKeyBase
|
||||||
- key: apps.keila.dbPassword
|
default: "{{ random.AlphaNum 64 }}"
|
||||||
- key: apps.keila.dbUrl
|
- key: dbPassword
|
||||||
- key: apps.keila.adminPassword
|
- key: dbUrl
|
||||||
- key: apps.keila.smtpPassword
|
default: "postgres://{{ .app.dbUsername }}:{{ .secrets.dbPassword }}@{{ .app.dbHostname }}:{{ .app.dbPort }}/keila?sslmode=disable"
|
||||||
- key: apps.postgres.password
|
- key: adminPassword
|
||||||
|
- key: smtpPassword
|
||||||
|
requiredSecrets:
|
||||||
|
- postgres.password
|
||||||
@@ -21,8 +21,8 @@ spec:
|
|||||||
- "OPTIONS"
|
- "OPTIONS"
|
||||||
accessControlAllowOriginList:
|
accessControlAllowOriginList:
|
||||||
- "http://localhost:1313"
|
- "http://localhost:1313"
|
||||||
- "https://*.{{ .cloud.domain }}"
|
- "https://*.{{ .externalDnsDomain }}"
|
||||||
- "https://{{ .cloud.domain }}"
|
- "https://{{ .externalDnsDomain }}"
|
||||||
accessControlExposeHeaders:
|
accessControlExposeHeaders:
|
||||||
- "*"
|
- "*"
|
||||||
accessControlMaxAge: 86400
|
accessControlMaxAge: 86400
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: keila
|
name: "{{ .namespace }}"
|
||||||
@@ -7,4 +7,4 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.keila.storage }}
|
storage: {{ .storage }}
|
||||||
@@ -7,5 +7,5 @@ spec:
|
|||||||
component: web
|
component: web
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
targetPort: {{ .apps.keila.port }}
|
targetPort: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
@@ -28,23 +28,23 @@ spec:
|
|||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
env:
|
env:
|
||||||
- name: PGHOST
|
- name: PGHOST
|
||||||
value: {{ .apps.listmonk.dbHost }}
|
value: {{ .dbHost }}
|
||||||
- name: PGUSER
|
- name: PGUSER
|
||||||
value: postgres
|
value: postgres
|
||||||
- name: PGPASSWORD
|
- name: PGPASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: listmonk-secrets
|
name: listmonk-secrets
|
||||||
key: apps.postgres.password
|
key: postgres.password
|
||||||
- name: DB_NAME
|
- name: DB_NAME
|
||||||
value: {{ .apps.listmonk.dbName }}
|
value: {{ .dbName }}
|
||||||
- name: DB_USER
|
- name: DB_USER
|
||||||
value: {{ .apps.listmonk.dbUser }}
|
value: {{ .dbUser }}
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: listmonk-secrets
|
name: listmonk-secrets
|
||||||
key: apps.listmonk.dbPassword
|
key: dbPassword
|
||||||
command:
|
command:
|
||||||
- /bin/bash
|
- /bin/bash
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -30,21 +30,23 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: LISTMONK_app__address
|
- name: LISTMONK_app__address
|
||||||
value: "0.0.0.0:9000"
|
value: "0.0.0.0:9000"
|
||||||
|
- name: LISTMONK_app__root_url
|
||||||
|
value: "{{ .rootUrl }}"
|
||||||
- name: LISTMONK_db__host
|
- name: LISTMONK_db__host
|
||||||
value: {{ .apps.listmonk.dbHost }}
|
value: {{ .dbHost }}
|
||||||
- name: LISTMONK_db__port
|
- name: LISTMONK_db__port
|
||||||
value: "{{ .apps.listmonk.dbPort }}"
|
value: "{{ .dbPort }}"
|
||||||
- name: LISTMONK_db__user
|
- name: LISTMONK_db__user
|
||||||
value: {{ .apps.listmonk.dbUser }}
|
value: {{ .dbUser }}
|
||||||
- name: LISTMONK_db__database
|
- name: LISTMONK_db__database
|
||||||
value: {{ .apps.listmonk.dbName }}
|
value: {{ .dbName }}
|
||||||
- name: LISTMONK_db__ssl_mode
|
- name: LISTMONK_db__ssl_mode
|
||||||
value: {{ .apps.listmonk.dbSSLMode }}
|
value: {{ .dbSSLMode }}
|
||||||
- name: LISTMONK_db__password
|
- name: LISTMONK_db__password
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: listmonk-secrets
|
name: listmonk-secrets
|
||||||
key: apps.listmonk.dbPassword
|
key: dbPassword
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 500m
|
cpu: 500m
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- {{ .apps.listmonk.domain }}
|
- {{ .domain }}
|
||||||
secretName: {{ .apps.listmonk.tlsSecretName }}
|
secretName: {{ .tlsSecretName }}
|
||||||
rules:
|
rules:
|
||||||
- host: {{ .apps.listmonk.domain }}
|
- host: {{ .domain }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
name: listmonk
|
name: listmonk
|
||||||
description: Listmonk is a standalone, self-hosted, newsletter and mailing list manager. It is fast, feature-rich, and packed into a single binary.
|
description: Listmonk is a standalone, self-hosted, newsletter and mailing list manager.
|
||||||
|
It is fast, feature-rich, and packed into a single binary.
|
||||||
version: 5.0.3
|
version: 5.0.3
|
||||||
icon: https://listmonk.app/static/images/logo.svg
|
icon: https://listmonk.app/static/images/logo.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: listmonk
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
domain: listmonk.{{ .cloud.domain }}
|
domain: listmonk.{{ .cloud.domain }}
|
||||||
|
rootUrl: https://listmonk.{{ .cloud.domain }}
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
dbHost: postgres.postgres.svc.cluster.local
|
dbHost: postgres.postgres.svc.cluster.local
|
||||||
@@ -15,6 +19,8 @@ defaultConfig:
|
|||||||
dbSSLMode: disable
|
dbSSLMode: disable
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.listmonk.dbPassword
|
- key: dbPassword
|
||||||
- key: apps.listmonk.dbUrl
|
- key: dbUrl
|
||||||
- key: apps.postgres.password
|
default: 'postgres://{{ .app.dbUser }}:{{ .secrets.dbPassword }}@{{ .app.dbHost }}:{{ .app.dbPort }}/{{ .app.dbName }}?sslmode={{ .app.dbSSLMode }}'
|
||||||
|
requiredSecrets:
|
||||||
|
- postgres.password
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: listmonk
|
name: "{{ .namespace }}"
|
||||||
@@ -8,4 +8,4 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.listmonk.storage }}
|
storage: {{ .storage }}
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
name: loomio
|
name: loomio
|
||||||
description: Loomio is a collaborative decision-making tool that makes it easy for groups to make decisions together
|
description: Loomio is a collaborative decision-making tool that makes it easy for groups to make decisions together
|
||||||
version: 3.0.11
|
version: 3.0.11
|
||||||
icon: https://www.loomio.com/favicon.ico
|
icon: https://www.loomio.com/brand/logo_gold.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
installed_as: postgres
|
installed_as: postgres
|
||||||
- name: redis
|
- name: redis
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
namespace: loomio
|
namespace: loomio
|
||||||
externalDnsDomain: {{ .cloud.domain }}
|
externalDnsDomain: "{{ .cloud.domain }}"
|
||||||
image: loomio/loomio:v3.0.11
|
image: loomio/loomio:v3.0.11
|
||||||
workerImage: loomio/loomio:v3.0.11
|
workerImage: loomio/loomio:v3.0.11
|
||||||
appName: Loomio
|
appName: Loomio
|
||||||
domain: loomio.{{ .cloud.domain }}
|
domain: "loomio.{{ .cloud.domain }}"
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
port: 3000
|
port: 3000
|
||||||
storage:
|
storage:
|
||||||
uploads: 5Gi
|
uploads: 5Gi
|
||||||
files: 5Gi
|
files: 5Gi
|
||||||
plugins: 1Gi
|
plugins: 1Gi
|
||||||
redisUrl: {{ .apps.redis.uri }}
|
redisUrl: "{{ .apps.redis.uri }}"
|
||||||
adminEmail: "admin@{{ .cloud.domain }}"
|
adminEmail: "{{ .operator.email }}"
|
||||||
supportEmail: "support@{{ .cloud.domain }}"
|
supportEmail: "{{ .operator.email }}"
|
||||||
forceSSL: "1"
|
forceSSL: "1"
|
||||||
useRackAttack: "1"
|
useRackAttack: "1"
|
||||||
pumaWorkers: "2"
|
pumaWorkers: "2"
|
||||||
@@ -31,8 +31,8 @@ defaultConfig:
|
|||||||
db:
|
db:
|
||||||
name: loomio
|
name: loomio
|
||||||
user: loomio
|
user: loomio
|
||||||
host: {{ .apps.postgres.host }}
|
host: "{{ .apps.postgres.host }}"
|
||||||
port: {{ .apps.postgres.port }}
|
port: "{{ .apps.postgres.port }}"
|
||||||
smtp:
|
smtp:
|
||||||
auth: plain
|
auth: plain
|
||||||
domain: "{{ .cloud.domain }}"
|
domain: "{{ .cloud.domain }}"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
name: memcached
|
name: memcached
|
||||||
spec:
|
spec:
|
||||||
replicas: {{ .apps.memcached.replicas }}
|
replicas: {{ .replicas }}
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
component: cache
|
component: cache
|
||||||
@@ -14,24 +14,24 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: memcached
|
- name: memcached
|
||||||
image: {{ .apps.memcached.image }}
|
image: "{{ .image }}"
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .apps.memcached.port }}
|
- containerPort: {{ .port }}
|
||||||
name: memcached
|
name: memcached
|
||||||
args:
|
args:
|
||||||
- -m
|
- -m
|
||||||
- {{ .apps.memcached.memoryLimit }}
|
- "{{ .memoryLimit }}"
|
||||||
- -c
|
- -c
|
||||||
- "{{ .apps.memcached.maxConnections }}"
|
- "{{ .maxConnections }}"
|
||||||
- -p
|
- -p
|
||||||
- "{{ .apps.memcached.port }}"
|
- "{{ .port }}"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
memory: {{ .apps.memcached.resources.requests.memory }}
|
memory: "{{ .resources.requests.memory }}"
|
||||||
cpu: {{ .apps.memcached.resources.requests.cpu }}
|
cpu: "{{ .resources.requests.cpu }}"
|
||||||
limits:
|
limits:
|
||||||
memory: {{ .apps.memcached.resources.limits.memory }}
|
memory: "{{ .resources.limits.memory }}"
|
||||||
cpu: {{ .apps.memcached.resources.limits.cpu }}
|
cpu: "{{ .resources.limits.cpu }}"
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
runAsUser: 11211
|
runAsUser: 11211
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
name: memcached
|
name: memcached
|
||||||
description: Memcached is an in-memory key-value store for small chunks of arbitrary data, commonly used as a cache layer.
|
description: Memcached is an in-memory key-value store for small chunks of arbitrary
|
||||||
|
data, commonly used as a cache layer.
|
||||||
version: 1.6.32
|
version: 1.6.32
|
||||||
icon: https://memcached.org/memcached-logo.png
|
icon: https://www.vectorlogo.zone/logos/memcached/memcached-icon.svg
|
||||||
requires: []
|
requires: []
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: memcached
|
||||||
image: memcached:1.6.32-alpine
|
image: memcached:1.6.32-alpine
|
||||||
port: 11211
|
port: 11211
|
||||||
memoryLimit: 64m
|
memoryLimit: 64m
|
||||||
@@ -16,4 +18,4 @@ defaultConfig:
|
|||||||
limits:
|
limits:
|
||||||
memory: 128Mi
|
memory: 128Mi
|
||||||
cpu: 200m
|
cpu: 200m
|
||||||
defaultSecrets: []
|
defaultSecrets: []
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: memcached
|
name: "{{ .namespace }}"
|
||||||
@@ -4,8 +4,8 @@ metadata:
|
|||||||
name: memcached
|
name: memcached
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .apps.memcached.port }}
|
- port: {{ .port }}
|
||||||
targetPort: {{ .apps.memcached.port }}
|
targetPort: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: memcached
|
name: memcached
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ version: 9.1.0
|
|||||||
icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
|
icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
|
||||||
requires: []
|
requires: []
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: mysql
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
image: mysql:9.1.0
|
image: mysql:9.1.0
|
||||||
port: 3306
|
port: 3306
|
||||||
storage: 20Gi
|
storage: 20Gi
|
||||||
@@ -13,5 +15,5 @@ defaultConfig:
|
|||||||
timezone: UTC
|
timezone: UTC
|
||||||
enableSSL: false
|
enableSSL: false
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.mysql.rootPassword
|
- key: rootPassword
|
||||||
- key: apps.mysql.password
|
- key: password
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: mysql
|
name: "{{ .namespace }}"
|
||||||
@@ -9,7 +9,7 @@ spec:
|
|||||||
publishNotReadyAddresses: true
|
publishNotReadyAddresses: true
|
||||||
ports:
|
ports:
|
||||||
- name: mysql
|
- name: mysql
|
||||||
port: {{ .apps.mysql.port }}
|
port: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: mysql
|
targetPort: mysql
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ spec:
|
|||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
ports:
|
ports:
|
||||||
- name: mysql
|
- name: mysql
|
||||||
port: {{ .apps.mysql.port }}
|
port: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: mysql
|
targetPort: mysql
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ spec:
|
|||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
containers:
|
containers:
|
||||||
- name: mysql
|
- name: mysql
|
||||||
image: {{ .apps.mysql.image }}
|
image: {{ .image }}
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
@@ -42,21 +42,21 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: mysql-secrets
|
name: mysql-secrets
|
||||||
key: apps.mysql.rootPassword
|
key: rootPassword
|
||||||
- name: MYSQL_USER
|
- name: MYSQL_USER
|
||||||
value: {{ .apps.mysql.user }}
|
value: {{ .user }}
|
||||||
- name: MYSQL_PASSWORD
|
- name: MYSQL_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: mysql-secrets
|
name: mysql-secrets
|
||||||
key: apps.mysql.password
|
key: password
|
||||||
- name: MYSQL_DATABASE
|
- name: MYSQL_DATABASE
|
||||||
value: {{ .apps.mysql.dbName }}
|
value: {{ .dbName }}
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: {{ .apps.mysql.timezone }}
|
value: {{ .timezone }}
|
||||||
ports:
|
ports:
|
||||||
- name: mysql
|
- name: mysql
|
||||||
containerPort: {{ .apps.mysql.port }}
|
containerPort: {{ .port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
exec:
|
exec:
|
||||||
@@ -113,4 +113,4 @@ spec:
|
|||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.mysql.storage }}
|
storage: {{ .storage }}
|
||||||
@@ -45,7 +45,7 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: open-webui-secrets
|
name: open-webui-secrets
|
||||||
key: apps.openWebui.secretKey
|
key: openWebui.secretKey
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: data
|
- name: data
|
||||||
mountPath: /app/backend/data
|
mountPath: /app/backend/data
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ kind: Ingress
|
|||||||
metadata:
|
metadata:
|
||||||
name: open-webui
|
name: open-webui
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
traefik.ingress.kubernetes.io/router.middlewares: crowdsec-crowdsec-bouncer@kubernetescrd,crowdsec-rate-limit@kubernetescrd
|
traefik.ingress.kubernetes.io/router.middlewares: crowdsec-crowdsec-bouncer@kubernetescrd,crowdsec-rate-limit@kubernetescrd
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: {{ .apps.open-webui.domain }}
|
- host: {{ .domain }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -22,4 +22,4 @@ spec:
|
|||||||
tls:
|
tls:
|
||||||
- secretName: wildcard-wild-cloud-tls
|
- secretName: wildcard-wild-cloud-tls
|
||||||
hosts:
|
hosts:
|
||||||
- {{ .apps.open-webui.domain }}
|
- {{ .domain }}
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
name: openWebui
|
name: openWebui
|
||||||
description: Open WebUI is a comprehensive, open-source web interface for AI models. Features a user-friendly design, supports various LLM runners, and operates entirely offline. Perfect for creating a ChatGPT-like experience with local or hosted models.
|
description: Open WebUI is a comprehensive, open-source web interface for AI models.
|
||||||
|
Features a user-friendly design, supports various LLM runners, and operates entirely
|
||||||
|
offline. Perfect for creating a ChatGPT-like experience with local or hosted models.
|
||||||
version: 0.4.5
|
version: 0.4.5
|
||||||
icon: https://docs.openwebui.com/assets/logo-dark.png
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/open-webui.svg
|
||||||
requires: []
|
requires: []
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: open-webui
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
image: ghcr.io/open-webui/open-webui:main
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
port: 8080
|
port: 8080
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
domain: chat.{{ .cloud.domain }}
|
domain: chat.{{ .cloud.domain }}
|
||||||
# vLLM integration - connect to existing vLLM service
|
|
||||||
vllmApiUrl: http://vllm-service.llm.svc.cluster.local:8000/v1
|
vllmApiUrl: http://vllm-service.llm.svc.cluster.local:8000/v1
|
||||||
# Authentication settings
|
|
||||||
enableAuth: true
|
enableAuth: true
|
||||||
enableSignup: false
|
enableSignup: false
|
||||||
defaultSecrets:
|
defaultSecrets: []
|
||||||
- key: apps.openWebui.secretKey
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: open-webui
|
name: "{{ .namespace }}"
|
||||||
@@ -5,17 +5,17 @@ kind: "ConfigMap"
|
|||||||
metadata:
|
metadata:
|
||||||
name: "openproject-core"
|
name: "openproject-core"
|
||||||
data:
|
data:
|
||||||
DATABASE_HOST: "{{ .apps.openproject.dbHostname }}"
|
DATABASE_HOST: "{{ .dbHostname }}"
|
||||||
DATABASE_PORT: "5432"
|
DATABASE_PORT: "5432"
|
||||||
DATABASE_URL: "postgresql://{{ .apps.openproject.dbUsername }}@{{ .apps.openproject.dbHostname }}:5432/{{ .apps.openproject.dbName }}"
|
DATABASE_URL: "postgresql://{{ .dbUsername }}@{{ .dbHostname }}:5432/{{ .dbName }}"
|
||||||
OPENPROJECT_SEED_ADMIN_USER_PASSWORD_RESET: "{{ .apps.openproject.adminPasswordReset }}"
|
OPENPROJECT_SEED_ADMIN_USER_PASSWORD_RESET: "{{ .adminPasswordReset }}"
|
||||||
OPENPROJECT_SEED_ADMIN_USER_NAME: "{{ .apps.openproject.adminUserName }}"
|
OPENPROJECT_SEED_ADMIN_USER_NAME: "{{ .adminUserName }}"
|
||||||
OPENPROJECT_SEED_ADMIN_USER_MAIL: "{{ .apps.openproject.adminUserEmail }}"
|
OPENPROJECT_SEED_ADMIN_USER_MAIL: "{{ .adminUserEmail }}"
|
||||||
OPENPROJECT_HTTPS: "{{ .apps.openproject.https }}"
|
OPENPROJECT_HTTPS: "{{ .https }}"
|
||||||
OPENPROJECT_SEED_LOCALE: "{{ .apps.openproject.seedLocale }}"
|
OPENPROJECT_SEED_LOCALE: "{{ .seedLocale }}"
|
||||||
OPENPROJECT_HOST__NAME: "{{ .apps.openproject.domain }}"
|
OPENPROJECT_HOST__NAME: "{{ .domain }}"
|
||||||
OPENPROJECT_HSTS: "{{ .apps.openproject.hsts }}"
|
OPENPROJECT_HSTS: "{{ .hsts }}"
|
||||||
OPENPROJECT_RAILS__CACHE__STORE: "{{ .apps.openproject.cacheStore }}"
|
OPENPROJECT_RAILS__CACHE__STORE: "{{ .cacheStore }}"
|
||||||
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "{{ .apps.openproject.railsRelativeUrlRoot }}"
|
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "{{ .railsRelativeUrlRoot }}"
|
||||||
POSTGRES_STATEMENT_TIMEOUT: "{{ .apps.openproject.postgresStatementTimeout }}"
|
POSTGRES_STATEMENT_TIMEOUT: "{{ .postgresStatementTimeout }}"
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ kind: "ConfigMap"
|
|||||||
metadata:
|
metadata:
|
||||||
name: "openproject-memcached"
|
name: "openproject-memcached"
|
||||||
data:
|
data:
|
||||||
OPENPROJECT_CACHE__MEMCACHE__SERVER: "{{ .apps.openproject.memcachedHostname }}:{{ .apps.openproject.memcachedPort }}"
|
OPENPROJECT_CACHE__MEMCACHE__SERVER: "{{ .memcachedHostname }}:{{ .memcachedPort }}"
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: db-init
|
- name: db-init
|
||||||
image: {{ .apps.postgres.image }}
|
image: postgres:17
|
||||||
command: ["/bin/bash", "-c"]
|
command: ["/bin/bash", "-c"]
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -36,16 +36,16 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: postgres-secrets
|
name: postgres-secrets
|
||||||
key: apps.postgres.password
|
key: password
|
||||||
- name: DB_HOSTNAME
|
- name: DB_HOSTNAME
|
||||||
value: "{{ .apps.openproject.dbHostname }}"
|
value: "{{ .dbHostname }}"
|
||||||
- name: DB_DATABASE_NAME
|
- name: DB_DATABASE_NAME
|
||||||
value: "{{ .apps.openproject.dbName }}"
|
value: "{{ .dbName }}"
|
||||||
- name: DB_USERNAME
|
- name: DB_USERNAME
|
||||||
value: "{{ .apps.openproject.dbUsername }}"
|
value: "{{ .dbUsername }}"
|
||||||
- name: DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
restartPolicy: OnFailure
|
restartPolicy: OnFailure
|
||||||
@@ -7,10 +7,10 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- "{{ .apps.openproject.domain }}"
|
- "{{ .domain }}"
|
||||||
secretName: "wildcard-wild-cloud-tls"
|
secretName: "wildcard-wild-cloud-tls"
|
||||||
rules:
|
rules:
|
||||||
- host: "{{ .apps.openproject.domain }}"
|
- host: "{{ .domain }}"
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
name: openproject
|
name: openproject
|
||||||
description: OpenProject is an open-source project management software that provides comprehensive features for project planning, tracking, and collaboration.
|
description: OpenProject is an open-source project management software that provides
|
||||||
|
comprehensive features for project planning, tracking, and collaboration.
|
||||||
version: 16.1.1
|
version: 16.1.1
|
||||||
icon: https://www.openproject.org/assets/images/openproject-logo.png
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/openproject.svg
|
||||||
requires:
|
requires:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
- name: memcached
|
- name: memcached
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
|
namespace: openproject
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
serverImage: openproject/openproject:16.1.1-slim
|
serverImage: openproject/openproject:16.1.1-slim
|
||||||
timezone: UTC
|
timezone: UTC
|
||||||
serverPort: 8080
|
serverPort: 8080
|
||||||
@@ -20,14 +23,15 @@ defaultConfig:
|
|||||||
hsts: true
|
hsts: true
|
||||||
seedLocale: en
|
seedLocale: en
|
||||||
adminUserName: OpenProject Admin
|
adminUserName: OpenProject Admin
|
||||||
adminUserEmail: "{{ .operator.email }}"
|
adminUserEmail: '{{ .operator.email }}'
|
||||||
adminPasswordReset: true
|
adminPasswordReset: true
|
||||||
postgresStatementTimeout: 120s
|
postgresStatementTimeout: 120s
|
||||||
tmpVolumesStorage: 2Gi
|
tmpVolumesStorage: 2Gi
|
||||||
tlsSecretName: wildcard-wild-cloud-tls
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
cacheStore: memcache
|
cacheStore: memcache
|
||||||
railsRelativeUrlRoot: ""
|
railsRelativeUrlRoot: ''
|
||||||
defaultSecrets:
|
defaultSecrets:
|
||||||
- key: apps.openproject.dbPassword
|
- key: dbPassword
|
||||||
- key: apps.openproject.adminPassword
|
- key: adminPassword
|
||||||
- key: apps.postgres.password
|
requiredSecrets:
|
||||||
|
- postgres.password
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: openproject
|
name: "{{ .namespace }}"
|
||||||
@@ -8,5 +8,5 @@ spec:
|
|||||||
accessModes: [ReadWriteMany]
|
accessModes: [ReadWriteMany]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: "{{ .apps.openproject.storage }}"
|
storage: "{{ .storage }}"
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: app-tmp
|
- name: app-tmp
|
||||||
# we can't use emptyDir due to the sticky bit / world writable issue
|
# we can't use emptyDir due to the sticky bit / world writable issue
|
||||||
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
||||||
@@ -39,13 +39,13 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: "data"
|
- name: "data"
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: openproject
|
claimName: openproject
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: check-db-ready
|
- name: check-db-ready
|
||||||
image: "{{ .apps.postgres.image }}"
|
image: "postgres:17"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
command: [
|
command: [
|
||||||
'sh',
|
'sh',
|
||||||
@@ -62,12 +62,12 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.adminPassword
|
key: adminPassword
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 200Mi
|
memory: 200Mi
|
||||||
@@ -91,7 +91,7 @@ spec:
|
|||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
containers:
|
containers:
|
||||||
- name: seeder
|
- name: seeder
|
||||||
image: "{{ .apps.openproject.serverImage }}"
|
image: "{{ .serverImage }}"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
args:
|
args:
|
||||||
- bash
|
- bash
|
||||||
@@ -106,12 +106,12 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.adminPassword
|
key: adminPassword
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 512Mi
|
memory: 512Mi
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: app-tmp
|
- name: app-tmp
|
||||||
# we can't use emptyDir due to the sticky bit / world writable issue
|
# we can't use emptyDir due to the sticky bit / world writable issue
|
||||||
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
||||||
@@ -55,12 +55,12 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: "data"
|
- name: "data"
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: openproject
|
claimName: openproject
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: wait-for-db
|
- name: wait-for-db
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
capabilities:
|
capabilities:
|
||||||
@@ -72,8 +72,13 @@ spec:
|
|||||||
runAsUser: 1000
|
runAsUser: 1000
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
image: {{ .apps.openproject.serverImage }}
|
image: postgres:17
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
|
command: [
|
||||||
|
'sh',
|
||||||
|
'-c',
|
||||||
|
'until pg_isready -h $DATABASE_HOST -p $DATABASE_PORT; do echo "waiting for database $DATABASE_HOST:$DATABASE_PORT"; sleep 2; done; echo "Database is ready!"'
|
||||||
|
]
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: openproject-core
|
name: openproject-core
|
||||||
@@ -84,14 +89,12 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.adminPassword
|
key: adminPassword
|
||||||
args:
|
|
||||||
- /app/docker/prod/wait-for-db
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 1Gi
|
memory: 1Gi
|
||||||
@@ -115,7 +118,7 @@ spec:
|
|||||||
runAsUser: 1000
|
runAsUser: 1000
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
image: {{ .apps.openproject.serverImage }}
|
image: {{ .serverImage }}
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
@@ -127,12 +130,12 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.adminPassword
|
key: adminPassword
|
||||||
args:
|
args:
|
||||||
- /app/docker/prod/web
|
- /app/docker/prod/web
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: app-tmp
|
- name: app-tmp
|
||||||
# we can't use emptyDir due to the sticky bit / world writable issue
|
# we can't use emptyDir due to the sticky bit / world writable issue
|
||||||
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
# see: https://github.com/kubernetes/kubernetes/issues/110835
|
||||||
@@ -55,7 +55,7 @@ spec:
|
|||||||
accessModes: ["ReadWriteOnce"]
|
accessModes: ["ReadWriteOnce"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .apps.openproject.tmpVolumesStorage }}
|
storage: {{ .tmpVolumesStorage }}
|
||||||
- name: "data"
|
- name: "data"
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: openproject
|
claimName: openproject
|
||||||
@@ -72,8 +72,13 @@ spec:
|
|||||||
runAsUser: 1000
|
runAsUser: 1000
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
image: {{ .apps.openproject.serverImage }}
|
image: postgres:17
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
|
command: [
|
||||||
|
'sh',
|
||||||
|
'-c',
|
||||||
|
'until pg_isready -h $DATABASE_HOST -p $DATABASE_PORT; do echo "waiting for database $DATABASE_HOST:$DATABASE_PORT"; sleep 2; done; echo "Database is ready!"'
|
||||||
|
]
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: openproject-core
|
name: openproject-core
|
||||||
@@ -84,15 +89,12 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
- name: OPENPROJECT_SEED_ADMIN_USER_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.adminPassword
|
key: adminPassword
|
||||||
args:
|
|
||||||
- bash
|
|
||||||
- /app/docker/prod/wait-for-db
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 1Gi
|
memory: 1Gi
|
||||||
@@ -116,7 +118,7 @@ spec:
|
|||||||
runAsUser: 1000
|
runAsUser: 1000
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
image: {{ .apps.openproject.serverImage }}
|
image: {{ .serverImage }}
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
@@ -132,7 +134,7 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: openproject-secrets
|
name: openproject-secrets
|
||||||
key: apps.openproject.dbPassword
|
key: dbPassword
|
||||||
- name: "OPENPROJECT_GOOD_JOB_QUEUES"
|
- name: "OPENPROJECT_GOOD_JOB_QUEUES"
|
||||||
value: ""
|
value: ""
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: redis
|
|||||||
install: true
|
install: true
|
||||||
description: Redis is an open source, in-memory data structure store, used as a database, cache and message broker.
|
description: Redis is an open source, in-memory data structure store, used as a database, cache and message broker.
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
icon: <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 85 27"><path fill="#FF4438" fill-rule="evenodd" d="M75.29 13.813c0-2.968 2.2-4.69 4.947-4.69 2.052 0 3.884.99 4.763 3.444-.257 1.245-1.795 2.638-2.455 2.858-.55-1.173-1.172-1.869-1.758-1.869-.733 0-.77.513-.77 1.172 0 .467.134 1.155.295 1.983.243 1.25.548 2.82.548 4.43 0 2.93-2.052 5.092-5.203 5.092-2.885 0-4.48-1.892-5.19-4.913-1.885 3.377-4.641 4.913-6.754 4.913-3.302 0-4.08-2.441-4-4.917-1.328 2.345-3.882 4.917-6.331 4.917-2.501 0-3.384-2.177-3.182-4.712-1.498 2.791-4.208 4.712-6.82 4.712-2.836 0-4.239-2.252-3.785-5.044-1.907 2.344-5.458 5.044-9.149 5.044-4.209 0-6.04-2.27-6.258-5.114-2.031 3.256-4.77 5.224-8.03 5.224-4.709 0-6.393-4.187-6.638-7.611a111 111 0 0 1-6.113 7.464c-.256.257-.476.403-.732.403C1.832 26.6.11 22.862 0 21.47c.723-1.121 5.281-6.13 8.95-10.161 1.29-1.417 2.471-2.714 3.336-3.679-2.247.678-4.564 2.03-7.486 4.132-.513.366-1.942-2.968-1.906-5.533 3.371-2.49 8.5-4.066 12.64-4.066 5.79 0 9.123 3.224 9.123 7.694 0 3.737-3.114 7.84-7.657 7.987-2.362.061-3.876-1.265-4.65-2.902.092 2.532 1.409 5.65 4.943 5.65 3.853 0 5.704-2.326 8.463-5.795q.269-.339.55-.69c2.345-2.895 5.056-5.46 9.013-5.46 2.418 0 4.067 1.503 4.067 3.774 0 2.748-3.224 6.558-7.73 6.558-.77 0-1.472-.101-2.064-.301q-.024.173-.025.338c0 1.282.476 2.052 2.565 2.052 3.077 0 5.971-1.832 9.489-6.119 3.444-4.213 6.045-6.045 8.793-6.045 1.855 0 3.262 1.005 3.883 2.698C57.98 6.283 61.104 2.514 63.75 0c2.601 1.1 4.47 3.26 3.957 3.7-1.942 1.76-8.427 8.83-10.991 13.044-.66 1.099-1.283 2.308-1.283 2.894 0 .55.33.733.696.733 1.76 0 5.289-4.156 8.336-7.746 1.138-1.34 2.209-2.602 3.095-3.539 2.052.843 4.14 2.638 3.627 3.261-2.71 3.224-4.762 5.862-4.762 7.364 0 .403.146.66.696.66 1.026 0 1.978-.916 3.554-2.858.33-.403.732-.403.989.22.696 1.685 1.722 2.601 2.528 2.601.952 0 1.429-.843 1.429-2.125 0-.876-.107-1.895-.2-2.772-.069-.664-.13-1.246-.13-1.624m-59.096-.477c1.942 0 4.067-1.062 4.067-3.224 0-1.312-.814-2.521-2.99-2.89l-.342.535c-1.106 1.729-2.149 3.359-3.2 4.953.63.354 1.427.626 2.465.626m19.638.66c0-.587-.367-.99-.953-.99-1.47 0-3.687 2.063-4.73 4.055.385.15.837.232 1.323.232 2.601 0 4.36-1.978 4.36-3.297m9.636 5.312c0 .66.366 1.1 1.135 1.1 2.382 0 5.35-4.324 5.35-6.083 0-.732-.403-1.172-1.063-1.172-2.162 0-5.422 4.103-5.422 6.155M76.06 6.082c-.843 1.392-2.125 2.968-2.601 3.444-2.199-.916-4.25-2.748-3.957-3.26.806-1.43 2.125-2.968 2.601-3.445 2.198.916 4.25 2.785 3.957 3.261" clip-rule="evenodd"></path></svg>
|
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/redis.svg
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
namespace: redis
|
namespace: redis
|
||||||
image: redis:alpine
|
image: redis:alpine
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ spec:
|
|||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
nvidia.com/gpu.product: "{{ .apps.vllm.gpuProduct }}"
|
nvidia.com/gpu.product: "{{ .gpuProduct }}"
|
||||||
containers:
|
containers:
|
||||||
- name: vllm
|
- name: vllm
|
||||||
image: "{{ .apps.vllm.image }}"
|
image: "{{ .image }}"
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
@@ -31,10 +31,10 @@ spec:
|
|||||||
- ALL
|
- ALL
|
||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
args:
|
args:
|
||||||
- --model={{ .apps.vllm.model }}
|
- --model={{ .model }}
|
||||||
- --max-model-len={{ .apps.vllm.maxModelLen }}
|
- --max-model-len={{ .maxModelLen }}
|
||||||
- --tensor-parallel-size={{ .apps.vllm.tensorParallelSize }}
|
- --tensor-parallel-size={{ .tensorParallelSize }}
|
||||||
- --gpu-memory-utilization={{ .apps.vllm.gpuMemoryUtilization }}
|
- --gpu-memory-utilization={{ .gpuMemoryUtilization }}
|
||||||
{{- if .apps.vllm.enforceEager }}
|
{{- if .apps.vllm.enforceEager }}
|
||||||
- --enforce-eager=True
|
- --enforce-eager=True
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -48,13 +48,13 @@ spec:
|
|||||||
containerPort: 8000
|
containerPort: 8000
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: "{{ .apps.vllm.cpuRequest }}"
|
cpu: "{{ .cpuRequest }}"
|
||||||
memory: "{{ .apps.vllm.memoryRequest }}"
|
memory: "{{ .memoryRequest }}"
|
||||||
nvidia.com/gpu: {{ .apps.vllm.gpuCount }}
|
nvidia.com/gpu: {{ .gpuCount }}
|
||||||
limits:
|
limits:
|
||||||
cpu: "{{ .apps.vllm.cpuLimit }}"
|
cpu: "{{ .cpuLimit }}"
|
||||||
memory: "{{ .apps.vllm.memoryLimit }}"
|
memory: "{{ .memoryLimit }}"
|
||||||
nvidia.com/gpu: {{ .apps.vllm.gpuCount }}
|
nvidia.com/gpu: {{ .gpuCount }}
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /v1/models
|
path: /v1/models
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ kind: Ingress
|
|||||||
metadata:
|
metadata:
|
||||||
name: vllm
|
name: vllm
|
||||||
annotations:
|
annotations:
|
||||||
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
|
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
- host: {{ .apps.vllm.domain }}
|
- host: {{ .domain }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -21,5 +21,5 @@ spec:
|
|||||||
number: 8000
|
number: 8000
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- {{ .apps.vllm.domain }}
|
- {{ .domain }}
|
||||||
secretName: vllm-tls
|
secretName: vllm-tls
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
namespace: {{ .apps.vllm.namespace }}
|
namespace: {{ .namespace }}
|
||||||
labels:
|
labels:
|
||||||
- includeSelectors: true
|
- includeSelectors: true
|
||||||
pairs:
|
pairs:
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
name: vllm
|
name: vllm
|
||||||
description: vLLM is a fast and easy-to-use library for LLM inference and serving with OpenAI-compatible API
|
description: vLLM is a fast and easy-to-use library for LLM inference and serving
|
||||||
|
with OpenAI-compatible API
|
||||||
version: 0.5.4
|
version: 0.5.4
|
||||||
icon: https://raw.githubusercontent.com/vllm-project/vllm/main/docs/source/assets/logos/vllm-logo-text-light.png
|
icon: https://unpkg.com/@lobehub/icons-static-png@latest/dark/vllm.png
|
||||||
requires: []
|
requires: []
|
||||||
defaultConfig:
|
defaultConfig:
|
||||||
image: vllm/vllm-openai:v0.5.4
|
image: vllm/vllm-openai:v0.5.4
|
||||||
model: Qwen/Qwen2.5-7B-Instruct
|
model: Qwen/Qwen2.5-7B-Instruct
|
||||||
maxModelLen: 8192
|
maxModelLen: 8192
|
||||||
tensorParallelSize: 1
|
tensorParallelSize: 1
|
||||||
gpuMemoryUtilization: 0.90
|
gpuMemoryUtilization: 0.9
|
||||||
enforceEager: true
|
enforceEager: true
|
||||||
gpuProduct: "RTX 4090"
|
gpuProduct: RTX 4090
|
||||||
cpuRequest: "4"
|
cpuRequest: '4'
|
||||||
cpuLimit: "8"
|
cpuLimit: '8'
|
||||||
memoryRequest: "16Gi"
|
memoryRequest: 16Gi
|
||||||
memoryLimit: "24Gi"
|
memoryLimit: 24Gi
|
||||||
gpuCount: 1
|
gpuCount: 1
|
||||||
domain: vllm.{{ .cloud.domain }}
|
domain: vllm.{{ .cloud.domain }}
|
||||||
namespace: llm
|
namespace: llm
|
||||||
defaultSecrets: []
|
defaultSecrets: []
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .apps.vllm.namespace }}
|
name: {{ .namespace }}
|
||||||
Reference in New Issue
Block a user