jitsi setup
This commit is contained in:
parent
8207ef10d1
commit
001e9c36fe
19
infrastructure/flux-system/kustomization-jitsi.yaml
Normal file
19
infrastructure/flux-system/kustomization-jitsi.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
# infrastructure/flux-system/kustomization-jitsi.yaml
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: jitsi
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
path: ./services/jitsi
|
||||
targetNamespace: jitsi
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
dependsOn:
|
||||
- name: core
|
||||
wait: true
|
||||
timeout: 5m
|
||||
@ -1,3 +1,4 @@
|
||||
# infrastructure/flux-system/kustomization-longhorn-ui.yaml
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
|
||||
@ -9,6 +9,7 @@ resources:
|
||||
- kustomization-helm.yaml
|
||||
- kustomization-gitea.yaml
|
||||
- kustomization-vault.yaml
|
||||
- kustomization-jitsi.yaml
|
||||
- kustomization-crypto.yaml
|
||||
- kustomization-monerod.yaml
|
||||
- kustomization-jellyfin.yaml
|
||||
|
||||
169
services/jitsi/deployment.yaml
Normal file
169
services/jitsi/deployment.yaml
Normal file
@ -0,0 +1,169 @@
|
||||
# services/jitsi/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jitsi-prosody
|
||||
namespace: jitsi
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels: { app: jitsi-prosody }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: jitsi-prosody }
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: titan-22 # keep everything on titan-22 for simplicity
|
||||
kubernetes.io/arch: amd64
|
||||
containers:
|
||||
- name: prosody
|
||||
image: jitsi/prosody:stable
|
||||
ports:
|
||||
- { name: c2s, containerPort: 5222, protocol: TCP }
|
||||
- { name: http, containerPort: 5280, protocol: TCP }
|
||||
- { name: comp, containerPort: 5347, protocol: TCP }
|
||||
env:
|
||||
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||
- { name: ENABLE_AUTH, value: "0" } # open instance, no auth (fastest path)
|
||||
- { name: ENABLE_GUESTS, value: "1" }
|
||||
- { name: JICOFO_AUTH_USER, value: "focus" }
|
||||
- { name: JVB_AUTH_USER, value: "jvb" }
|
||||
- name: JICOFO_AUTH_PASSWORD
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_AUTH_PASSWORD } }
|
||||
- name: JICOFO_COMPONENT_SECRET
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_COMPONENT_SECRET } }
|
||||
- name: JVB_AUTH_PASSWORD
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JVB_AUTH_PASSWORD } }
|
||||
volumeMounts:
|
||||
- { name: cfg, mountPath: /config }
|
||||
volumes:
|
||||
- name: cfg
|
||||
persistentVolumeClaim: { claimName: jitsi-prosody-config }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jitsi-jicofo
|
||||
namespace: jitsi
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels: { app: jitsi-jicofo }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: jitsi-jicofo }
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: titan-22
|
||||
kubernetes.io/arch: amd64
|
||||
containers:
|
||||
- name: jicofo
|
||||
image: jitsi/jicofo:stable
|
||||
env:
|
||||
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||
- { name: XMPP_SERVER, value: "jitsi-prosody.jitsi.svc.cluster.local" }
|
||||
- { name: JICOFO_AUTH_USER, value: "focus" }
|
||||
- name: JICOFO_AUTH_PASSWORD
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_AUTH_PASSWORD } }
|
||||
- name: JICOFO_COMPONENT_SECRET
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_COMPONENT_SECRET } }
|
||||
- { name: JVB_BREWERY_MUC, value: "jvbbrewery" }
|
||||
volumeMounts:
|
||||
- { name: cfg, mountPath: /config }
|
||||
volumes:
|
||||
- name: cfg
|
||||
persistentVolumeClaim: { claimName: jitsi-jicofo-config }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jitsi-jvb
|
||||
namespace: jitsi
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels: { app: jitsi-jvb }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: jitsi-jvb }
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: titan-22
|
||||
kubernetes.io/arch: amd64
|
||||
containers:
|
||||
- name: jvb
|
||||
image: jitsi/jvb:stable
|
||||
ports:
|
||||
- { name: colibri-ws, containerPort: 9090, protocol: TCP } # WebSocket control channel
|
||||
- { name: rtp-udp, containerPort: 10000, hostPort: 10000, protocol: UDP } # media
|
||||
env:
|
||||
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||
- { name: XMPP_SERVER, value: "jitsi-prosody.jitsi.svc.cluster.local" }
|
||||
- { name: JVB_AUTH_USER, value: "jvb" }
|
||||
- name: JVB_AUTH_PASSWORD
|
||||
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JVB_AUTH_PASSWORD } }
|
||||
- { name: JVB_BREWERY_MUC, value: "jvbbrewery" }
|
||||
- { name: JVB_PORT, value: "10000" } # matches hostPort above
|
||||
- { name: ENABLE_COLIBRI_WEBSOCKET, value: "1" } # enables /colibri-ws
|
||||
- { name: JVB_STUN_SERVERS, value: "stun.l.google.com:19302,stun1.l.google.com:19302,meet-jit-si-turnrelay.jitsi.net:443" }
|
||||
# For pure speed you can advertise your public IP here if STUN is flaky:
|
||||
# - name: JVB_ADVERTISE_IPS
|
||||
# value: "YOUR.PUBLIC.IP.ADDR"
|
||||
volumeMounts:
|
||||
- { name: cfg, mountPath: /config }
|
||||
volumes:
|
||||
- name: cfg
|
||||
persistentVolumeClaim: { claimName: jitsi-jvb-config }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jitsi-web
|
||||
namespace: jitsi
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels: { app: jitsi-web }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: jitsi-web }
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: titan-22
|
||||
kubernetes.io/arch: amd64
|
||||
containers:
|
||||
- name: web
|
||||
image: jitsi/web:stable
|
||||
ports:
|
||||
- { name: http, containerPort: 80, protocol: TCP }
|
||||
env:
|
||||
- { name: PUBLIC_URL, value: "https://meet.bstein.dev" }
|
||||
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||
- { name: XMPP_BOSH_URL_BASE, value: "http://jitsi-prosody.jitsi.svc.cluster.local:5280" }
|
||||
- { name: ENABLE_XMPP_WEBSOCKET, value: "1" }
|
||||
- { name: ENABLE_COLIBRI_WEBSOCKET, value: "1" }
|
||||
# Optional: lower default quality a bit for tough links
|
||||
# - { name: RESOLUTION, value: "360" }
|
||||
volumeMounts:
|
||||
- { name: cfg, mountPath: /config }
|
||||
volumes:
|
||||
- name: cfg
|
||||
persistentVolumeClaim: { claimName: jitsi-web-config }
|
||||
41
services/jitsi/ingress.yaml
Normal file
41
services/jitsi/ingress.yaml
Normal file
@ -0,0 +1,41 @@
|
||||
# services/jitsi/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: jitsi
|
||||
namespace: jitsi
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
tls:
|
||||
- hosts: [ "meet.bstein.dev" ]
|
||||
secretName: jitsi-meet-tls
|
||||
rules:
|
||||
- host: meet.bstein.dev
|
||||
http:
|
||||
paths:
|
||||
- path: /colibri-ws
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: jitsi-jvb
|
||||
port: { number: 9090 }
|
||||
- path: /xmpp-websocket
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: jitsi-prosody
|
||||
port: { number: 5280 }
|
||||
- path: /http-bind
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: jitsi-prosody
|
||||
port: { number: 5280 }
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: jitsi-web
|
||||
port: { number: 80 }
|
||||
10
services/jitsi/kustomization.yaml
Normal file
10
services/jitsi/kustomization.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
# services/jitsi/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- pvc.yaml
|
||||
- ingress.yaml
|
||||
- secret.yaml
|
||||
5
services/jitsi/namespace.yaml
Normal file
5
services/jitsi/namespace.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
# services/jitsi/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: jitsi
|
||||
42
services/jitsi/pvc.yaml
Normal file
42
services/jitsi/pvc.yaml
Normal file
@ -0,0 +1,42 @@
|
||||
# services/jitsi/pvc.yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: jitsi-web-config
|
||||
namespace: jitsi
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: { requests: { storage: 10Gi } }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: jitsi-prosody-config
|
||||
namespace: jitsi
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: { requests: { storage: 10Gi } }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: jitsi-jicofo-config
|
||||
namespace: jitsi
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: { requests: { storage: 10Gi } }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: jitsi-jvb-config
|
||||
namespace: jitsi
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: { requests: { storage: 10Gi } }
|
||||
11
services/jitsi/secret.yaml
Normal file
11
services/jitsi/secret.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
# services/jitsi/secret.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: jitsi-internal-secrets
|
||||
namespace: jitsi
|
||||
type: Opaque
|
||||
data:
|
||||
JICOFO_COMPONENT_SECRET: bEg5Y09hZFJBem5PUFliQlp4RHkwRTRP
|
||||
JICOFO_AUTH_PASSWORD: VVkyUmczaVRDWUZ0MzdQdmN3UDN1SFc5
|
||||
JVB_AUTH_PASSWORD: d0M5aWJ4dWlPTnhFak9lRHJqSHdYa0g5
|
||||
36
services/jitsi/service.yaml
Normal file
36
services/jitsi/service.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
# services/jitsi/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jitsi-prosody
|
||||
namespace: jitsi
|
||||
spec:
|
||||
selector: { app: jitsi-prosody }
|
||||
ports:
|
||||
- { name: c2s, port: 5222, targetPort: 5222, protocol: TCP }
|
||||
- { name: http, port: 5280, targetPort: 5280, protocol: TCP }
|
||||
- { name: comp, port: 5347, targetPort: 5347, protocol: TCP }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jitsi-jvb
|
||||
namespace: jitsi
|
||||
spec:
|
||||
selector: { app: jitsi-jvb }
|
||||
ports:
|
||||
- { name: colibri-ws, port: 9090, targetPort: 9090, protocol: TCP }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: jitsi-web
|
||||
namespace: jitsi
|
||||
spec:
|
||||
selector: { app: jitsi-web }
|
||||
ports:
|
||||
- { name: http, port: 80, targetPort: 80, protocol: TCP }
|
||||
25
services/pegasus/configmap.yaml
Normal file
25
services/pegasus/configmap.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
# services/pegasus/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: pegasus-config
|
||||
namespace: jellyfin
|
||||
data:
|
||||
PEGASUS_MEDIA_ROOT: "/media"
|
||||
PEGASUS_BIND: ":8080"
|
||||
# Optional: PEGASUS_COOKIE_DOMAIN
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: pegasus-user-map
|
||||
namespace: jellyfin
|
||||
data:
|
||||
user-map.yaml: |
|
||||
map:
|
||||
mary_grace_allison: "Allison"
|
||||
maddie_rejcek: "Rejcek"
|
||||
carol_mcguinness: "McGuinness_90s"
|
||||
ed_stein: "Stein_90s"
|
||||
63
services/pegasus/deployment.yaml
Normal file
63
services/pegasus/deployment.yaml
Normal file
@ -0,0 +1,63 @@
|
||||
# services/pegasus/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pegasus
|
||||
namespace: jellyfin
|
||||
spec:
|
||||
replicas: 1
|
||||
selector: { matchLabels: { app: pegasus } }
|
||||
template:
|
||||
metadata: { labels: { app: pegasus } }
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
containers:
|
||||
- name: pegasus
|
||||
image: registry.bstein.dev/pegasus:1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: PEGASUS_MEDIA_ROOT
|
||||
valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_MEDIA_ROOT } }
|
||||
- name: PEGASUS_BIND
|
||||
valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_BIND } }
|
||||
- name: PEGASUS_USER_MAP_FILE
|
||||
value: "/config/user-map.yaml"
|
||||
- name: PEGASUS_SESSION_KEY
|
||||
valueFrom: { secretKeyRef: { name: pegasus-secrets, key: PEGASUS_SESSION_KEY } }
|
||||
- name: JELLYFIN_URL
|
||||
valueFrom: { secretKeyRef: { name: pegasus-secrets, key: JELLYFIN_URL } }
|
||||
- name: PEGASUS_DEBUG
|
||||
value: 1
|
||||
- name: PEGASUS_DRY_RUN
|
||||
value: 1
|
||||
ports: [{ name: http, containerPort: 8080 }]
|
||||
volumeMounts:
|
||||
- name: media
|
||||
mountPath: /media
|
||||
- name: config
|
||||
mountPath: /config
|
||||
readOnly: true
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
readinessProbe: { httpGet: { path: "/", port: http } }
|
||||
livenessProbe: { httpGet: { path: "/metrics", port: http } }
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities: { drop: ["ALL"] }
|
||||
resources:
|
||||
requests: { cpu: 100m, memory: 256Mi }
|
||||
limits: { cpu: 1000m, memory: 1Gi }
|
||||
volumes:
|
||||
- name: media
|
||||
persistentVolumeClaim:
|
||||
claimName: jellyfin-media-asteria
|
||||
- name: config
|
||||
configMap: { name: pegasus-user-map }
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
24
services/pegasus/ingress.yaml
Normal file
24
services/pegasus/ingress.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
# services/pegasus/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: pegasus
|
||||
namespace: jellyfin
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: traefik
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
spec:
|
||||
tls:
|
||||
- hosts: [ "pegasus.bstein.dev" ]
|
||||
rules:
|
||||
- host: pegasus.bstein.dev
|
||||
http:
|
||||
paths:
|
||||
- pathType: Prefix
|
||||
path: /
|
||||
backend:
|
||||
service:
|
||||
name: pegasus
|
||||
port: { number: 80 }
|
||||
27
services/pegasus/kustomization.yaml
Normal file
27
services/pegasus/kustomization.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
# services/pegasus/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- configmap.yaml
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
- ingress.yaml
|
||||
patches:
|
||||
- target: { kind: Deployment, name: pegasus, namespace: jellyfin }
|
||||
patch: |
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/env/-
|
||||
value: { name: PEGASUS_DEBUG, value: "1" }
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/env/-
|
||||
value: { name: PEGASUS_DRY_RUN, value: "1" }
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/-
|
||||
value:
|
||||
name: shell
|
||||
image: alpine:3.20
|
||||
command: ["sh","-c","sleep infinity"]
|
||||
securityContext: { runAsUser: 10001, runAsGroup: 10001, allowPrivilegeEscalation: false }
|
||||
volumeMounts:
|
||||
- { name: media, mountPath: /media }
|
||||
- { name: config, mountPath: /config, readOnly: true }
|
||||
12
services/pegasus/service.yaml
Normal file
12
services/pegasus/service.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
# services/pegasus/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: pegasus
|
||||
namespace: jellyfin
|
||||
spec:
|
||||
selector: { app: pegasus }
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: http
|
||||
Loading…
x
Reference in New Issue
Block a user