Files
telegram-gateway/chart/values.yaml
Gabriel Radureau 799e10dcc2
Some checks failed
Docker Build / build-and-push-image (push) Has been cancelled
Phase 2b — durable Postgres queue + worker (gated on DATABASE_URL)
Adds the async dispatch infrastructure :

- Postgres pool + embedded migration (CREATE TABLE/INDEX IF NOT EXISTS
  gateway_jobs). Auto-applied at boot. lib/pq driver (matches webapp
  convention).
- queue.go : Enqueue (idempotent on UNIQUE(bot_slug, update_id) — handles
  Telegram redelivery), Pop with FOR UPDATE SKIP LOCKED, MarkDone,
  MarkFailed with exponential backoff (30s → 2m → 10m → 1h → dead at 5).
- worker.go : goroutine that drains the queue, dispatches via the same
  Handler interface as sync, schedules retries on failure, notifies the
  user once when a job goes to dead.
- BotConfig gains `async: bool`. Registry refuses bots with async=true
  if DATABASE_URL is unset (queue=nil).
- Server : when bot.Async, the webhook ack is immediate ; the update
  payload is enqueued for the worker.

When DATABASE_URL is unset (current default), queue/worker stay disabled
and only sync handlers (echo, http, auth) work — no breaking change to
the running cluster.

Refs ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 2.
2026-05-09 14:38:41 +02:00

135 lines
3.7 KiB
YAML

replicaCount: 1
image:
repository: gitea.arcodange.lab/arcodange/telegram-gateway
pullPolicy: Always
# Le registry ne produit que :latest et la branch ref (:main) via le
# workflow Gitea Actions ; appVersion (0.1.0) n'existe pas comme tag.
# Image Updater écrira ensuite le digest réel dans le manifest in-cluster.
tag: "latest"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
automount: true
annotations: {}
name: ""
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
service:
type: ClusterIP
port: 8080
# Public exposure via Traefik. Cloudflare routes *.arcodange.fr to the home lab
# already, so we just declare the hostname here. CF terminates TLS, Traefik
# receives plain HTTP on entrypoint `web`.
ingress:
enabled: true
className: ""
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.middlewares: kube-system-crowdsec@kubernetescrd
hosts:
- host: tg.arcodange.fr
paths:
- path: /
pathType: Prefix
tls: []
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /readyz
port: http
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 80
# Bot routing config — non-secret, becomes the bots.yaml ConfigMap entry.
# Tokens & secret_token values live in a k8s Secret named `secret.name`.
#
# Auth gate (Phase 1.5, ADR factory/doc/adr/20260509-telegram-gateway-auth.md):
# - `requireAuth` defaults to **true** (secure by default). Add
# `requireAuth: false` only for bots you want to expose publicly.
# - For `handler: auth`, requireAuth is auto-forced to false (the auth bot
# can't gate itself or no one could ever authenticate).
bots:
factory:
handler: auth # principal bot — gère /auth, /whoami, /logout
# Exemple d'un bot gated (défaut) :
# pingbot:
# handler: echo
#
# Exemple d'un bot public (opt-out explicite) :
# statusbot:
# handler: echo
# requireAuth: false
# Auth layer (Phase 1.5). REDIS_URL est passé en env clair (non secret).
# AUTH_SECRET et ALLOWED_USERS doivent vivre dans le Secret k8s `secret.name`.
auth:
redisURL: "redis://redis.tools.svc.cluster.local:6379/0"
sessionTTL: "24h"
# Async queue (Phase 2b). Quand DATABASE_URL est dans le Secret cluster,
# la queue Postgres + worker s'activent ; sinon tout reste sync (les bots
# avec `async: true` font fail au boot — secure by default).
# Format DSN attendu : postgres://USER:PASSWORD@pgbouncer.tools:6432/DBNAME?sslmode=disable
# L'utilisateur doit avoir CREATE TABLE / CREATE INDEX sur la base cible
# (le pod auto-applique les migrations idempotentes au démarrage).
# k8s Secret consumed by `envFrom`. Phase 1: create it manually with kubectl.
# kubectl -n telegram-gateway create secret generic telegram-gateway-bots \
# --from-literal=BOT_FACTORY_TOKEN=… --from-literal=BOT_FACTORY_SECRET=…
secret:
name: telegram-gateway-bots
# Vault Secrets Operator integration (Phase 2+). When enabled, VSO writes the
# secret named `secret.name` automatically from `kvv2/telegram-gateway/config`.
vault:
enabled: false
role: telegram-gateway
mount: kvv2
path: telegram-gateway/config
refreshAfter: 30s
nodeSelector:
kubernetes.io/hostname: pi1
tolerations: []
affinity: {}