feat: add alert bridge service and related configurations
Some checks failed
validate / lint (push) Failing after 1s

This commit is contained in:
Nik Afiq 2026-08-01 22:51:59 +09:00
parent d95806cd32
commit 85cc8494fa
8 changed files with 170 additions and 2 deletions

View File

@ -38,5 +38,11 @@ SWITCHBOT_SECRET=your_switchbot_secret_here
# Dashy weather widget API key (rotated off the plaintext value formerly in config/dashy/conf.yaml) # Dashy weather widget API key (rotated off the plaintext value formerly in config/dashy/conf.yaml)
DASHY_WEATHER_API_KEY=your_api_key_here DASHY_WEATHER_API_KEY=your_api_key_here
# alert-bridge (Discord alert webhook relay) - prefixed since "API_KEY" alone
# is too generic a name for this shared flat .env namespace
ALERT_BRIDGE_API_KEY=your_api_key_here
ALERT_BRIDGE_DISCORD_WEBHOOK_URL=your_discord_webhook_url_here
ALERT_BRIDGE_MENTION_USER_ID=your_discord_user_id_here
PIA_USER=your_pia_username_here PIA_USER=your_pia_username_here
PIA_PASSWORD=your_pia_password_here PIA_PASSWORD=your_pia_password_here

View File

@ -39,7 +39,7 @@ Public services under `nik4nao.com` use Let's Encrypt.
| Observability | kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector, Glances | | Observability | kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector, Glances |
| Git and CI | Gitea, Gitea Actions runner, registry pull secrets, Gitea backup CronJob | | Git and CI | Gitea, Gitea Actions runner, registry pull secrets, Gitea backup CronJob |
| Media | Jellyfin, qBittorrent, JDownloader | | Media | Jellyfin, qBittorrent, JDownloader |
| Home services | Home Assistant ingress, HA gateway, AI gateway, Discord bot | | Home services | Home Assistant ingress, HA gateway, AI gateway, Discord bot, Alexa bridge, Alert bridge |
| Public apps | Portfolio, Watch Party ingress to the Mac Mini | | Public apps | Portfolio, Watch Party ingress to the Mac Mini |
| Dashboard | Dashy | | Dashboard | Dashy |
@ -61,6 +61,7 @@ Public services under `nik4nao.com` use Let's Encrypt.
| `https://ha.home.arpa` | Home Assistant | Internal CA | | `https://ha.home.arpa` | Home Assistant | Internal CA |
| `https://glances.home.arpa` | Glances on K3s | Internal CA | | `https://glances.home.arpa` | Glances on K3s | Internal CA |
| `https://glances-debian.home.arpa` | Glances on Debian | Internal CA | | `https://glances-debian.home.arpa` | Glances on Debian | Internal CA |
| `https://alert-bridge.home.arpa` | Alert bridge (Discord webhook relay) | Internal CA |
| `https://watch-party.nik4nao.com` | Watch Party on Mac Mini | Let's Encrypt | | `https://watch-party.nik4nao.com` | Watch Party on Mac Mini | Let's Encrypt |
| `https://nik4nao.com` | Portfolio | Let's Encrypt | | `https://nik4nao.com` | Portfolio | Let's Encrypt |
| `http://ca.home.arpa` | Internal CA installer | Plain HTTP | | `http://ca.home.arpa` | Internal CA installer | Plain HTTP |

View File

@ -0,0 +1,39 @@
# Apply: kubectl apply -f manifests/home-services/alert-bridge-ingress.yaml
# Delete: kubectl delete -f manifests/home-services/alert-bridge-ingress.yaml
# Description: Internal-CA TLS certificate and Traefik IngressRoute for
# alert-bridge at alert-bridge.home.arpa, so a caller elsewhere on the home
# network (not inside the k8s cluster, e.g. a cronjob on another LAN host) can
# reach POST /alerts. Modeled on manifests/authentik/authentik-ingress.yaml's
# shape (internal-ca-issuer + websecure entrypoint) rather than
# alexa-bridge-public-ingress.yaml's letsencrypt-prod pattern, since this is
# not exposed to the public internet - LAN-only, same trust tier as Argo CD,
# Traefik's own dashboard, etc.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: alert-bridge-tls
namespace: home-services
spec:
secretName: alert-bridge-tls
issuerRef:
name: internal-ca-issuer
kind: ClusterIssuer
dnsNames:
- alert-bridge.home.arpa
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: alert-bridge
namespace: home-services
spec:
entryPoints:
- websecure
routes:
- match: Host(`alert-bridge.home.arpa`)
kind: Rule
services:
- name: alert-bridge
port: 8080
tls:
secretName: alert-bridge-tls

View File

@ -0,0 +1,15 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: alert-bridge-secret
namespace: home-services
spec:
encryptedData:
API_KEY: AgBrR36fXjr9dIns0ygP/oa+/AowMElESRGiB88Y//v4aq+9Xhv4MzZJOLaLr9E3mPioNtvnh6fbgtswqPX+gldGUbU6FJEt5dSGwlRZpDR7B3QX+Dn7HBFLoiwGISqwFFxr1xD+vn0mrmV1KggriT26ofz4JW2IDMXrPArkyaeJ0F0XfbA4Ddv1BQ3iZ6ujoFaYRIOHYg8V1aRTr/cQZCyRXH3IGxIkkkyJNQ4SUWX1XoQ8aCjSxoawQKgVQUYbh9yaoy17+Qhs9dKlA4SS/8Ez5fBv2WfXb8jzX4qcm8J/jZoZjhtjJFpZeuAg7Gwj3f6pmVrtkUcWmYQRHO7ftHLpjgED/9CmVAOrqWpHmnRWQheSf2aeXPWyHUqSH17m6Z7uZd51Apkkge1+ZdGIEpgJPgzsjAC/ACLgOoAqV+LlD1ZezyesK19VvvtYsXbjKhCcN1eAqSGm/oTo6LVWkgthedfUnRzT3srZLtwcbL6/YONGcL+Ah+RlDXXfa0SGMyRSr8Wi8bpNMIwx3NN5b6WSoDWAZ6Hlny+UvqfAcCAR/pZyzbD3PC3pE90ewpvt4gOzy/LjRxcLt1D3E5uE82WvdyLGzLoP2MSVY6W3VeYV2PzZOF2nuHu19eNVmipe8j4kuBetdFuNEMXUe2nKgGKed+w8t+59Kq2fkEJEpPppWzDPMbmTSiZF4rygBjEfQlslzv/mm3qTTbsFx1vw2ziQpaxs75WM0tZwlsWlromx8txpOx+klWlQzUu10h2qXcHf2boAgjBGknUmoCXmlEo/
DISCORD_WEBHOOK_URL: AgAV8De/Nv2tF8Qp+lshiPYF6C0HNPRhotriB/aUwCTMhZ481L6fFet91yLMPtQQNupAETAqsy/3Xl5AYyJeR8zGF1qeG1AbjFVtURQpha1kkaGdl6c01sZAxX2ASCIO8RmqUPbRrxs7RvQh0tSNYc5UVoCl9N7dUrNXsS/wKigdvRydSCuJ1q39I2mL/NX0ZHcH81nCkTmNSZ2Z7MJ+VAe/WAydRv7qCaj13c6okKP5fWiSnrjw5/uLGlhcOQNObu6I9JbsA16fDQd5ez1Uu+EQfmHXtvIuZVMuOR/IEESG0Zvm+jUBA/0MHIovMI6TMIOQI8DqO/r7jNXB9pP6sJW9qRT54S9rtHH0+5VPe/QL6IqWQzEeoHMLEEikL0heks7Ww2HEKRVOnmmEomdVX/MzPZatWJpV7oshlWaTAjJC/gH0yvxj393cuKubOWT0J/POZfrnMfAZd3sgE4eoX9xWrp1gNsEatExBcnaLKdipvGNAirMhieQZC0+VvevO0VEuDfV5/B07OlC6Zbg1BVLm2btvODXp+eKHDeG4cqd74eWzJoEuSwZbkTH3EAyJy7j7scElFz1ZlTOJmYypxmRFhxeqYRPSXsHCHrBrCmwsj5LzE6ih3QnyVdi8fZWslBKDoz4u7K2Dy3bjP/zmWmygIEMZ5aCR42AcH+mwTgNDmU5x93h4jkl7atWAmz35oHKjDazLhNLM09gSwnwkp2zGeFUGSQb3G3oZF92+cy2Fj1Iqkraz2Ische+m+q91eG8coJgzygDb7y2RvAkMwMSTNMp3BySXlUw6dqj8mEjArAhRK2Pn03BlGYTvbiHJJea4GtjjxqpU9lk81SGyMM7Vcf2lnJ3rPf+6
MENTION_USER_ID: AgCqqxjnt/xiDfBj7+3i3p46+/yqeDvtLJPLdRwiGWFFJZ0gbm7tDH2q04GatSzxLM/NI5yapIbizmBmBqswEfGyraaTtwP9uBoQZsc/vZBncSoxAkHQvDzJr67KL0yOpIyYm+JeY8KPyIra6INozE0Ir6sLo8diyKxLvPlxvg9UJMfEp5eRdk01PxgBkj9kWLWA3shRNZlH+WfnzPILvc9TUPaSI2xq8QJaKOg93Wqf6grqK5x/6C4vV7nMzPo/NOSSfZ76Da8iUig4mZJ0aSzdZqBQSOhu4EBspG8iA9q/Ptn0Oao5nNTF53ozDdADAS0hJ3ODHaLi+iyTg3N0tWzK0ivsGs7yRe37NuGwdYEx2H2GMxSZTYlMX+v/FPsGw2tktkokUkjwzEcw7iq5XaHUW6j2XwB8WXpde3mYMx3ZhysJRwALkI9wNEK3npGl9pNrGkyTVXwQkcatAO2G2n7sxc0moCa74h3RHiSy0MtiIa79A/JhPlFVg3W4DXTaKRrNb8RhFjhvB+HVvJ9MWxcAicJMUiZftnsYGEJiTg2nDdmJM8Hof0+AJRXDCy3txcWnzOx2hTjGvBzI4qpSiU4+LU5FKPYrZ0ZtkHXYRil4M/BKS1pCPFoMQf10qsBDOHJ3jKhq3zG33qaVaF/vYljMr+q1TutIETzSJNzKLBmCjj9+PKslpiNm6493a9zuTwvm8VAAY0WXoxeKLj3ov7SLbP8=
template:
metadata:
name: alert-bridge-secret
namespace: home-services

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Usage: bash manifests/home-services/alert-bridge-secret.sh
# Description: Regenerates the alert-bridge SealedSecret from .env
#
# Deliberately reads prefixed ALERT_BRIDGE_* variable names from the shared
# .env, unlike ha-gateway-secret.sh/discord-bot-secret.sh's unprefixed
# HA_TOKEN/DISCORD_TOKEN - "API_KEY" alone is too generic a name to trust to
# this repo's single flat .env namespace shared across every service's
# secret.sh script.
set -euo pipefail
source "$(dirname "$0")/../../.env"
kubectl create secret generic alert-bridge-secret \
--namespace=home-services \
--from-literal=API_KEY="${ALERT_BRIDGE_API_KEY}" \
--from-literal=DISCORD_WEBHOOK_URL="${ALERT_BRIDGE_DISCORD_WEBHOOK_URL}" \
--from-literal=MENTION_USER_ID="${ALERT_BRIDGE_MENTION_USER_ID}" \
--dry-run=client -o yaml \
| kubeseal --controller-namespace=kube-system \
--controller-name=sealed-secrets-controller \
--format=yaml \
> "$(dirname "$0")/alert-bridge-sealed.yaml"
echo "alert-bridge-sealed.yaml regenerated — commit to repo"

View File

@ -0,0 +1,80 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: alert-bridge
namespace: home-services
labels:
app: alert-bridge
spec:
replicas: 1
selector:
matchLabels:
app: alert-bridge
template:
metadata:
labels:
app: alert-bridge
spec:
imagePullSecrets:
- name: gitea-registry-secret
containers:
- name: alert-bridge
image: gitea.nik4nao.com/nik/alert-bridge:latest
ports:
- containerPort: 8080
name: http
env:
- name: HTTP_PORT
value: "8080"
- name: API_KEY
valueFrom:
secretKeyRef:
name: alert-bridge-secret
key: API_KEY
- name: DISCORD_WEBHOOK_URL
valueFrom:
secretKeyRef:
name: alert-bridge-secret
key: DISCORD_WEBHOOK_URL
- name: MENTION_USER_ID
valueFrom:
secretKeyRef:
name: alert-bridge-secret
key: MENTION_USER_ID
- name: OTEL_ENDPOINT
value: "otel-collector-opentelemetry-collector.monitoring.svc.cluster.local:4317"
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: alert-bridge
namespace: home-services
labels:
app: alert-bridge
spec:
selector:
app: alert-bridge
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP

View File

@ -51,6 +51,7 @@ dnsmasq:
- address=/ha.home.arpa/192.168.7.77 - address=/ha.home.arpa/192.168.7.77
- address=/argocd.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77
- address=/gluetun.home.arpa/192.168.7.77 - address=/gluetun.home.arpa/192.168.7.77
- address=/alert-bridge.home.arpa/192.168.7.77
persistentVolumeClaim: persistentVolumeClaim:
enabled: true enabled: true

View File

@ -81,4 +81,5 @@ dnsmasq:
- address=/gitea.nik4nao.com/192.168.7.77 - address=/gitea.nik4nao.com/192.168.7.77
- address=/ha.home.arpa/192.168.7.77 - address=/ha.home.arpa/192.168.7.77
- address=/argocd.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77
- address=/gluetun.home.arpa/192.168.7.77 - address=/gluetun.home.arpa/192.168.7.77
- address=/alert-bridge.home.arpa/192.168.7.77