Skip to content
ineedcloudineedcloud — home
All guides
NetworkingIntermediate

Put Keycloak behind Nginx with a free SSL certificate

Keycloak in production needs HTTPS. This guide walks through an Nginx reverse proxy with a Let's Encrypt cert — so your login page isn't served over plain HTTP.

20 min readLast updated 4 May 2026

TL;DR

Run Nginx on the same host as Keycloak, proxy traffic to it on port 8080, and use Certbot to get a free Let's Encrypt certificate. Keycloak needs specific proxy headers to work correctly behind Nginx — get those wrong and you'll see redirect loops.

What you'll need

  • A domain name pointing to your server's public IP (DNS A record, propagated)
  • A server with Docker and Nginx installed
  • Ports 80 and 443 open in your firewall
  • Certbot: sudo apt install certbot python3-certbot-nginx

Step 1 — Run Keycloak bound to localhost

Keycloak should not be publicly accessible directly. Start it bound to the loopback interface only, in production mode:

docker run -d \
  --name keycloak \
  -p 127.0.0.1:8080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=changeme \
  -e KC_PROXY=edge \
  -e KC_HOSTNAME=auth.yourdomain.com \
  quay.io/keycloak/keycloak:latest \
  start-dev

Replace auth.yourdomain.com with your actual domain. KC_PROXY=edge tells Keycloak it's behind a reverse proxy that handles TLS.

Step 2 — Configure Nginx

Create a new site config:

sudo nano /etc/nginx/sites-available/keycloak

Paste this, replacing the domain name:

server {
    listen 80;
    server_name auth.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_buffer_size 128k;
        proxy_buffers 4 256k;
    }
}

Enable it:

sudo ln -s /etc/nginx/sites-available/keycloak /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 3 — Get the SSL certificate

sudo certbot --nginx -d auth.yourdomain.com

Follow the prompts. Certbot will edit your Nginx config automatically to add the HTTPS server block and redirect HTTP to HTTPS.

Test renewal works:

sudo certbot renew --dry-run

Step 4 — Verify

Open https://auth.yourdomain.com in your browser. You should see the Keycloak welcome page with a valid certificate. The padlock should be green.

The admin console is at https://auth.yourdomain.com/admin.

Common pitfalls

Redirect loop. The most common problem. Make sure KC_PROXY=edge is set on the Keycloak container. Without it, Keycloak doesn't trust the X-Forwarded-Proto header and thinks all requests are HTTP — causing infinite redirects.

KC_HOSTNAME must match your domain exactly. If the value doesn't match the hostname in the browser URL, Keycloak will reject or redirect requests. Include the subdomain.

Buffer size errors. Keycloak's tokens can be large. The proxy_buffer_size and proxy_buffers lines in the Nginx config prevent 502 errors caused by response headers being too big for default buffer sizes.

Certbot fails on DNS not propagated. If the A record is too fresh, Let's Encrypt can't verify the domain. Wait 10–15 minutes and try again.

Where to go next