feat: remove stalwart and roundcube

This commit is contained in:
2026-05-02 20:32:39 -05:00
parent e4c0a3b627
commit 1af493509b
20 changed files with 5 additions and 772 deletions

View File

@@ -134,7 +134,7 @@ blocky:
komodo IN CNAME traefik-cl01tl komodo IN CNAME traefik-cl01tl
languagetool IN CNAME traefik-cl01tl languagetool IN CNAME traefik-cl01tl
lidarr IN CNAME traefik-cl01tl lidarr IN CNAME traefik-cl01tl
mail IN CNAME traefik-cl01tl loki IN CNAME traefik-cl01tl
medialyze IN CNAME traefik-cl01tl medialyze IN CNAME traefik-cl01tl
music-grabber IN CNAME traefik-cl01tl music-grabber IN CNAME traefik-cl01tl
navidrome IN CNAME traefik-cl01tl navidrome IN CNAME traefik-cl01tl
@@ -162,7 +162,6 @@ blocky:
sonarr-4k IN CNAME traefik-cl01tl sonarr-4k IN CNAME traefik-cl01tl
sonarr-anime IN CNAME traefik-cl01tl sonarr-anime IN CNAME traefik-cl01tl
sparkyfitness IN CNAME traefik-cl01tl sparkyfitness IN CNAME traefik-cl01tl
stalwart IN CNAME traefik-cl01tl
tdarr IN CNAME traefik-cl01tl tdarr IN CNAME traefik-cl01tl
tubearchivist IN CNAME traefik-cl01tl tubearchivist IN CNAME traefik-cl01tl
vault IN CNAME traefik-cl01tl vault IN CNAME traefik-cl01tl

View File

@@ -1,6 +1,5 @@
eck-operator: eck-operator:
managedNamespaces: managedNamespaces:
- stalwart
- tubearchivist - tubearchivist
installCRDs: true installCRDs: true
replicaCount: 2 replicaCount: 2

View File

@@ -212,12 +212,6 @@ gatus:
- name: authentik - name: authentik
url: https://authentik.alexlebens.net url: https://authentik.alexlebens.net
<<: *defaults <<: *defaults
- name: roundcube
url: https://mail.alexlebens.net
<<: *defaults
- name: stalwart
url: https://stalwart.alexlebens.net
<<: *defaults
- name: ntfy - name: ntfy
url: https://ntfy.alexlebens.net url: https://ntfy.alexlebens.net
<<: *defaults <<: *defaults

View File

@@ -487,24 +487,6 @@ homepage:
href: https://authentik.alexlebens.net href: https://authentik.alexlebens.net
siteMonitor: http://authentik-server.authentik:80 siteMonitor: http://authentik-server.authentik:80
statusStyle: dot statusStyle: dot
- Email Client:
icon: sh-roundcube.webp
description: Roundcube
href: https://mail.alexlebens.net
siteMonitor: http://roundcube.roundcube:80
statusStyle: dot
- Email Server:
icon: sh-stalwart.webp
description: Stalwart
href: https://stalwart.alexlebens.net
siteMonitor: http://stalwart.stalwart:80
statusStyle: dot
namespace: stalwart
app: stalwart
podSelector: >-
app.kubernetes.io/instance in (
stalwart
)
- Notifications: - Notifications:
icon: sh-ntfy.webp icon: sh-ntfy.webp
description: ntfy description: ntfy

View File

@@ -1,12 +0,0 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.12.1
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 1.1.1
digest: sha256:6ea0ffea8d47e3c62657f35ce0dda5d5f67aa13c99107dee396787a6e0c3633c
generated: "2026-04-28T23:36:57.236521514Z"

View File

@@ -1,32 +0,0 @@
apiVersion: v2
name: roundcube
version: 1.0.0
description: Roundcube
keywords:
- roundcube
- email-client
home: https://docs.alexlebens.dev/applications/rclone/
sources:
- https://github.com/roundcube/roundcubemail
- https://hub.docker.com/r/roundcube/roundcubemail
- https://hub.docker.com/_/nginx
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: roundcube
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.12.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: volsync-target
alias: volsync-target-data
version: 1.1.1
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/roundcube.png
# renovate: datasource=github-releases depName=roundcube/roundcubemail
appVersion: 1.6.15

View File

@@ -1,14 +0,0 @@
{{/*
Common labels
*/}}
{{- define "custom.labels" -}}
{{ include "custom.selectorLabels" $ }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "custom.selectorLabels" -}}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
{{- end }}

View File

@@ -1,17 +0,0 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: roundcube-key
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: roundcube-key
{{- include "custom.labels" . | nindent 4 }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: openbao
data:
- secretKey: DES_KEY
remoteRef:
key: /cl01tl/roundcube/key
property: des-key

View File

@@ -1,236 +0,0 @@
roundcube:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
containers:
main:
image:
repository: roundcube/roundcubemail
tag: 1.6.15-fpm-alpine@sha256:0e07c1c66d5a1392f0c47cc79e85e0c60095108f715037d7d0aa3fd8cbe2e780
env:
- name: ROUNDCUBEMAIL_DB_TYPE
value: pgsql
- name: ROUNDCUBEMAIL_DB_HOST
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: host
- name: ROUNDCUBEMAIL_DB_NAME
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: dbname
- name: ROUNDCUBEMAIL_DB_USER
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: user
- name: ROUNDCUBEMAIL_DB_PASSWORD
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: password
- name: ROUNDCUBEMAIL_DES_KEY
valueFrom:
secretKeyRef:
name: roundcube-key
key: DES_KEY
- name: ROUNDCUBEMAIL_DEFAULT_HOST
value: stalwart.stalwart
- name: ROUNDCUBEMAIL_DEFAULT_PORT
value: 143
- name: ROUNDCUBEMAIL_SMTP_SERVER
value: stalwart.stalwart
- name: ROUNDCUBEMAIL_SMTP_PORT
value: 25
- name: ROUNDCUBEMAIL_SKIN
value: elastic
- name: ROUNDCUBEMAIL_PLUGINS
value: archive,zipdownload,newmail_notifier
resources:
requests:
cpu: 1m
memory: 40Mi
nginx:
image:
repository: nginx
tag: 1.30.0-alpine-slim@sha256:830b40ff1beb5e018e56aef2ed1f9fe87a7797e35a555b75fea5c9568e316b04
env:
- name: NGINX_HOST
value: mail.alexlebens.net
- name: NGINX_PHP_CGI
value: roundcube.roundcube:9000
cleandb:
type: cronjob
cronjob:
suspend: false
timeZone: America/Chicago
schedule: 30 4 * * *
backoffLimit: 3
parallelism: 1
containers:
backup:
image:
repository: roundcube/roundcubemail
tag: 1.6.15-fpm-alpine@sha256:0e07c1c66d5a1392f0c47cc79e85e0c60095108f715037d7d0aa3fd8cbe2e780
args:
- bin/cleandb.sh
env:
- name: ROUNDCUBEMAIL_DB_TYPE
value: pgsql
- name: ROUNDCUBEMAIL_DB_HOST
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: host
- name: ROUNDCUBEMAIL_DB_NAME
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: dbname
- name: ROUNDCUBEMAIL_DB_USER
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: user
- name: ROUNDCUBEMAIL_DB_PASSWORD
valueFrom:
secretKeyRef:
name: roundcube-postgresql-18-cluster-app
key: password
- name: ROUNDCUBEMAIL_DES_KEY
valueFrom:
secretKeyRef:
name: roundcube-key
key: DES_KEY
- name: ROUNDCUBEMAIL_DEFAULT_HOST
value: tls://stalwart.stalwart
- name: ROUNDCUBEMAIL_SMTP_SERVER
value: tls://stalwart.stalwart
- name: ROUNDCUBEMAIL_SKIN
value: elastic
- name: ROUNDCUBEMAIL_PLUGINS
value: archive,zipdownload,newmail_notifier
configMaps:
config:
enabled: true
data:
default.conf: |
server {
listen 80 default_server;
server_name _;
root /var/www/html;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php(/|$) {
try_files $uri =404;
fastcgi_pass roundcube:9000;
fastcgi_read_timeout 300;
proxy_read_timeout 300;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
internal;
}
client_max_body_size 6m;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
service:
main:
controller: main
ports:
mail:
port: 9000
targetPort: 9000
web:
port: 80
targetPort: 80
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- mail.alexlebens.net
rules:
- backendRefs:
- name: roundcube
port: 80
matches:
- path:
type: PathPrefix
value: /
persistence:
config:
enabled: true
type: configMap
name: roundcube-config
advancedMounts:
main:
nginx:
- path: /etc/nginx/conf.d/default.conf
readOnly: true
mountPropagation: None
subPath: default.conf
data:
forceRename: roundcube-data
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 5Gi
advancedMounts:
main:
main:
- path: /var/www/html
readOnly: false
nginx:
- path: /var/www/html
readOnly: false
temp:
type: emptyDir
advancedMounts:
main:
main:
- path: /tmp/roundcube-temp
readOnly: false
postgres-18-cluster:
mode: recovery
recovery:
method: objectStore
objectStore:
index: 1
backup:
objectStore:
- name: garage-local
index: 1
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 40 15 * * *"
backupName: garage-local
volsync-target-data:
pvcTarget: roundcube-data
local:
enabled: true
schedule: 12 11 * * *
remote:
enabled: true
schedule: 12 12 * * *
external:
enabled: true
schedule: 12 13 * * *

View File

@@ -1,15 +0,0 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.12.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.7.0
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 1.1.1
digest: sha256:dd614761622fa310ad50f400727fa6a6574071c2ac057294364409fdfe0ff545
generated: "2026-05-02T01:49:21.562586412Z"

View File

@@ -1,37 +0,0 @@
apiVersion: v2
name: stalwart
version: 1.0.0
description: Stalwart
keywords:
- stalwart
- email
home: https://docs.alexlebens.dev/applications/stalwart/
sources:
- https://github.com/stalwartlabs/mail-server
- https://github.com/stalwartlabs/stalwart/pkgs/container/stalwart
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/postgres-cluster
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/valkey
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: stalwart
version: 4.6.2
repository: https://bjw-s-labs.github.io/helm-charts/
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.12.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey
version: 0.7.0
repository: oci://harbor.alexlebens.net/helm-charts
- name: volsync-target
alias: volsync-target-config
version: 1.1.1
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/stalwart.png
# renovate: datasource=github-releases depName=stalwartlabs/mail-server
appVersion: v0.15.5

View File

@@ -1,14 +0,0 @@
{{/*
Common labels
*/}}
{{- define "custom.labels" -}}
{{ include "custom.selectorLabels" $ }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "custom.selectorLabels" -}}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
{{- end }}

View File

@@ -1,29 +0,0 @@
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch-stalwart
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: elasticsearch-stalwart
{{- include "custom.labels" . | nindent 4 }}
spec:
# renovate: datasource=docker depName=elasticsearch
version: 9.3.4
auth:
fileRealm:
- secretName: stalwart-elasticsearch-config
nodeSets:
- name: default
count: 2
config:
node.store.allow_mmap: false
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: ceph-block

View File

@@ -1,25 +0,0 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: stalwart-elasticsearch-config
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: stalwart-elasticsearch-config
{{- include "custom.labels" . | nindent 4 }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: openbao
data:
- secretKey: username
remoteRef:
key: /cl01tl/stalwart/elasticsearch
property: username
- secretKey: password
remoteRef:
key: /cl01tl/stalwart/elasticsearch
property: password
- secretKey: roles
remoteRef:
key: /cl01tl/stalwart/elasticsearch
property: roles

View File

@@ -1,10 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Namespace }}
{{- include "custom.labels" . | nindent 4 }}
pod-security.kubernetes.io/audit: privileged
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/warn: privileged

View File

@@ -1,169 +0,0 @@
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: elasticsearch
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: elasticsearch
{{- include "custom.labels" . | nindent 4 }}
spec:
groups:
- name: ElasticsearchExporter
rules:
- alert: ElasticsearchHeapUsageTooHigh
expr: (elasticsearch_jvm_memory_used_bytes{area="heap"} / elasticsearch_jvm_memory_max_bytes{area="heap"}) * 100 > 90 and elasticsearch_jvm_memory_max_bytes{area="heap"} > 0
for: 2m
labels:
severity: critical
annotations:
summary: Elasticsearch Heap Usage Too High (instance {{ `{{ $labels.instance }}` }})
description: "The heap usage is over 90%\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchHeapUsageWarning
expr: (elasticsearch_jvm_memory_used_bytes{area="heap"} / elasticsearch_jvm_memory_max_bytes{area="heap"}) * 100 > 80 and elasticsearch_jvm_memory_max_bytes{area="heap"} > 0
for: 2m
labels:
severity: warning
annotations:
summary: Elasticsearch Heap Usage warning (instance {{ `{{ $labels.instance }}` }})
description: "The heap usage is over 80%\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchDiskOutOfSpace
expr: elasticsearch_filesystem_data_available_bytes / elasticsearch_filesystem_data_size_bytes * 100 < 10 and elasticsearch_filesystem_data_size_bytes > 0
for: 0m
labels:
severity: critical
annotations:
summary: Elasticsearch disk out of space (instance {{ `{{ $labels.instance }}` }})
description: "The disk usage is over 90%\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchDiskSpaceLow
expr: elasticsearch_filesystem_data_available_bytes / elasticsearch_filesystem_data_size_bytes * 100 < 20 and elasticsearch_filesystem_data_size_bytes > 0
for: 2m
labels:
severity: warning
annotations:
summary: Elasticsearch disk space low (instance {{ `{{ $labels.instance }}` }})
description: "The disk usage is over 80%\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchClusterRed
expr: elasticsearch_cluster_health_status{color="red"} == 1
for: 0m
labels:
severity: critical
annotations:
summary: Elasticsearch Cluster Red (instance {{ `{{ $labels.instance }}` }})
description: "Elastic Cluster Red status\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchClusterYellow
expr: elasticsearch_cluster_health_status{color="yellow"} == 1
for: 0m
labels:
severity: warning
annotations:
summary: Elasticsearch Cluster Yellow (instance {{ `{{ $labels.instance }}` }})
description: "Elastic Cluster Yellow status\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
# 1m delay allows a restart without triggering an alert.
- alert: ElasticsearchHealthyNodes
expr: elasticsearch_cluster_health_number_of_nodes < 3
for: 1m
labels:
severity: critical
annotations:
summary: Elasticsearch Healthy Nodes (instance {{ `{{ $labels.instance }}` }})
description: "Missing node in Elasticsearch cluster\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
# 1m delay allows a restart without triggering an alert.
- alert: ElasticsearchHealthyDataNodes
expr: elasticsearch_cluster_health_number_of_data_nodes < 3
for: 1m
labels:
severity: critical
annotations:
summary: Elasticsearch Healthy Data Nodes (instance {{ `{{ $labels.instance }}` }})
description: "Missing data node in Elasticsearch cluster\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchRelocatingShards
expr: elasticsearch_cluster_health_relocating_shards > 0
for: 0m
labels:
severity: info
annotations:
summary: Elasticsearch relocating shards (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch is relocating shards\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchRelocatingShardsTooLong
expr: elasticsearch_cluster_health_relocating_shards > 0
for: 15m
labels:
severity: warning
annotations:
summary: Elasticsearch relocating shards too long (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch has been relocating shards for 15min\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchInitializingShards
expr: elasticsearch_cluster_health_initializing_shards > 0
for: 0m
labels:
severity: info
annotations:
summary: Elasticsearch initializing shards (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch is initializing shards\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchInitializingShardsTooLong
expr: elasticsearch_cluster_health_initializing_shards > 0
for: 15m
labels:
severity: warning
annotations:
summary: Elasticsearch initializing shards too long (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch has been initializing shards for 15 min\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchUnassignedShards
expr: elasticsearch_cluster_health_unassigned_shards > 0
for: 2m
labels:
severity: critical
annotations:
summary: Elasticsearch unassigned shards (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch has unassigned shards\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchPendingTasks
expr: elasticsearch_cluster_health_number_of_pending_tasks > 0
for: 15m
labels:
severity: warning
annotations:
summary: Elasticsearch pending tasks (instance {{ `{{ $labels.instance }}` }})
description: "Elasticsearch has pending tasks. Cluster works slowly.\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchNoNewDocuments
expr: increase(elasticsearch_indices_indexing_index_total{es_data_node="true"}[10m]) < 1
for: 0m
labels:
severity: warning
annotations:
summary: Elasticsearch no new documents (instance {{ `{{ $labels.instance }}` }})
description: "No new documents for 10 min!\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
# Threshold of 10ms (0.01s) per indexing operation is a rough default. Adjust based on your document size and cluster performance.
- alert: ElasticsearchHighIndexingLatency
expr: rate(elasticsearch_indices_indexing_index_time_seconds_total[5m]) / rate(elasticsearch_indices_indexing_index_total[5m]) > 0.01 and rate(elasticsearch_indices_indexing_index_total[5m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: Elasticsearch High Indexing Latency (instance {{ `{{ $labels.instance }}` }})
description: "The indexing latency on Elasticsearch cluster is higher than the threshold (current value: {{ `{{ $value }}` }}s).\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
# Threshold of 10000 ops/s is a rough default. Adjust based on your cluster capacity and expected workload.
- alert: ElasticsearchHighIndexingRate
expr: sum(rate(elasticsearch_indices_indexing_index_total[1m]))> 10000
for: 5m
labels:
severity: warning
annotations:
summary: Elasticsearch High Indexing Rate (instance {{ `{{ $labels.instance }}` }})
description: "The indexing rate on Elasticsearch cluster is higher than the threshold.\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
# Threshold of 100 queries/s is very low for most production clusters. Adjust based on your expected query volume.
- alert: ElasticsearchHighQueryRate
expr: sum(rate(elasticsearch_indices_search_query_total[1m])) > 100
for: 5m
labels:
severity: warning
annotations:
summary: Elasticsearch High Query Rate (instance {{ `{{ $labels.instance }}` }})
description: "The query rate on Elasticsearch cluster is higher than the threshold.\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"
- alert: ElasticsearchHighQueryLatency
expr: rate(elasticsearch_indices_search_query_time_seconds[1m]) / rate(elasticsearch_indices_search_query_total[1m]) > 1 and rate(elasticsearch_indices_search_query_total[1m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: Elasticsearch High Query Latency (instance {{ `{{ $labels.instance }}` }})
description: "The query latency on Elasticsearch cluster is higher than the threshold (current value: {{ `{{ $value }}` }}s).\n VALUE = {{ `{{ $value }}` }}\n LABELS = {{ `{{ $labels }}` }}"

View File

@@ -1,129 +0,0 @@
stalwart:
controllers:
main:
forceRename: stalwart
type: deployment
replicas: 1
strategy: Recreate
containers:
main:
image:
repository: ghcr.io/stalwartlabs/stalwart
tag: v0.15.5@sha256:dcf575db2d53d9ef86d6ced8abe4ba491984659a0f8862cc6079ee7b41c3c568
resources:
requests:
cpu: 10m
memory: 100Mi
metrics:
type: deployment
replicas: 1
strategy: Recreate
containers:
main:
image:
repository: quay.io/prometheuscommunity/elasticsearch-exporter
tag: v1.10.0@sha256:a6a4d4403f670faf6a94b8c7f9adbca3ead91f26dd64e5ccf95fa69025dc6e58
args:
- '--es.uri=https://elasticsearch-stalwart-es-http.tubearchivist:9200'
- '--es.ssl-skip-verify'
resources:
requests:
cpu: 1m
memory: 10Mi
service:
main:
controller: main
forceRename: stalwart
ports:
http:
port: 80
targetPort: 8080
smtp:
port: 25
targetPort: 25
smtps:
port: 465
targetPort: 465
imap:
port: 143
targetPort: 143
imaps:
port: 993
targetPort: 993
metrics:
controller: metrics
ports:
metrics:
port: 9114
targetPort: 9114
serviceMonitor:
main:
selector:
matchLabels:
app.kubernetes.io/name: stalwart-metrics
app.kubernetes.io/instance: stalwart-metrics
serviceName: '{{ include "bjw-s.common.lib.chart.names.fullname" $ }}'
endpoints:
- port: metrics
interval: 30s
scrapeTimeout: 10s
path: /metrics
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- stalwart.alexlebens.net
rules:
- backendRefs:
- name: stalwart
port: 80
matches:
- path:
type: PathPrefix
value: /
persistence:
config:
forceRename: stalwart-config
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
advancedMounts:
main:
main:
- path: /opt/stalwart
readOnly: false
postgres-18-cluster:
mode: recovery
recovery:
method: objectStore
objectStore:
index: 1
backup:
objectStore:
- name: garage-local
index: 1
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 5 16 * * *"
backupName: garage-local
volsync-target-config:
pvcTarget: stalwart-config
local:
enabled: true
schedule: 28 11 * * *
remote:
enabled: true
schedule: 28 12 * * *
external:
enabled: true
schedule: 28 13 * * *

View File

@@ -111,7 +111,7 @@ customDNS:
komodo IN CNAME traefik-cl01tl komodo IN CNAME traefik-cl01tl
languagetool IN CNAME traefik-cl01tl languagetool IN CNAME traefik-cl01tl
lidarr IN CNAME traefik-cl01tl lidarr IN CNAME traefik-cl01tl
mail IN CNAME traefik-cl01tl loki IN CNAME traefik-cl01tl
medialyze IN CNAME traefik-cl01tl medialyze IN CNAME traefik-cl01tl
music-grabber IN CNAME traefik-cl01tl music-grabber IN CNAME traefik-cl01tl
navidrome IN CNAME traefik-cl01tl navidrome IN CNAME traefik-cl01tl
@@ -140,7 +140,6 @@ customDNS:
sonarr-4k IN CNAME traefik-cl01tl sonarr-4k IN CNAME traefik-cl01tl
sonarr-anime IN CNAME traefik-cl01tl sonarr-anime IN CNAME traefik-cl01tl
sparkyfitness IN CNAME traefik-cl01tl sparkyfitness IN CNAME traefik-cl01tl
stalwart IN CNAME traefik-cl01tl
tdarr IN CNAME traefik-cl01tl tdarr IN CNAME traefik-cl01tl
tubearchivist IN CNAME traefik-cl01tl tubearchivist IN CNAME traefik-cl01tl
vault IN CNAME traefik-cl01tl vault IN CNAME traefik-cl01tl

View File

@@ -132,7 +132,7 @@ customDNS:
komodo IN CNAME traefik-cl01tl komodo IN CNAME traefik-cl01tl
languagetool IN CNAME traefik-cl01tl languagetool IN CNAME traefik-cl01tl
lidarr IN CNAME traefik-cl01tl lidarr IN CNAME traefik-cl01tl
mail IN CNAME traefik-cl01tl loki IN CNAME traefik-cl01tl
medialyze IN CNAME traefik-cl01tl medialyze IN CNAME traefik-cl01tl
music-grabber IN CNAME traefik-cl01tl music-grabber IN CNAME traefik-cl01tl
navidrome IN CNAME traefik-cl01tl navidrome IN CNAME traefik-cl01tl
@@ -161,7 +161,6 @@ customDNS:
sonarr-4k IN CNAME traefik-cl01tl sonarr-4k IN CNAME traefik-cl01tl
sonarr-anime IN CNAME traefik-cl01tl sonarr-anime IN CNAME traefik-cl01tl
sparkyfitness IN CNAME traefik-cl01tl sparkyfitness IN CNAME traefik-cl01tl
stalwart IN CNAME traefik-cl01tl
tdarr IN CNAME traefik-cl01tl tdarr IN CNAME traefik-cl01tl
tubearchivist IN CNAME traefik-cl01tl tubearchivist IN CNAME traefik-cl01tl
vault IN CNAME traefik-cl01tl vault IN CNAME traefik-cl01tl

View File

@@ -90,10 +90,10 @@
{ {
"description": "Specific app grouping overrides", "description": "Specific app grouping overrides",
"matchPackageNames": [ "matchPackageNames": [
"/(^|/|-)(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|roundcube|rybbit|sonarr|sparkyfitness|stalwartlabs|tdarr|traefik)/", "/(^|/|-)(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|rybbit|sonarr|sparkyfitness|tdarr|traefik)/",
"/^rook(-ceph|/rook|/ceph)/" "/^rook(-ceph|/rook|/ceph)/"
], ],
"groupName": "{{#if packageName}}{{{replace '^.*(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|roundcube|rybbit|sonarr|sparkyfitness|stalwartlabs|tdarr|traefik).*$' '$1' packageName}}}{{else}}{{{replace '^.*(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|roundcube|rybbit|sonarr|sparkyfitness|stalwartlabs|tdarr|traefik).*$' '$1' depName}}}{{/if}}", "groupName": "{{#if packageName}}{{{replace '^.*(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|rybbit|sonarr|sparkyfitness|tdarr|traefik).*$' '$1' packageName}}}{{else}}{{{replace '^.*(argo-cd|bazarr|cilium|dawarich|element-web|home-assistant|immich|komodo|plex|postiz|prowlarr|radarr|rook-ceph|rybbit|sonarr|sparkyfitness|tdarr|traefik).*$' '$1' depName}}}{{/if}}",
"groupSlug": "unified-{{{groupName}}}" "groupSlug": "unified-{{{groupName}}}"
}, },
{ {