Search code examples
dockerdocker-composekeycloakreverse-proxytraefik

Keycloak behind Traefik returns 502 Bad Gateway


The problem

I am trying to place keycloak behind traefik in order to secure several services and a SPA.

Until then, however, I only want to reach keycloak via my hostname tsl protected with traefik.

what I have tried

In my YML file below, keycloak and traefik are set up.

keycloak is created with a dockerfile as described in the documentation, and a key is also generated.

The created key is not secure, I know that in production I would use a letsencrypt certificate, but I don't want to request new certificates every time I try.

As alias server I have specified my stack host as in the compose file and the IP of my WSL. At the moment I think there might be an error, but I don't know what to change.

In my YML file keycloak is released via traefik with the https port 8443. However, if I only use

https://stack_host..:8443/admin

502 Bad Gateway appears, however everything is looking fine in my Traefik dashboard.


Solution

  • Answer

    I have now managed it. Traefik runs with Keycloak, the TSL encryption is done via traefik and not via keycoak, therefore keycloak must only be accessible via port 8080, it does not require a keypair for keycloak.

    I have added another host auth.stack_host in /etc/hosts (under Windows System32/drivers/hosts), which is now reachable under https:auth.stack_host and leads to keycloak.

    Here is a boilerplate YML file for keycloak, traefik and a vue SPA. The vue application is listening on https://stack_host:443 Set stack_host to the name of your computer or add another host in the file from above.

    version: "3"
    
    services:
      traefik:
        image: traefik:v2.9
        command:
          - --api.insecure=true
          - --providers.file.directory=/configuration/
          - --providers.file.watch=true
          - --accesslog
          - --providers.docker.exposedbydefault=false
          - --providers.docker
          - --entryPoints.websecure.address=:443
          - --entrypoints.web.address=:80
          - --entrypoints.gateway.address=:5001
        ports:
          - "172.17.108.255:8080:8080"
          - "80:80"
          - "443:443"
          - "5001:5001"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - /traefik:/configuration/
        networks:
          - external-network
        mem_limit: 200m
        mem_reservation: 100m
    
      frontend:
        build: gui
        container_name: ${STACK_NAME}-frontend
        restart: always
        networks:
          - external-network
        command: --brotli --port 8083
        labels:
          - "traefik.enable=true"
          - "traefik.docker.network=${STACK_NAME}-external"
          
          - "traefik.http.routers.frontend.rule=Host(`${STACK_HOST}`)"
          - "traefik.http.routers.frontend.entrypoints=websecure"
          - "traefik.http.routers.frontend.tls=true"
          - "traefik.http.routers.frontend.middlewares=cors_header"
          - "traefik.http.middlewares.cors_header.headers.accesscontrolallowmethods=GET,OPTIONS,PUT,POST,DELETE,PATCH"
          - "traefik.http.middlewares.cors_header.headers.accesscontrolallowheaders=*"
          - "traefik.http.middlewares.cors_header.headers.accesscontrolalloworiginlist=https://${STACK_HOST}"
          - "traefik.http.middlewares.cors_header.headers.accesscontrolmaxage=100"
          - "traefik.http.middlewares.cors_header.headers.addvaryheader=true"
          - "traefik.http.services.frontend.loadbalancer.server.port=8083"
          - "traefik.http.services.frontend.loadbalancer.server.scheme=http"
    
    
      keycloak:
        container_name: keycloak
        build: KeycloakContainer
        restart: always
        command: start
        environment:
          KC_PROXY_ADDRESS_FORWARDING: "true"
          KC_HOSTNAME_STRICT: "false"
          KC_HOSTNAME_STRICT_HTTPS: "false"
          KC_HOSTNAME: auth.${STACK_HOST}
          KC_HTTP_ENABLED: "true"
          KC_PROXY_HEADERS: xforwarded
          KEYCLOAK_ADMIN: admin
          KEYCLOAK_ADMIN_PASSWORD: password
          KC_HEALTH_ENABLED: "true"
        labels:
          - "traefik.docker.network=${STACK_NAME}-external"
          - "traefik.enable=true"
          - "traefik.http.routers.keycloak.rule=Host(`auth.${STACK_HOST}`)"
          - "traefik.http.routers.keycloak.tls=true"
          - "traefik.http.services.keycloak.loadbalancer.server.port=8080"
        networks:
          - external-network
          - internal-network
        healthcheck:
          test:
            [
              "CMD-SHELL",
              "exec 3<>/dev/tcp/localhost/8080 && echo -e 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && cat <&3 | grep -q '200 OK'"
            ]
          interval: 30s
          timeout: 5s
          retries: 20
    
    networks:
      internal-network:
        name: ${STACK_NAME}-internal
        internal: true
      external-network:
        name: ${STACK_NAME}-external
        driver: bridge
    

    Keycloak Dockerfile/ or just use the image if you dont want to import smth.

    FROM quay.io/keycloak/keycloak:24.0.1 as builder
    WORKDIR /opt/keycloak
    
    RUN /opt/keycloak/bin/kc.sh build
    
    FROM quay.io/keycloak/keycloak:24.0.1
    
    COPY --from=builder /opt/keycloak/ /opt/keycloak/
    
    // load custom theme
    COPY ./marvins-theme/ /opt/keycloak/themes/marvins-theme
    
    // import realm
    COPY ./realm-config/realm.json /opt/keycloak_import/
    
    RUN /opt/keycloak/bin/kc.sh import --file /opt/keycloak_import/realm.json
    ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]