Keycloak in docker behind reverse proxy

My keycloak 13.0.1 instance is behind nginx and SSL is terminated at nginx. When loading administrative console one of the URL directs to http://MYSERVER/auth/js/keycloak.js?version=1l9i9 which is a violation as it gets directed to HTTP. is there a fix?

1 Like

I’m using docker-compose and nginx(https) reverse proxying to docker(http).
These are the settings that worked for me:

docker-compose.yml

version: '3'

volumes:
  postgres_data:
      driver: local

services:
  postgres:
      image: postgres
      volumes:
        - ./postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: mypassssss
  adminer:
    image: adminer
    restart: always
    ports:
      - 9092:8080
  keycloak:
      image: quay.io/keycloak/keycloak:latest
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: mypassssss
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: ad123456
        PROXY_ADDRESS_FORWARDING: 'true'
        # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
        #JDBC_PARAMS: "ssl=true"
      ports:
        - 9091:8080
      depends_on:
        - postgres

nginx file:

server {
    server_name my.domain.net; # managed by Certbot
        root         /usr/share/nginx/html;
        client_max_body_size 1000M;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;


        location / {
        proxy_pass http://127.0.0.1:9091/;
        proxy_set_header Host $host:$server_port;
#       proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Cookie $http_cookie;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

        error_page 404 /404.html;
                location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
                location = /50x.html {
        }






    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my.domain.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my.domain.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

Did you need to make this setting because you don’t resolve the SSL certificate in nginx?
using: ssl_certificate / ssl_certificate_key nginx settings?

I’m using nginx as a reverse proxy into a LXD container with keycloak and other apps. (not using docker)

I just got past the point where the keycloak.js file is finally being requested with my domain with https, but now I’m getting a “failed to initialize keycloak” message. a 403 on /init does anyone know how to resolve this?

My nginx settings are:

    location /auth {
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass      http://10.1.1.242:8280;
    }
````Preformatted text`
the port is 8280 because I have competing ports with other apps, so when i launch keycloak i have to shift all the ports 200

`$KEYCLOAK_HOME/bin/standalone.sh  -Djboss.socket.binding.port-offset=200  -b 0.0.0.0 -bmanagement 0.0.0.`

I have also followed the docs exactly to update my standalone.xml file... lines:


.... ```

and i’ve the Frontend URL on the realm i’m testing

https://my.domain.com/auth

(I can’t set this on the master realm, otherwise i can’t login to the admin portal)

finally I’m testing with the default account client. and in that i’ve set the Web Origins to “*”

I don’t have clear memory of what I have done but I think this was due to keycloak code assuming http when connected by its 8080 port.

Even when nginx is taking care of SSL, due to probably some hardcoding assuming http when modifying URLs, instead of checking what the current protocol actually is, access to keycloak did not work when accessing keycloak through nginx then its 8080 port.

1 Like

Hi there,

I was facing the same issue when I was using nginx server as a reverse proxy but then I switched to miniOrange reverse proxy server and the issue was gone. You can check out their site here.

If you are using keycloak.x, ensure that you start it with --proxy=passthrough or one of the other values. Had the same problem with traefik passing through to keycloak and the admin console not loading due to a Mixed Content warning. As traefik already passes all required X-Forwarded-* heades, this solved it for me.

Thanks you, works for me.

Hey there. I just posted a first PR for the new proxy configs documentation in Keycloak.X - It would be great if you could provide some feedback (preferrably as comments to the PR) if this guide would’ve helped you, so these kinds of threads do not need to be opened anymore.

I am facing this error page
Screenshot 2023-11-03 101705

I use nginx as a reverse proxy in front of the keycloak docker container(KC_PROXY: edge).
My docker-compose.yaml looks like this:

services:
  postgres:
    container_name: postgres_keycloak
    image: postgres:16
    healthcheck:
      test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "root" ]
      timeout: 45s
      interval: 10s
      retries: 10
    volumes:
      - postgres_data:/var/lib/postgresql/data
      #- ./sql:/docker-entrypoint-initdb.d/:ro # turn it on, if you need run init DB
    environment:
      POSTGRES_USER: kc
      POSTGRES_PASSWORD: <pass>
      POSTGRES_DB: keycloak
      POSTGRES_HOST: postgres
    networks:
      - keycloak_network

  keycloak:
    container_name: keycloak
    healthcheck:
      test: [ "CMD", "curl", "--head","fsS", "http://localhost:8080/health/ready" ]
      interval: 5s
      timeout: 2s
      retries: 15
    build:
      context: .
      args:
        KEYCLOAK_VERSION: 22.0.0
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: <pass>
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres/keycloak
      KC_DB_USERNAME: kc
      KC_DB_PASSWORD: <pass>
      KC_HTTP_ENABLED: true
      KC_HOSTNAME: <my_fqdn>
      KC_HOSTNAME_URL: http://localhost:8080/auth
      KC_HOSTNAME_ADMIN_URL: http://localhost:8080/auth
      KC_HOSTNAME_PATH: /auth
      KC_HOSTNAME_STRICT_HTTPS: false
      KC_HOSTNAME_STRICT: false
      KC_PROXY: edge
      KC_PROXY_ADDRESS_FORWARDING: true
    ports:
      - "9090:8080"
    networks:
      - keycloak_network
    command:
      - start --optimized

volumes:
  postgres_data:

networks:
  keycloak_network:
    driver: bridge

My nginx config looks like this:

...

server {
        ...
        ...

        location /auth {
                proxy_pass http://localhost:9090/;

                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Server $host;
        }
}

Any help is appreciated!

EDIT:
When using curl http://localhost:9090/ locally, the correct site is prompted, so the fault seems to be a misconfigured proxy or faulty/missing environment variables.

My mistake was using KC_HOSTNAME_PATH instead of KC_HTTP_RELATIVE_PATH (which is a build option!). This did the trick for me

I have a situation very similar to yours: keycloak in a docker container on my NSA with nginx as a reverse-proxy. nginx is setup for the dockerized-keycloak service (using Synology’s Container Manager) by the NAS itself (Synology Web Station).

  • I am able to get to the admin console but when I try to login with the admin credentials I get the “We are sorry…” page with the error message: Cookie not found. Please make sure cookies are enabled in your browser.
  • I think this means that the application is unable to find the AUTH_SESSION_ID cookie that is supposed to be set when you first visit the admin login page (and before logging in). I don’t know why it cannot be found (I used Firefox Inspector to check) but suspect it may have to do with hostname +/ path settings related to a reverse proxy.
  • I tested the same setup in a Linux VM and it worked fine with the only difference being the nginx.

My docker compose is included below.

I would greatly appreciate any guidance on this!

UPDATE (May 1 '24): After much digging in I have concluded that there may be inconsistencies in the way keycloak supports dev-mode - either in documentation (and could be my partial understanding also) or in code. Specifically the way cookies are set when HTTPS is not used. So I decided to switch to HTTPS and that solved the issue. Lol!

version: '3.1'

name: mymachine-basic-services

services:

  mymachine_db:
    image: mariadb
    container_name: mymachine-mariadb
    restart: always
    environment:
      MARIADB_ROOT_PASSWORD: 
    ports: 
      - 8040:3306

  mymachine_access:
    image: keycloak/keycloak
    container_name: mymachine-keycloak
    restart: always
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: 
      KC_HEALTH_ENABLED: true
      KC_METRICS_ENABLED: true
      KC_DB: mariadb
      KC_DB_URL: jdbc:mariadb://mymachine_db:3306/mymachine_keycloak
      KC_DB_USERNAME: mymachine_keycloak_user
      KC_DB_PASSWORD: 
      KC_DB_SCHEMA: mymachine_keycloak
      KC_PROXY_HEADERS: forwarded
      KC_HOSTNAME_URL: http://mymachineds723.local:8030
    ports: 
      - 8080:8080
      - 8443:8443
    entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev"]

Did some additional debugging and using the browser’s inspector I find that the cookies are being rejected. Will dig into it to understand why.

What is baffling is that since keycloak is operating in dev mode, I would assume that it would work with most typical browser setups. I am using Firefox with a vanilla configuration. So if keycloak is in dev mode, then why is Firefox rejecting the cookie?

Could there be domain confusion? I log into my NAS using https://mymachine.local:5001 and I am setting up keycloak access at http://mymachine.local:8080

Attaching (1) the shot of the browser inspector, (2) shot of the offending cookies.