Skip to content

OIDC Login Fails when running multiple instances #1034

Description

@Javex

Can the issue be reproduced with the latest available release? (y/n)
y (gotify/server:3.0.0)

Which one is the environment gotify server is running in?

  • Docker
  • Linux machine
  • Windows machine
  • Kubernetes
deployment.yaml
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: gotify
      app.kubernetes.io/name: gotify
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      annotations:
        alertmanager-bridge-templates/config: a3520f5dc1b26b019d61808906af87497f43ba75da812c84ed42bfcf12cfa24e
        kubectl.kubernetes.io/restartedAt: "2025-11-24T17:36:44+10:30"
      labels:
        app.kubernetes.io/instance: gotify
        app.kubernetes.io/name: gotify
    spec:
      containers:
      - env:
        - name: TZ
          value: Australia/Adelaide
        - name: GOTIFY_LOGLEVEL
          value: debug
        - name: GOTIFY_DATABASE_DIALECT
          value: postgres
        - name: GOTIFY_DATABASE_CONNECTION
          valueFrom:
            secretKeyRef:
              key: database_connection
              name: gotify
        - name: GOTIFY_DEFAULTUSER_NAME
          value: flozza
        - name: GOTIFY_DEFAULTUSER_PASS
          valueFrom:
            secretKeyRef:
              key: defaultuser_pass
              name: gotify
        - name: GOTIFY_PASSSTRENGTH
          value: "10"
        - name: GOTIFY_SERVER_PORT
          value: "8081"
        - name: GOTIFY_UPLOADEDIMAGESDIR
          value: data/images
        - name: GOTIFY_PLUGINSDIR
          value: data/plugins
        - name: GOTIFY_REGISTRATION
          value: "false"
        - name: GOTIFY_OIDC_ENABLED
          value: "true"
        - name: GOTIFY_OIDC_ISSUER
          value: https://auth.example.com/application/o/gotify/
        - name: GOTIFY_OIDC_CLIENTID
          valueFrom:
            secretKeyRef:
              key: oidc_client_id
              name: gotify
        - name: GOTIFY_OIDC_CLIENTSECRET
          valueFrom:
            secretKeyRef:
              key: oidc_client_secret
              name: gotify
        - name: GOTIFY_OIDC_REDIRECTURL
          value: https://gotify.home.example.com/auth/oidc/callback
        - name: GOTIFY_OIDC_AUTOREGISTER
          value: "false"
        - name: GOTIFY_OIDC_LINK_BY_USERNAME
          value: "true"
        image: gotify/server:3.0.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /health
            port: http
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: gotify
        ports:
        - containerPort: 8081
          name: http
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /health
            port: http
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            memory: 50Mi
          requests:
            memory: 20Mi
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /app/data
          name: gotify-data
      - env:
        - name: GOTIFY_ENDPOINT
          value: http://127.0.0.1:8081/message
        - name: GOTIFY_TOKEN
          valueFrom:
            secretKeyRef:
              key: gotify_token
              name: gotify
        image: ghcr.io/druggeri/alertmanager_gotify_bridge:2.3.2
        imagePullPolicy: IfNotPresent
        name: alertmanager-bridge
        ports:
        - containerPort: 8080
          name: bridge
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /templates
          name: alertmanager-bridge-templates-dest
      dnsPolicy: ClusterFirst
      initContainers:
      - command:
        - sh
        - -c
        - cp /templates-cm/* /templates/
        image: alpine:latest
        imagePullPolicy: Always
        name: alertmanager-bridge-template-copy
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /templates-cm
          name: alertmanager-bridge-templates
        - mountPath: /templates
          name: alertmanager-bridge-templates-dest
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - emptyDir: {}
        name: gotify-data
      - configMap:
          defaultMode: 420
          name: alertmanager-bridge-templates
        name: alertmanager-bridge-templates
      - emptyDir: {}
        name: alertmanager-bridge-templates-dest

Do you have an reverse proxy installed in front of gotify server? (Please select None if the problem can be reproduced without the presense of a reverse proxy)

  • None
  • Nginx
  • Apache
  • Caddy
  • Traefik
Reverse proxy configuration (please mask sensitive information)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  annotations:
    meta.helm.sh/release-name: gotify
    meta.helm.sh/release-namespace: gotify
  creationTimestamp: "2025-11-17T12:02:39Z"
  generation: 2
  labels:
    app.kubernetes.io/instance: gotify
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: gotify
    helm.sh/chart: gotify-0.6.2
  name: gotify
  namespace: gotify
  resourceVersion: "96523273"
  uid: 68a94b6b-6e21-4fbc-86d4-7462e3a80b36
spec:
  hostnames:
  - gotify.example.com
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: traefik-gateway
    namespace: traefik
  rules:
  - backendRefs:
    - group: ""
      kind: Service
      name: gotify
      port: 80
      weight: 1
    matches:
    - path:
        type: PathPrefix
        value: /
status:
  parents:
  - conditions:
    - lastTransitionTime: "2025-11-17T12:07:15Z"
      message: ""
      observedGeneration: 2
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2025-11-17T12:07:15Z"
      message: ""
      observedGeneration: 2
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    controllerName: traefik.io/gateway-controller
    parentRef:
      group: gateway.networking.k8s.io
      kind: Gateway
      name: traefik-gateway
      namespace: traefik

On which client do you experience problems? (Select as many as you can see)

  • WebUI
  • gotify-cli
  • Android Client
  • 3rd-party API call (Please include your code)

What did you do?

I upgraded to v3 and configured OIDC, but the login failed (see error below). I figured out that if I reduced my replicaCount to 1 the error went away. I think the root cause is this line:

	if _, err := rand.Read(cookieKey); err != nil {
		log.Fatal().Err(err).Msg("failed to generate OIDC cookie key")
	}

Each instance generates its own OIDC key, so multiple instances (pods in my case) get their own key. I found a similar issue in project-zot/zot#2526 which looks like the same type of issue (if my theory is correct).

What did you expect to see?

OIDC login works even with multiple containers running.

Ideally, as a user, I would like to provide my own secret key for the cookie as an env var so that all instances use the same value. That would hopefully fix the issue.

What did you see instead? (Include screenshots, android logcat/request dumps if possible)

failed to get state: securecookie: the value is not valid

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions