# Grafana sends its own JSON and Gotify rejects it, so this Deployment is the # translation step between them. Grafana posts to the Service, the bridge posts # to /message with the app token from a SOPS secret. apiVersion: apps/v1 kind: Deployment metadata: name: grafana-gotify-bridge namespace: notifications labels: app: grafana-gotify-bridge spec: replicas: 1 selector: matchLabels: app: grafana-gotify-bridge template: metadata: labels: app: grafana-gotify-bridge spec: securityContext: runAsNonRoot: true runAsUser: 65534 seccompProfile: type: RuntimeDefault containers: - name: bridge image: python:3.12-alpine command: ["python3", "/app/grafana_gotify_bridge.py"] env: - name: GOTIFY_URL value: "http://gotify.notifications.svc.cluster.local" - name: PORT value: "8080" - name: GOTIFY_TOKEN valueFrom: secretKeyRef: {name: grafana-gotify-bridge, key: app-token} ports: - name: http containerPort: 8080 readinessProbe: httpGet: {path: /, port: http} initialDelaySeconds: 3 periodSeconds: 10 livenessProbe: httpGet: {path: /, port: http} initialDelaySeconds: 10 periodSeconds: 20 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumeMounts: - name: script mountPath: /app readOnly: true resources: requests: {cpu: 10m, memory: 32Mi} limits: {cpu: 200m, memory: 96Mi} volumes: - name: script configMap: name: grafana-gotify-bridge --- apiVersion: v1 kind: Service metadata: name: grafana-gotify-bridge namespace: notifications labels: app: grafana-gotify-bridge spec: type: ClusterIP selector: app: grafana-gotify-bridge ports: - name: http port: 8080 targetPort: http