Authelia

Prerequisites

This guide assumes you have the following prerequisites in place:

Authelia

Authelia is an open-source authentication and authorization server that provides a single sign-on (SSO) solution for your applications. It supports various authentication methods, including LDAP, TOTP, and WebAuthn, and can be easily integrated with reverse proxies like Traefik to secure access to your applications.

Installation

  1. Create the following directory structure for Authelia:

     authelia/
     ├── authelia-cm.yml
     ├── authelia-db.yml
     ├── authelia-ingress.yml
     ├── authelia-middleware.yml
     ├── authelia-redis.yml
     ├── authelia-release.yml
     ├── authelia-repository.yml
     ├── authelia-secret.yml
     ├── authelia-users-secret.yml
     └── authelia-users.yml
  2. Add the following content to authelia/authelia-cm.yml:

     ---
     apiVersion: v1
     kind: ConfigMap
     metadata:
       name: authelia-config
       namespace: tools
     data:
       configuration.yaml: |
         server:
           address: 'tcp4://:9091'
           buffers:
             read: 16384
         log:
           level: info 
           file_path: ''
           keep_stdout: true
    
         identity_validation:
           elevated_session:
             require_second_factor: true
           reset_password:
             jwt_lifespan: '5 minutes'
    
         theme: dark
    
         totp:
           disable: false
           issuer: 'example.com'
           period: 30
           skew: 1
           algorithm: 'sha1'
           digits: 6
           secret_size: 32
           allowed_algorithms:
             - 'SHA1'
           allowed_digits:
             - 6
           allowed_periods:
             - 30
           disable_reuse_security_policy: false
    
         password_policy:
           zxcvbn:
             enabled: true
             min_score: 4
    
         authentication_backend:
           file:
             path: '/secrets/users.yml'
             password:
               algorithm: 'argon2'
               argon2:
                 variant: 'argon2id'
                 iterations: 3
                 memory: 65535
                 parallelism: 4
                 key_length: 32
                 salt_length: 16
    
         access_control:
           default_policy: 'deny'
           rules:
             - domain: 'auth.example.com'
               policy: bypass
             - domain: 'invidious.example.com'
               resources: '^/(api/v1|feed|videoplayback|vi/.+\.(jpg|webp)|ggpht|latest_version|sb)'
               policy: bypass
             - domain: 'immich.example.com'
               policy: bypass
             - domain: 'vw.example.com'
               policy: bypass
             - domain: '*.example.com'
               policy: two_factor
    
         session:
           name: 'authelia_session'
           cookies:
             - domain: 'example.com'
               authelia_url: 'https://auth.example.com'
           redis:
             host: 'authelia-dragonfly.tools.svc.cluster.local'
             port: 6379
    
         regulation:
           max_retries: 4
           find_time: 120
           ban_time: 300
    
         storage:
           postgres:
             address: 'tcp://authelia-db-cluster.tools.svc.cluster.local:5432'
             database: authelia
             username: authelia
             tls:
               skip_verify: true
               server_name: ''
               minimum_version: TLS1.2
    
         notifier:
           disable_startup_check: false
           smtp:
             address: submissions://smtp.gmail.com:465
             username: [email protected]
             sender: [email protected]
             identifier: localhost
             subject: "[Authelia] {title}"
             startup_check_address: [email protected]
             disable_require_tls: false
             disable_html_emails: false
             tls:
               skip_verify: false
               minimum_version: TLS1.2
         ntp:
           address: 'time.google.com:123'
           version: 4
           max_desync: '3s'
           disable_startup_check: false
  3. Add the following content to authelia/authelia-db.yml:

     ---
     kind: "postgresql"
     apiVersion: "acid.zalan.do/v1"
    
     metadata:
       name: "authelia-db-cluster"
       namespace: "tools"
       labels:
         team: acid
    
     spec:
       teamId: "acid"
       postgresql:
         version: "17"
       numberOfInstances: 2
       volume:
         size: "1Gi"
         storageClass: "longhorn"
       users:
         authelia: []
       databases:
         authelia: authelia

    Zalando Postgres Operator will deploy a PostgreSQL cluster for Authelia’s storage backend. It will create a secret named authelia.authelia-db-cluster.credentials.postgresql.acid.zalan.do in the tools namespace containing the database credentials. You need to copy the contents of this secret to a new secret named authelia-db-credentials that will be used by Authelia. You can’t refer to the original secret directly in the Authelia HelmRelease because of limitations in the Authelia Helm chart.

  4. Add the following content to authelia/authelia-ingress.yml:

     ---
     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: authelia
       namespace: tools
       annotations:
         cert-manager.io/cluster-issuer: letsencrypt-cloudflare
     spec:
       ingressClassName: traefik
       tls:
         - hosts:
             - auth.example.com
           secretName: authelia-tls
       rules:
         - host: auth.example.com
           http:
             paths:
               - path: /
                 pathType: Prefix
                 backend:
                   service:
                     name: authelia
                     port:
                       number: 9091
  5. Add the following content to authelia/authelia-middleware.yml:

    apiVersion: traefik.io/v1alpha1
    kind: Middleware
    metadata:
      name: authelia
      namespace: tools
    spec:
      forwardAuth:
        address: http://authelia.tools.svc.cluster.local:9091/api/authz/forward-auth
        trustForwardHeader: true
        authResponseHeaders:
          - Remote-User
          - Remote-Groups
          - Remote-Name
          - Remote-Email
  6. Add the following content to authelia/authelia-redis.yml:

    ---
    apiVersion: dragonflydb.io/v1alpha1
    kind: Dragonfly
    metadata:
      name: authelia-dragonfly
      namespace: tools
    spec:
      replicas: 3
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 500m
          memory: 512Mi
      args:
        - --maxmemory=256mb
  7. Add the following content to authelia/authelia-release.yml:

    ---
    apiVersion: helm.toolkit.fluxcd.io/v2
    kind: HelmRelease
    metadata:
      name: authelia
      namespace: tools
    spec:
      interval: 6h
      chart:
        spec:
          chart: authelia
          version: "0.11.4"
          sourceRef:
            kind: HelmRepository
            name: authelia
            namespace: flux-system
          interval: 6h
      install:
        remediation:
          retries: 3
      upgrade:
        remediation:
          retries: 3
      values:
        configMap:
          existingConfigMap: authelia-config
          session:
            redis:
              enabled: true
              host: authelia-dragonfly.tools.svc.cluster.local
              port: 6379
              password:
                disabled: true
                value: ''
          storage:
            postgres:
              enabled: true
              tls:
                enabled: true
              password:
                disabled: true
                secret_name: authelia-db-credentials
                path: password
          notifier:
            smtp:
              enabled: true
              username: [email protected]
              password:
                secret_name: authelia-secrets
                path: password
    
        secret:
          existingSecret: authelia-secrets
          additionalSecrets:
            authelia-secrets: {}
            authelia-db-credentials: {}
    
        service:
          port: 9091
    
        pod:
          env:
            - name: AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE
              value: /secrets/authelia-db-credentials/password
          initContainers:
            - name: substitute-users-db
              image: alpine
              envFrom:
                - secretRef:
                    name: authelia-users-secrets
              command:
                - sh
                - -c
                - |
                  apk add --no-cache gettext \
                  && envsubst < /mnt/init/users.yml > /mnt/final/users.yml
              volumeMounts:
                - name: users-db-template
                  mountPath: /mnt/init/users.yml
                  subPath: users.yml
                - name: users-db-final
                  mountPath: /mnt/final
    
          extraVolumes:
            - name: users-db-template
              configMap:
                name: authelia-users
            - name: users-db-final
              emptyDir: {}
    
          extraVolumeMounts:
            - name: users-db-final
              mountPath: /secrets/users.yml
              subPath: users.yml
  8. Add the following content to authelia/authelia-repository.yml:

    ---
    apiVersion: source.toolkit.fluxcd.io/v1
    kind: HelmRepository
    metadata:
      name: authelia
      namespace: flux-system
    spec:
      interval: 6h
      url: https://charts.authelia.com
  9. Add the following content to authelia/authelia-secret-tmp.yml:

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: authelia-secrets
      namespace: tools
    type: Opaque
    data:
      identity_validation.reset_password.jwt.hmac.key: <base64-encoded-secret-key>
      jwt.secret: <base64-encoded-secret-key>
      notifier.smtp.username: <base64-encoded-email-username>
      password: <base64-encoded-email-password>
      session.authentication.key: <base64-encoded-secret-key>
      session.encryption.key: <base64-encoded-secret-key>
      storage.encryption.key: <base64-encoded-secret-key>
  10. Encrypt the authelia/authelia-secret-tmp.yml file using Sealed-Secrets and save the output as authelia/authelia-secret.yml:

    kubeseal --format yaml < authelia/authelia-secret-tmp.yml > authelia/authelia-secret.yml && \
    rm authelia/authelia-secret-tmp.yml
  11. Add the following content to authelia/authelia-users.yml:

    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: authelia-users
      namespace: tools
    data:
      users.yml: |
        ---
        users:
          admin_user:
            displayname: 'Admin'
            password: ${ADMIN}
            email: '[email protected]'
            groups:
              - 'admin'
              - 'dev'
        #  user_2:
        #    displayname: 'User 2'
        #    password: ${USER_2}
        #    email: '[email protected]'
        #    groups:
        #      - 'users'
  12. Create a secret named authelia-users-secrets with user passwords:

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: authelia-users-secrets
      namespace: tools
    type: Opaque
    data:
      ADMIN: <base64-encoded-admin-argon-hashed-password>
      USER_2: <base64-encoded-user2-argon-hashed-password>
  13. Encrypt the authelia-users-secrets secret using Sealed-Secrets:

    kubeseal -o yaml < authelia-users-secrets.yml > authelia-users-secrets-sealed.yml && \
    rm authelia-users-secrets.yml
  14. Commit and push the changes to your git repo and wait for fluxcd to deploy Authelia.