205 lines
6.7 KiB
YAML
205 lines
6.7 KiB
YAML
# Gotify — self-hosted push notification server + SMTP email relay.
|
|||
|
|
# Forgejo webhooks → Gotify → push notifications + email forwarding.
|
||
|
|
# Runs on control plane (no GPU needed), lightweight.
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: gotify
|
||
|
|
namespace: notifications
|
||
|
|
labels:
|
||
|
|
app: gotify
|
||
|
|
spec:
|
||
|
|
replicas: 1
|
||
|
|
strategy:
|
||
|
|
type: Recreate
|
||
|
|
selector:
|
||
|
|
matchLabels:
|
||
|
|
app: gotify
|
||
|
|
template:
|
||
|
|
metadata:
|
||
|
|
labels:
|
||
|
|
app: gotify
|
||
|
|
spec:
|
||
|
|
containers:
|
||
|
|
# --- Gotify server ---
|
||
|
|
- name: gotify
|
||
|
|
image: ghcr.io/gotify/server:2.6.1
|
||
|
|
command: ["/bin/sh", "-c"]
|
||
|
|
args:
|
||
|
|
- |
|
||
|
|
export GOTIFY_DATABASE_DIALECT=postgres
|
||
|
|
export GOTIFY_DATABASE_CONNECTION="host=gotify-db-rw.notifications port=5432 user=${DB_USER} password=${DB_PASS} dbname=gotify sslmode=disable"
|
||
|
|
exec /app/gotify-app
|
||
|
|
ports:
|
||
|
|
- containerPort: 80
|
||
|
|
protocol: TCP
|
||
|
|
env:
|
||
|
|
- name: GOTIFY_DEFAULTUSER_NAME
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-admin
|
||
|
|
key: username
|
||
|
|
- name: GOTIFY_DEFAULTUSER_PASS
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-admin
|
||
|
|
key: password
|
||
|
|
- name: DB_USER
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-db-app
|
||
|
|
key: username
|
||
|
|
- name: DB_PASS
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-db-app
|
||
|
|
key: password
|
||
|
|
- name: GOTIFY_SERVER_PORT
|
||
|
|
value: "80"
|
||
|
|
- name: GOTIFY_SERVER_KEEPALIVEPERIODSECONDS
|
||
|
|
value: "0"
|
||
|
|
- name: TZ
|
||
|
|
value: Asia/Tokyo
|
||
|
|
resources:
|
||
|
|
requests:
|
||
|
|
cpu: 50m
|
||
|
|
memory: 64Mi
|
||
|
|
limits:
|
||
|
|
cpu: 200m
|
||
|
|
memory: 128Mi
|
||
|
|
livenessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /health
|
||
|
|
port: 80
|
||
|
|
periodSeconds: 30
|
||
|
|
initialDelaySeconds: 10
|
||
|
|
readinessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /health
|
||
|
|
port: 80
|
||
|
|
periodSeconds: 10
|
||
|
|
initialDelaySeconds: 5
|
||
|
|
|
||
|
|
# --- SMTP emailer sidecar ---
|
||
|
|
# Watches Gotify WebSocket stream, forwards messages as email.
|
||
|
|
# https://github.com/eternal-flame-AD/gotify-broadcast
|
||
|
|
- name: smtp-emailer
|
||
|
|
image: ghcr.io/gotify/server:2.6.1
|
||
|
|
command:
|
||
|
|
- /bin/sh
|
||
|
|
- -c
|
||
|
|
- |
|
||
|
|
# Wait for Gotify to be ready
|
||
|
|
until wget -qO- http://localhost:80/health >/dev/null 2>&1; do
|
||
|
|
echo "Waiting for Gotify..."
|
||
|
|
sleep 2
|
||
|
|
done
|
||
|
|
echo "Gotify is ready, starting email relay..."
|
||
|
|
|
||
|
|
# Poll Gotify messages and forward via SMTP using msmtp
|
||
|
|
# Install msmtp for lightweight SMTP sending
|
||
|
|
apk add --no-cache msmtp curl jq
|
||
|
|
|
||
|
|
# Configure msmtp
|
||
|
|
cat > /tmp/msmtprc <<MSMTP
|
||
|
|
defaults
|
||
|
|
auth on
|
||
|
|
tls on
|
||
|
|
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||
|
|
logfile /tmp/msmtp.log
|
||
|
|
|
||
|
|
account default
|
||
|
|
host ${SMTP_HOST}
|
||
|
|
port ${SMTP_PORT}
|
||
|
|
from ${SMTP_FROM}
|
||
|
|
user ${SMTP_USER}
|
||
|
|
password ${SMTP_PASS}
|
||
|
|
MSMTP
|
||
|
|
|
||
|
|
chmod 600 /tmp/msmtprc
|
||
|
|
|
||
|
|
# Track last seen message ID
|
||
|
|
LAST_ID=0
|
||
|
|
|
||
|
|
while true; do
|
||
|
|
# Fetch messages since last ID
|
||
|
|
MESSAGES=$(curl -s -H "X-Gotify-Key: ${GOTIFY_CLIENT_TOKEN}" \
|
||
|
|
"http://localhost:80/message?since=${LAST_ID}&limit=10" 2>/dev/null)
|
||
|
|
|
||
|
|
if [ -n "$MESSAGES" ]; then
|
||
|
|
echo "$MESSAGES" | jq -r '.messages[]? | @base64' | while read -r MSG; do
|
||
|
|
DECODED=$(echo "$MSG" | base64 -d)
|
||
|
|
ID=$(echo "$DECODED" | jq -r '.id')
|
||
|
|
TITLE=$(echo "$DECODED" | jq -r '.title // "Notification"')
|
||
|
|
BODY=$(echo "$DECODED" | jq -r '.message // ""')
|
||
|
|
PRIORITY=$(echo "$DECODED" | jq -r '.priority // 5')
|
||
|
|
APP=$(echo "$DECODED" | jq -r '.appid // 0')
|
||
|
|
DATE=$(echo "$DECODED" | jq -r '.date // ""')
|
||
|
|
|
||
|
|
# Only forward messages with priority >= configured threshold
|
||
|
|
if [ "$PRIORITY" -ge "${MIN_PRIORITY:-0}" ]; then
|
||
|
|
printf "Subject: [Gotify] %s\nFrom: %s\nTo: %s\nContent-Type: text/plain; charset=UTF-8\n\n%s\n\n---\nPriority: %s\nDate: %s" \
|
||
|
|
"$TITLE" "$SMTP_FROM" "$NOTIFY_EMAIL" "$BODY" "$PRIORITY" "$DATE" | \
|
||
|
|
msmtp -C /tmp/msmtprc "$NOTIFY_EMAIL" && \
|
||
|
|
echo "Email sent for message $ID: $TITLE" || \
|
||
|
|
echo "Failed to send email for message $ID"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Update last seen ID
|
||
|
|
if [ "$ID" -gt "$LAST_ID" ]; then
|
||
|
|
LAST_ID=$ID
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
sleep ${POLL_INTERVAL:-30}
|
||
|
|
done
|
||
|
|
env:
|
||
|
|
- name: GOTIFY_CLIENT_TOKEN
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-tokens
|
||
|
|
key: client-token
|
||
|
|
- name: SMTP_HOST
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: host
|
||
|
|
- name: SMTP_PORT
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: port
|
||
|
|
- name: SMTP_FROM
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: from
|
||
|
|
- name: SMTP_USER
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: user
|
||
|
|
- name: SMTP_PASS
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: password
|
||
|
|
- name: NOTIFY_EMAIL
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: gotify-smtp
|
||
|
|
key: notify-email
|
||
|
|
- name: MIN_PRIORITY
|
||
|
|
value: "5"
|
||
|
|
- name: POLL_INTERVAL
|
||
|
|
value: "15"
|
||
|
|
resources:
|
||
|
|
requests:
|
||
|
|
cpu: 10m
|
||
|
|
memory: 32Mi
|
||
|
|
limits:
|
||
|
|
cpu: 100m
|
||
|
|
memory: 64Mi
|
||
|
|
# No volumes — Postgres handles persistence
|