# Recommended reverse proxy setup example and headers question

**URL:** <https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636>\
**Category:** Configuring the server\
**Created:** [March 3, 2023, 7:34pm UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636 "2023-03-03T19:34:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![berber](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/berber/32/7843_2.png) [@berber](https://forum.keycloak.org/u/berber)\
**Post date:** [March 3, 2023, 7:34pm UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636/1 "2023-03-03T19:34:35Z")

</div>

I am having a lot of difficulties setting up my reverse proxy and reaching the admin console. Can somebody help me or give me _any_ reverse proxy setup that works on their server? Yes, I have looked through other posts here.

I can’t seem to find any example config that adheres to the official recommendations here [Using a reverse proxy - Keycloak](https://www.keycloak.org/server/reverseproxy). I will write down what my tries for a setup that adheres to the official reverse proxy guide, and where my problems are.

This is the summary of what I have observed, and I should note that I use NixOS.

- Everything works fine if I don’t set the headers (`X-Forwarded-*`, etc), but the official recommendations strongly advise to set these headers.
- When setting the `proxy_set_header`s (I’ll get to that a bit lower), everything works if I just expose the root directory `/`, but obviously that is not very secure. If I put a basic auth infront of the vulnerable locations (which is not an ideal setup anyway), then I also cannot reach the admin console.
- If I set the `proxy_set_header`s, and expose only `/js/`, `/realms/`, `/resources/`, and `/robots.txt`, and furthermore set `hostname-admin` in the keycloak config to `localhost`, I can’t seem to reach the admin console when I reach it via `ssh` port forwarding (I use `ssh -L 8080:localhost:8080 mykeycloak.server`). I get an “invalid parameter: redirect\_uri” error. Removing (some of) the `proxy_set_header` in the nginx config gives me other problems, like an infinite “Loading the admin console” screen, and when I remove enough of those `proxy_set_header`s, then it works (as I mentioned in the first bullet point).

I am sorry to say that I am not too knowledgeable about how these headers work.

This is my Keycloak configuration:

```auto
db=postgres
db-password=somepassword
db-url-database=keycloak
db-url-host=localhost
db-url-port=5432
db-url-properties=
db-username=keycloak
hostname=mykeycloak.server
hostname-admin=localhost
hostname-strict-backchannel=false
http-host=0.0.0.0
http-port=8080
http-relative-path=/
https-certificate-file=/run/keycloak/ssl/ssl_cert
https-certificate-key-file=/run/keycloak/ssl/ssl_key
https-port=8443
proxy=edge

```

This is my nginx configuration (yeah sorry I run NixOS so it adds a lot of clutter):

```auto
pid /run/nginx/nginx.pid;
error_log stderr;
daemon off;
events {
}
http {
        # The mime type definitions included with nginx are very incomplete, so
        # we use a list of mime types from the mailcap package, which is also
        # used by most other Linux distributions by default.
        include /nix/store/<long-nix-store-hash>-mailcap-2.1.53/etc/nginx/mime.types;
        # When recommendedOptimisation is disabled nginx fails to start because the mailmap mime.types database
        # contains 1026 enries and the default is only 1024. Setting to a higher number to remove the need to
        # overwrite it because nginx does not allow duplicated settings.
        types_hash_max_size 4096;
        include /nix/store/<long-nix-store-hash>-nginx-1.22.1/conf/fastcgi.conf;
        include /nix/store/<long-nix-store-hash>-nginx-1.22.1/conf/uwsgi_params;
        default_type application/octet-stream;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
        proxy_redirect off;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        proxy_http_version 1.1;
        include /nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf;
        # $connection_upgrade is used for websocket proxying
        map $http_upgrade $connection_upgrade {
                default upgrade;
                '' close;
        }
        client_max_body_size 10m;
        server_tokens off;
        server {
                listen 0.0.0.0:443 http2 ssl ;
                listen [::0]:443 http2 ssl ;
                listen 0.0.0.0:80 ;
                listen [::0]:80 ;
                server_name mykeycloak.server ;
                # Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
                # We use ^~ here, so that we don't check any regexes (which could
                # otherwise easily override this intended match accidentally).
                location ^~ /.well-known/acme-challenge/ {
                        root /var/lib/acme/acme-challenge;
                        auth_basic off;
                }
                root /var/www/mykeycloak.server;
                ssl_certificate /var/lib/acme/mykeycloak.server/fullchain.pem;
                ssl_certificate_key /var/lib/acme/mykeycloak.server/key.pem;
                ssl_trusted_certificate /var/lib/acme/mykeycloak.server/chain.pem;
                location /js/ {
                        proxy_pass http://localhost:8080/js/;
                        include /nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf;
                }
                location /realms/ {
                        proxy_pass http://localhost:8080/realms/;
                        include /nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf;
                }
                location /resources/ {
                        proxy_pass http://localhost:8080/resources/;
                        include /nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf;
                }
                location /robots.txt {
                        proxy_pass http://localhost:8080/robots.txt;
                        include /nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf;
                }
        }
}

```

Important: `/nix/store/<long-nix-store-hash>-nginx-recommended-proxy-headers.conf` contains the following:

```auto
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-Host $host;
proxy_set_header X-Forwarded-Server $host;

```

Removing the `proxy_set_header`s `Host` and `X-Forwarded-Proto` and `X-Real-IP` resolves my issues iirc (removing different ones gives me different issues when trying to reach the admin console), and removing all of it definitely resolves my issues, as mentioned before. But also as mentioned, setting `X-Forwarded Proto` was recommended by the official documentation. Also, it recommends setting `X-Forwarded-Port`. Furthermore, I have no idea how I would set `Forward` as per RFC7239.

Can somebody give me _any_ reverse proxy config that works on their server? I am willing to change the setup, I don’t have any super specific requirements/restrictions.

Any help is appreciated.

---

<div class="post-metadata">

**Author:** ![gsmith](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/gsmith/32/294_2.png) [@gsmith](https://forum.keycloak.org/u/gsmith)\
**Post date:** [March 4, 2023, 5:46am UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636/2 "2023-03-04T05:46:55Z")

</div>

Hey @berber

Here is mine, perhaps this will help.

```auto
cat > /etc/nginx/conf.d/keycloak.conf <<EOF
upstream keycloak {
    # Use IP Hash for session persistence
    ip_hash;
  
    # List of Keycloak servers
    server 192.168.1.101:8080;
}
  
      
server {
    listen 80;
    server_name lab-keycloak.keycloak.local;
 
    # Redirect all HTTP to HTTPS
    location / {   
      return 301 https://\$server_name\$request_uri;
    }
}
  
server {
    listen 443 ssl http2;
    server_name lab-keycloak.keycloak.local;
 
    ssl_certificate /etc/pki/tls/certs/my-cert.cer;
    ssl_certificate_key /etc/pki/tls/private/my-key.key;
    ssl_session_cache shared:SSL:1m;
    ssl_prefer_server_ciphers on;
 
    location / {
      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_pass http://keycloak;
    }
}
EOF

```

---

<div class="post-metadata">

**Author:** ![berber](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/berber/32/7843_2.png) [@berber](https://forum.keycloak.org/u/berber)\
**Post date:** [March 4, 2023, 9:53am UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636/3 "2023-03-04T09:53:32Z")

</div>

Thank you for your reply!

If I try your config, I would still have the same problems I’ve had before:

- The root directory is exposed, which in particular exposes `/admin/`.
- Not all of the `proxy_set_header`s are set that are mentioned in the official reverse proxy recommendations.

---

<div class="post-metadata">

**Author:** ![lajibolala](https://avatars.discourse-cdn.com/v4/letter/l/a4c791/32.png) [@lajibolala](https://forum.keycloak.org/u/lajibolala)\
**Post date:** [April 26, 2023, 5:38pm UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636/4 "2023-04-26T17:38:34Z")

</div>

I’m using a similar reverse proxy setup in my project, but I’m struggling in connect keycloak to LDAP over SSL, can you give a check in my [question](http://forum.keycloak.org/t/javax-net-ssl-sslhandshakeexception-when-connecting-keycloak-to-ldap-over-ssl/21721)

---

<div class="post-metadata">

**Author:** ![gsmith](https://yyz2.discourse-cdn.com/free1/user_avatar/forum.keycloak.org/gsmith/32/294_2.png) [@gsmith](https://forum.keycloak.org/u/gsmith)\
**Post date:** [April 26, 2023, 9:32pm UTC](https://forum.keycloak.org/t/recommended-reverse-proxy-setup-example-and-headers-question/20636/5 "2023-04-26T21:32:17Z")

</div>

Hey @lajibolala

> [@lajibolala](#):
>
> keycloak to LDAP over SSL,

I posted a while back, not sure if this will help but over TCP/TLS using LDAPS

> [@Keycloak Connecting to MSAD LDAP Over SSL](http://forum.keycloak.org/t/keycloak-connecting-to-msad-ldap-over-ssl/1921):
>
> Unable to Connect to MSAD LDAP over SSL Server Info: Server Version 9.0.2 Standalone Server Profile: Community Operating System: CentOS 7 minimal Latest Virtual Machine 4 CPU, 6GB Memory, and 100GB Storage. Java Version 1.8.0\_242 Created a Service account on MSAD with Administrator Rights for Read/Write to User/s OU. My issue is I need to write Password/Login Name attributes back to MSAD from Keycloak. The only way I see this happening is to enable LDAP over SSL. My Active Directory con…
