Consume published Immich Sync and Coturn charts

This commit is contained in:
2026-10-18 18:28:55 +02:00
parent 5f0c3470b7
commit cf4f0b067c
13 changed files with 73 additions and 422 deletions
-4
View File
@@ -1,4 +0,0 @@
apiVersion: v2
name: coturn-homelab
type: application
version: 0.1.0
-4
View File
@@ -1,4 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Release.Namespace }}
-54
View File
@@ -1,54 +0,0 @@
{{- range $protocol := list "tcp" "udp" }}
apiVersion: v1
kind: Service
metadata:
name: coturn-{{ $protocol }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
annotations:
metallb.io/loadBalancerIPs: {{ $.Values.loadBalancerIP | quote }}
metallb.io/allow-shared-ip: coturn
mikrotik.brunner.ninja/router: newgw
mikrotik.brunner.ninja/forwardings: {{ if eq $protocol "tcp" }}'[{"name":"3478-tcp","servicePort":"tcp","dstAddressList":"WANs"},{"name":"5349-tcp","servicePort":"tcp-tls","dstAddressList":"WANs"}]'{{ else }}'[{"name":"3478-udp","servicePort":"udp","dstAddressList":"WANs"},{"name":"5349-udp","servicePort":"udp-tls","dstAddressList":"WANs"}]'{{ end }}
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
ports:
- name: {{ $protocol }}
port: 3478
targetPort: {{ $protocol }}
protocol: {{ upper $protocol }}
- name: {{ $protocol }}-tls
port: 5349
targetPort: {{ $protocol }}-tls
protocol: {{ upper $protocol }}
---
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: coturn-relay
namespace: {{ .Release.Namespace }}
annotations:
metallb.io/loadBalancerIPs: {{ .Values.loadBalancerIP | quote }}
metallb.io/allow-shared-ip: coturn
mikrotik.brunner.ninja/router: newgw
mikrotik.brunner.ninja/forwardings: '[{"name":"relay-udp","servicePortRange":"{{ .Values.relay.minPort }}-{{ .Values.relay.maxPort }}","dstAddressList":"WANs"}]'
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/instance: coturn
app.kubernetes.io/name: coturn
ports:
{{- range $port := untilStep (int .Values.relay.minPort) (int (add1 .Values.relay.maxPort)) 1 }}
- name: relay-{{ $port }}
port: {{ $port }}
targetPort: {{ $port }}
protocol: UDP
{{- end }}
-137
View File
@@ -1,137 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
automountServiceAccountToken: false
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
app.kubernetes.io/version: {{ .Values.image.tag | quote }}
spec:
replicas: 1
revisionHistoryLimit: 3
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
template:
metadata:
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
spec:
serviceAccountName: coturn
automountServiceAccountToken: false
containers:
- name: coturn
image: {{ printf "%s:%s" .Values.image.repository .Values.image.tag }}
imagePullPolicy: IfNotPresent
args:
- --listening-port=3478
- --tls-listening-port=5349
- --fingerprint
- --cert=/etc/ssl/certs/cert.pem
- --pkey=/etc/ssl/private/privkey.pem
- --realm={{ .Values.realm }}
- --log-file=stdout
- --no-software-attribute
- --no-cli
- --use-auth-secret
- --static-auth-secret=$(TURN_SHARED_SECRET)
- --external-ip={{ .Values.externalIP }}
- --min-port={{ .Values.relay.minPort }}
- --max-port={{ .Values.relay.maxPort }}
- --no-multicast-peers
env:
- name: TURN_SHARED_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.sharedSecret.name }}
key: {{ .Values.sharedSecret.key }}
ports:
- name: tcp
containerPort: 3478
protocol: TCP
- name: udp
containerPort: 3478
protocol: UDP
- name: tcp-tls
containerPort: 5349
protocol: TCP
- name: udp-tls
containerPort: 5349
protocol: UDP
readinessProbe:
tcpSocket:
port: tcp
livenessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 30
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
add: [NET_BIND_SERVICE]
drop: [ALL]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
volumeMounts:
- name: certs
mountPath: /etc/ssl/certs
readOnly: true
- name: private
mountPath: /etc/ssl/private
readOnly: true
volumes:
- name: certs
secret:
secretName: {{ .Values.certificate.secretName }}
items:
- key: tls.crt
path: cert.pem
- name: private
secret:
secretName: {{ .Values.certificate.secretName }}
items:
- key: tls.key
path: privkey.pem
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: coturn
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: coturn
app.kubernetes.io/instance: coturn
spec:
secretName: {{ .Values.certificate.secretName }}
dnsNames:
- {{ .Values.certificate.dnsName }}
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
name: {{ .Values.certificate.issuerName }}
usages:
- digital signature
- key encipherment
+13 -1
View File
@@ -3,7 +3,18 @@ image:
tag: 4.10.0-r1
realm: brunner.ninja
externalIP: 37.186.4.16
loadBalancerIP: 192.168.0.19
service:
loadBalancerIP: 192.168.0.19
commonAnnotations:
metallb.io/loadBalancerIPs: 192.168.0.19
metallb.io/allow-shared-ip: coturn
mikrotik.brunner.ninja/router: newgw
tcpAnnotations:
mikrotik.brunner.ninja/forwardings: '[{"name":"3478-tcp","servicePort":"tcp","dstAddressList":"WANs"},{"name":"5349-tcp","servicePort":"tcp-tls","dstAddressList":"WANs"}]'
udpAnnotations:
mikrotik.brunner.ninja/forwardings: '[{"name":"3478-udp","servicePort":"udp","dstAddressList":"WANs"},{"name":"5349-udp","servicePort":"udp-tls","dstAddressList":"WANs"}]'
relayAnnotations:
mikrotik.brunner.ninja/forwardings: '[{"name":"relay-udp","servicePortRange":"49160-49200","dstAddressList":"WANs"}]'
relay:
minPort: 49160
maxPort: 49200
@@ -11,6 +22,7 @@ sharedSecret:
name: turn-shared-secret
key: shared-secret
certificate:
enabled: true
secretName: coturn
dnsName: brunner.ninja
issuerName: letsencrypt-dns
-14
View File
@@ -1,14 +0,0 @@
#!/bin/sh
set -eu
expected_context=kubernetes-admin@kubernetes
current_context=$(kubectl config current-context)
if [ "${current_context}" != "${expected_context}" ]; then
echo "Refusing to deploy through unexpected context: ${current_context}" >&2
exit 1
fi
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
kubectl apply --server-side --dry-run=server -k "${script_dir}"
kubectl apply --server-side -k "${script_dir}"
kubectl --namespace default rollout status deployment/immich-sync --timeout=5m
-7
View File
@@ -1,7 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- resources.yaml
images:
- name: registry.brunner.ninja/feedc0de/immich-sync
newTag: dea9ed7ab0eb5075cbeb33884bbe3374403e99e0
-162
View File
@@ -1,162 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: immich-sync-stats
spec:
accessModes:
- ReadWriteMany
storageClassName: rook-cephfs
resources:
requests:
storage: 64Mi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: immich-sync
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: immich-sync
template:
metadata:
labels:
app: immich-sync
spec:
automountServiceAccountToken: false
securityContext:
fsGroup: 65532
fsGroupChangePolicy: OnRootMismatch
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: immich-sync
topologyKey: kubernetes.io/hostname
containers:
- name: immich-sync
image: registry.brunner.ninja/feedc0de/immich-sync
imagePullPolicy: Always
env:
- name: PORT
value: "8090"
- name: STATS_FILE
value: /data/stats.json
ports:
- name: http
containerPort: 8090
readinessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 1
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 5
periodSeconds: 15
resources:
requests:
cpu: 10m
memory: 32Mi
ephemeral-storage: 64Mi
limits:
cpu: "1"
memory: 128Mi
ephemeral-storage: 20Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
volumeMounts:
- name: tmp
mountPath: /tmp
- name: stats
mountPath: /data
volumes:
- name: tmp
emptyDir:
sizeLimit: 20Gi
- name: stats
persistentVolumeClaim:
claimName: immich-sync-stats
---
apiVersion: v1
kind: Service
metadata:
name: immich-sync
labels:
app: immich-sync
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: immich-sync
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: immich-sync
spec:
minAvailable: 1
selector:
matchLabels:
app: immich-sync
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: immich-sync
labels:
release: prometheus
spec:
selector:
matchLabels:
app: immich-sync
namespaceSelector:
matchNames:
- default
endpoints:
- port: http
path: /metrics
interval: 30s
scrapeTimeout: 10s
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: immich-sync
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
rules:
- host: immich-sync.brunner.ninja
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: immich-sync
port:
name: http
+36
View File
@@ -0,0 +1,36 @@
fullnameOverride: immich-sync
replicaCount: 2
image:
pullPolicy: Always
persistence:
enabled: true
existingClaim: immich-sync-stats
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
host: immich-sync.brunner.ninja
metrics:
serviceMonitor:
enabled: true
labels:
release: prometheus
podDisruptionBudget:
enabled: true
minAvailable: 1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: immich-sync
topologyKey: kubernetes.io/hostname
+1
View File
@@ -7,6 +7,7 @@ spec:
description: Coturn relay and certificate resources
sourceRepos:
- https://code.brunner.ninja/feedc0de/homelab-gitops.git
- https://brunner.ninja/charts
destinations:
- namespace: coturn
server: https://kubernetes.default.svc
+11 -4
View File
@@ -5,12 +5,17 @@ metadata:
namespace: argocd
spec:
project: coturn
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/coturn
sources:
- repoURL: https://brunner.ninja/charts
chart: coturn
targetRevision: 1.0.0-3-gb1ad321
helm:
releaseName: coturn
valueFiles:
- $values/apps/coturn/values.yaml
- repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: coturn
@@ -19,3 +24,5 @@ spec:
enabled: true
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
+12 -3
View File
@@ -5,10 +5,17 @@ metadata:
namespace: argocd
spec:
project: homelab
source:
repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
sources:
- repoURL: https://brunner.ninja/charts
chart: immich-sync
targetRevision: 1.0.0-4-g1868be2
helm:
releaseName: immich-sync
valueFiles:
- $values/apps/immich-sync/values.yaml
- repoURL: https://code.brunner.ninja/feedc0de/homelab-gitops.git
targetRevision: main
path: apps/immich-sync
ref: values
destination:
server: https://kubernetes.default.svc
namespace: default
@@ -17,3 +24,5 @@ spec:
enabled: true
prune: true
selfHeal: true
syncOptions:
- ServerSideApply=true
-32
View File
@@ -1,32 +0,0 @@
#!/bin/sh
set -eu
if [ "$#" -ne 1 ] || ! printf '%s\n' "$1" | grep -Eq '^[0-9a-f]{40}$'; then
echo "usage: $0 <full-lowercase-git-sha>" >&2
exit 2
fi
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
repository_dir=$(dirname -- "${script_dir}")
kustomization="${repository_dir}/apps/immich-sync/kustomization.yaml"
temporary="${kustomization}.tmp"
awk -v tag="$1" '
/^ newTag: / {
if (updated) {
print "multiple newTag fields found" > "/dev/stderr"
exit 1
}
print " newTag: " tag
updated = 1
next
}
{ print }
END {
if (!updated) {
print "newTag field not found" > "/dev/stderr"
exit 1
}
}
' "${kustomization}" > "${temporary}"
mv "${temporary}" "${kustomization}"