I would like to run keycloak with traefik as a reverse proxy on my server.
Is there a kind of boilerplate for this project. Many instructions are very old.
Do I need traefik forward auth or is there another way? The goal is that a SPA logs in to keycloak via redirect and OIDC. The services in the backend validate the access token and need access to the public key. Everything works locally so far.
Only when I tried to start the whole thing via docker-compose with a reverse proxy did I fail.
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
ports:
- "172.17.108.255:8080:8080"
- "80:80"
- "443:443"
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"]
Couple of questions for you…
I don’t see a route to the vuew spa in your config. Where is that done? Maybe a file provider?
Is anything being protected by keycloak forward auth in this config?