A step‑by‑step cookbook for adding single‑sign‑on to Keep with your self‑hosted GitLab using oauth2‑proxy and the NGINX Ingress Controller.
Conventions used below
  • <keep-host>             – public FQDN where users access Keep (e.g. keep.example.com)
  • <gitlab-host>           – URL of your GitLab instance (e.g. gitlab.example.com)
  • <registry-host>         – container registry that stores images (omit if you use the public images)
  • Kubernetes namespace keep – feel free to change it everywhere if you prefer another namespace.

1. Prerequisites

WhatWhy
Kubernetes cluster & keep namespaceWhere Keep, oauth2‑proxy and Services live
ingress‑nginx (or compatible)Provides the auth_request feature oauth2‑proxy uses
GitLab 15 + at https://<gitlab-host>OpenID‑Connect issuer
Helm 3.x & offline charts/images (optional)If your cluster has no Internet egress

2. Create the GitLab OAuth application

  1. GitLab ▸ Admin → Applications → New
  2. Name → keep‑sso
  3. Redirect URI → https://<keep-host>/oauth2/callback
  4. Scopes → openid profile email (+ read_api if you plan to gate access by group/project)
  5. Save – copy the generated Application ID and Secret.

3. Kubernetes secrets & config

# 3.1 Generate a 32‑byte cookie secret
echo "$(openssl rand -base64 32 | head -c 32 | base64)" > cookie.b64

# 3.2 Store GitLab credentials and cookie secret
kubectl -n keep create secret generic oauth2-proxy \
  --from-literal=client-id=<GITLAB_APP_ID> \
  --from-literal=client-secret=<GITLAB_APP_SECRET> \
  --from-file=cookie-secret=cookie.b64

# 3.3 Add gitlab credentials and cookie secret using OAUTH2_PROXY ENV variables
OAUTH2_PROXY_CLIENT_ID=<GITLAB_APP_ID>
OAUTH2_PROXY_CLIENT_SECRET=<GITLAB_APP_SECRET>
OAUTH2_PROXY_COOKIE_SECRET=cookie.b64

# (optional) store GitLab’s custom CA certificate
kubectl -n keep create secret generic gitlab-ca \
  --from-file=gitlab-ca.pem
# 3.4 oauth2_proxy.cfg (ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
  name: oauth2-proxy
  namespace: keep
data:
  oauth2_proxy.cfg: |
    email_domains = ["*"]
    upstreams     = ["file:///dev/null"]   # we only use auth‑request mode
    provider      = "gitlab"
    cookie_name   = "keep-dev" #if empty, will use default cookie name: _oauth2_proxy
    cookie_secure = true

4. Deploy oauth2‑proxy (Helm)

# values.oauth2-proxy.yaml – minimal baseline
image:                     # replace with public image if desired
  repository: <registry-host>/oauth2-proxy/oauth2-proxy
  tag: v7.9.0

config:
  configFile: |-
    # content comes from the ConfigMap above

extraArgs:
  oidc-issuer-url: https://<gitlab-host>
  set-xauthrequest: "true"            # add X-Auth-Request-*/X-Forwarded-* headers
  pass-authorization-header: "true"   # add Authorization: Bearer <id_token>
  # provider-ca-file: /ca/gitlab-ca.pem   # enable if you mounted a corporate CA or use ssl-insecure-skip-verify: "true" to disable SSL check.
extraVolumes:
  - name: gitlab-ca
    secret:
      secretName: gitlab-ca
extraVolumeMounts:
  - name: gitlab-ca
    mountPath: /ca/gitlab-ca.pem
    subPath: gitlab-ca.pem
    readOnly: true

service:
  type: ClusterIP

ingress:
  enabled: false   # we only need an internal Service
helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests
helm upgrade --install oauth2-proxy oauth2-proxy/oauth2-proxy \
     -n keep -f values.oauth2-proxy.yaml
Lab‑only shortcut: instead of mounting the CA you can temporarily add ssl-insecure-skip-verify: "true" under extraArgs.

5. Patch (or create) Keep’s Ingress resource

Add three annotations so ingress‑nginx delegates auth to the Service:
global:
  ingress:
    annotations:
      nginx.ingress.kubernetes.io/auth-url: "http://oauth2-proxy.keep.svc.cluster.local/oauth2/auth"
      nginx.ingress.kubernetes.io/auth-signin: "https://<keep-host>/oauth2/start?rd=$request_uri"
      nginx.ingress.kubernetes.io/auth-response-headers: "authorization,x-auth-request-user,x-auth-request-email,x-forwarded-user,x-forwarded-email,x-forwarded-groups"
Redeploy Keep (or patch the Ingress manually).

6. Environment variables for Keep

backend:
  env:
    - name: AUTH_TYPE
      value: OAUTH2PROXY
    - name: KEEP_OAUTH2_PROXY_USER_HEADER
      value: x-auth-request-email
    - name: KEEP_OAUTH2_PROXY_ROLE_HEADER
      value: x-auth-request-groups
    - name: KEEP_OAUTH2_PROXY_AUTO_CREATE_USER
      value: true
    - name: KEEP_OAUTH2_PROXY_ADMIN_ROLE
      vakue: <your gitlab group that will have admin role in your keep ui>
    - name: KEEP_OAUTH2_PROXY_NOC_ROLE
      value: <your gitlab group that wont have access to your keep ui>

frontend:
  env:
    # Public URL the **browser** should use
    - name: NEXTAUTH_URL
      value: "https://<keep-host>"

    # URL the **server‑side** Next.js code can always reach
    - name: NEXTAUTH_URL_INTERNAL
      value: "http://keep-frontend.keep.svc.cluster.local:3000"

    # API URLs
    - name: API_URL_CLIENT   # browser → ingress
      value: "/v2"
    - name: API_URL          # server → backend Service (no auth‑proxy)
      value: "http://keep-backend.keep.svc.cluster.local:8080"

    #Oauth2-Proxy
    - name: AUTH_TYPE
      value: OAUTH2PROXY
    - name: KEEP_OAUTH2_PROXY_USER_HEADER
      value: x-auth-request-email
    - name: KEEP_OAUTH2_PROXY_ROLE_HEADER
      value: x-auth-request-groups
Roll out the frontend:
kubectl -n keep rollout restart deploy/keep-frontend

7. Quick validation

# 7.1 Call auth endpoint without cookie – expect 401
curl -I http://oauth2-proxy.keep.svc.cluster.local/oauth2/auth

# 7.2 Copy the keep-dev cookie from your browser session
curl -I --cookie "keep-dev=<COOKIE>" \
     http://oauth2-proxy.keep.svc.cluster.local/oauth2/auth   # expect 200
Browser smoke‑test:
  • https://<keep-host> → redirect to GitLab → sign in → return to Keep.
  • DevTools ▸ Network → /api/auth/session returns 200.

8. Troubleshooting

SymptomCommon cause & remedy
TLS error x509: certificate signed by unknown authorityMount your GitLab CA (provider-ca-file) or set ssl-insecure-skip-verify=true (dev only).
Ingress logs auth request unexpected status: 502auth-url is pointing at the external host – use the internal Service DNS (http://oauth2-proxy.keep.svc.cluster.local).
Browser loops at /signin?callbackUrl=…① set-xauthrequest not enabled, or ② auth-response-headers not set, or ③ backend receives calls through oauth2‑proxy (API_URL wrong).
Redirect to 0.0.0.0:3000 or pod nameNEXTAUTH_URL missing at build time; rebuild UI or override env.
401 from /oauth2/auth even with cookieCookie expired / clocks out of sync. Clear cookie and re‑login.

9. Clean‑up

helm -n keep uninstall oauth2-proxy
helm -n keep uninstall keep          # if you want to remove Keep
kubectl -n keep delete secret oauth2-proxy gitlab-ca

openssl rand -hex 16 | xxd -r -p | base64

Appendix B – Sync images to an offline registry (example)

skopeo copy docker://quay.io/oauth2-proxy/oauth2-proxy:v7.9.0 \
             docker://<registry-host>/oauth2-proxy/oauth2-proxy:v7.9.0