Keycloak Connection Refused: Troubleshooting Guide

Guilliano Molaire Guilliano Molaire 8 min read

Last updated: March 2026

“Connection refused” is one of the most common errors when setting up or operating Keycloak. The error means your client (browser, application, or another service) attempted to connect to Keycloak’s port, but nothing was listening there. The causes range from simple port misconfigurations to complex Docker networking issues.

This guide covers every common cause of connection refused errors in Keycloak, organized from the most likely to the least obvious. Each section includes diagnostic commands and a fix.

Quick Diagnostic Checklist

Before diving into specific causes, run through this quick checklist:

# 1. Is Keycloak actually running?
docker ps | grep keycloak
# or
systemctl status keycloak

# 2. What port is Keycloak listening on?
docker logs keycloak 2>&1 | grep "Listening on"

# 3. Can you reach the port locally?
curl -v http://localhost:8080/realms/master

# 4. Is the port mapped correctly (Docker)?
docker port keycloak

# 5. Is something else using the port?
lsof -i :8080
# or on Linux
ss -tlnp | grep 8080

If any of these fail, the corresponding section below will help you fix the issue.

Cause 1: Keycloak Has Not Finished Starting

Keycloak takes 10-30 seconds to start, depending on your hardware and database. If your application tries to connect during startup, it will get a connection refused error.

Diagnosis

Check the container logs for startup status:

docker logs keycloak 2>&1 | tail -20

Look for the line:

Keycloak 26.1.0 on JVM (powered by Quarkus) started in Xs.

If you see messages like Hibernate ORM is disabled or Liquibase: Update command completed, Keycloak is still starting.

Fix

Wait for Keycloak to be ready before connecting. In Docker Compose, use a health check:

services:
  keycloak:
    image: quay.io/keycloak/keycloak:26.1.0
    command: start-dev
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: admin
      KC_HEALTH_ENABLED: "true"
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD-SHELL", "exec 3<>/dev/tcp/localhost/9000 && echo -e 'GET /health/ready HTTP/1.1rnHost: localhostrnrn' >&3 && cat <&3 | grep -q '"status":"UP"'"]
      interval: 10s
      timeout: 5s
      retries: 15
      start_period: 30s

In a script, poll the health endpoint:

#!/bin/bash
echo "Waiting for Keycloak to start..."
until curl -sf http://localhost:9000/health/ready > /dev/null 2>&1; do
  sleep 2
done
echo "Keycloak is ready"

Note: Keycloak’s health endpoint runs on port 9000 by default (separate from the main application port 8080). Make sure KC_HEALTH_ENABLED=true is set.

Cause 2: Wrong Port Configuration

Keycloak 17+ (Quarkus-based) uses different default ports than the older WildFly-based versions.

Keycloak Port Defaults

Mode HTTP Port HTTPS Port Health Port
start-dev 8080 8443 9000
start (production) 8080 8443 9000

Diagnosis

Check which port Keycloak is actually listening on:

# Check container logs for the listening port
docker logs keycloak 2>&1 | grep -i "listening"

# Check port mappings
docker port keycloak

Fix

Make sure your Docker port mapping matches:

services:
  keycloak:
    ports:
      - "8080:8080"   # HTTP
      - "8443:8443"   # HTTPS (if configured)

If you have changed the port via environment variable:

environment:
  KC_HTTP_PORT: 9090
ports:
  - "9090:9090"  # Must match KC_HTTP_PORT

Cause 3: Docker Network Isolation

This is the most common cause when one Docker container cannot reach Keycloak running in another container.

Diagnosis

If your application runs in Docker and tries to connect to localhost:8080, it will fail because localhost inside a container refers to the container itself, not the Docker host.

# From inside your application container
docker exec -it my-app curl http://localhost:8080/realms/master
# This will fail with "Connection refused"

Fix

Put both containers on the same Docker network and use the service name as the hostname:

services:
  keycloak:
    image: quay.io/keycloak/keycloak:26.1.0
    command: start-dev
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: admin
    networks:
      - app-network

  my-app:
    image: my-app:latest
    environment:
      # Use the service name, not localhost
      KEYCLOAK_URL: http://keycloak:8080
    depends_on:
      keycloak:
        condition: service_healthy
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

From the my-app container, Keycloak is reachable at http://keycloak:8080, not http://localhost:8080.

For a complete Docker Compose setup with Keycloak, use our Docker Compose Generator.

Container-to-Host Communication

If Keycloak runs on the Docker host (not in a container) and your application runs in a container:

# On Docker Desktop (Mac/Windows)
environment:
  KEYCLOAK_URL: http://host.docker.internal:8080

# On Linux
extra_hosts:
  - "host.docker.internal:host-gateway"
environment:
  KEYCLOAK_URL: http://host.docker.internal:8080

Cause 4: Keycloak Crashed During Startup

Keycloak might start and immediately crash, often due to database connectivity issues or misconfiguration.

Diagnosis

# Check if the container is running or has exited
docker ps -a | grep keycloak

# Check exit code
docker inspect keycloak --format='{{.State.ExitCode}}'

# Check full logs for errors
docker logs keycloak 2>&1 | grep -i "error|exception|failed"

Common crash messages:

  • Failed to obtain JDBC Connection – Database is unreachable
  • Unable to find column or Liquibase errors – Database schema issues
  • java.lang.OutOfMemoryError – Insufficient memory

Fix: Database Connection Issues

If Keycloak cannot reach its database:

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: keycloak
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U keycloak"]
      interval: 5s
      timeout: 5s
      retries: 10

  keycloak:
    image: quay.io/keycloak/keycloak:26.1.0
    command: start-dev
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: keycloak
    depends_on:
      postgres:
        condition: service_healthy

Key points:

  • The database hostname must match the Docker service name (postgres, not localhost)
  • Use depends_on with a health check to ensure the database is ready
  • Verify credentials match between PostgreSQL and Keycloak configuration

Fix: Memory Issues

Keycloak needs at least 512MB of memory, with 1GB or more recommended:

services:
  keycloak:
    deploy:
      resources:
        limits:
          memory: 1536M
    environment:
      JAVA_OPTS_KC_HEAP: "-Xms512m -Xmx1024m"

Cause 5: Hostname Configuration Mismatch

Keycloak’s hostname configuration affects which URLs it accepts connections on. A misconfigured hostname can cause redirects to wrong URLs or refuse connections.

Diagnosis

Check the hostname configuration:

docker logs keycloak 2>&1 | grep -i "hostname"

If you see KC_HOSTNAME set to a specific domain but you are trying to access via localhost, that is the problem.

Fix for Development

For local development, use start-dev mode which disables strict hostname validation:

services:
  keycloak:
    command: start-dev
    environment:
      KC_HOSTNAME: localhost

Fix for Production

In production mode (start), configure hostname properly:

environment:
  KC_HOSTNAME: auth.example.com
  KC_HOSTNAME_STRICT: "true"
  KC_PROXY_HEADERS: xforwarded

If you are running behind a reverse proxy, see our guide on running Keycloak behind a reverse proxy for detailed proxy configuration.

Cause 6: Firewall or Security Group Rules

On cloud infrastructure, security groups or firewall rules may block the Keycloak port.

Diagnosis

# Test from outside the server
nc -zv your-server-ip 8080

# Check iptables (Linux)
sudo iptables -L -n | grep 8080

# Check firewalld (RHEL/CentOS)
sudo firewall-cmd --list-ports

# Check UFW (Ubuntu)
sudo ufw status

Fix

# UFW
sudo ufw allow 8080/tcp

# firewalld
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# AWS Security Group - via CLI
aws ec2 authorize-security-group-ingress 
  --group-id sg-xxx 
  --protocol tcp 
  --port 8080 
  --cidr 10.0.0.0/16

Cause 7: Kubernetes-Specific Issues

In Kubernetes, connection refused errors often stem from service configuration or pod readiness.

Diagnosis

# Check pod status
kubectl get pods -l app=keycloak

# Check pod logs
kubectl logs -l app=keycloak --tail=50

# Check service endpoints
kubectl get endpoints keycloak-service

# Port-forward to test directly
kubectl port-forward svc/keycloak-service 8080:8080

Common Issues

Service targetPort mismatch:

# Wrong - targetPort doesn't match Keycloak's port
apiVersion: v1
kind: Service
metadata:
  name: keycloak-service
spec:
  ports:
    - port: 80
      targetPort: 80  # Should be 8080
# Correct
spec:
  ports:
    - port: 80
      targetPort: 8080  # Keycloak's actual port

Missing readiness probe:

spec:
  containers:
    - name: keycloak
      readinessProbe:
        httpGet:
          path: /health/ready
          port: 9000
        initialDelaySeconds: 30
        periodSeconds: 10

Without a readiness probe, the service might route traffic to a pod that is not ready yet. For Kubernetes deployment best practices, see our guide on deploying Keycloak with ArgoCD.

Cause 8: SSL/TLS Configuration

If Keycloak is configured for HTTPS but you are connecting via HTTP (or vice versa), you will get a connection refused error.

Diagnosis

# Try both HTTP and HTTPS
curl -v http://localhost:8080/realms/master
curl -vk https://localhost:8443/realms/master

Fix

In development mode, Keycloak listens on HTTP by default. In production mode, it expects HTTPS:

# For development - HTTP only
environment:
  KC_HTTP_ENABLED: "true"
  KC_HOSTNAME_STRICT_HTTPS: "false"

# For production with TLS termination at the proxy
environment:
  KC_HTTP_ENABLED: "true"
  KC_PROXY_HEADERS: xforwarded
  KC_HOSTNAME: auth.example.com

For SSL certificate issues, see our Keycloak SSL certificate error fix guide.

Cause 9: Keycloak Version URL Changes

Keycloak 17+ changed its URL structure. If you upgraded from an older version, your URLs might be wrong.

Old vs New URL Patterns

Resource Keycloak 16 and earlier Keycloak 17+
Admin console /auth/admin/ /admin/
Realm endpoint /auth/realms/{realm} /realms/{realm}
Token endpoint /auth/realms/{realm}/protocol/openid-connect/token /realms/{realm}/protocol/openid-connect/token
OIDC discovery /auth/realms/{realm}/.well-known/openid-configuration /realms/{realm}/.well-known/openid-configuration

Diagnosis

# Try both URL patterns
curl -sf http://localhost:8080/realms/master > /dev/null && echo "New URL pattern works"
curl -sf http://localhost:8080/auth/realms/master > /dev/null && echo "Old URL pattern works"

Fix

Update your application configuration to use the new URL pattern (without /auth/). If you cannot update all clients immediately, Keycloak supports a compatibility mode:

environment:
  KC_HTTP_RELATIVE_PATH: /auth

This restores the /auth/ prefix. However, it is recommended to migrate to the new URL pattern. For more details on URL changes across versions, see our Keycloak realm not found troubleshooting guide.

Cause 10: CORS Blocking Requests

If your browser shows a connection error but curl works fine, CORS (Cross-Origin Resource Sharing) might be the issue. The browser blocks the request before it reaches Keycloak, which can appear similar to a connection refused error.

Diagnosis

Check the browser’s developer console for CORS errors:

Access to XMLHttpRequest at 'http://localhost:8080/...' from origin 'http://localhost:3000'
has been blocked by CORS policy

Fix

Configure the client’s Web Origins in Keycloak:

  1. Open the Keycloak admin console
  2. Navigate to your realm > Clients > your client
  3. Add your application’s origin to “Web Origins” (e.g., http://localhost:3000)

Or set Web Origins to + to automatically allow all redirect URIs as origins.

For a deep dive into CORS configuration, see our guide on configuring CORS with Keycloak OIDC clients.

Systematic Debugging Approach

When none of the above causes are obvious, use this systematic approach:

# Step 1: Verify Keycloak is running and check logs
docker ps -a | grep keycloak
docker logs keycloak --tail 100

# Step 2: Test connectivity from the same host
curl -v http://localhost:8080/realms/master

# Step 3: Test from inside the Docker network
docker run --rm --network $(docker network ls -q -f name=myapp) 
  curlimages/curl curl -v http://keycloak:8080/realms/master

# Step 4: Check DNS resolution inside Docker
docker run --rm --network $(docker network ls -q -f name=myapp) 
  busybox nslookup keycloak

# Step 5: Check port availability
docker run --rm --network $(docker network ls -q -f name=myapp) 
  busybox nc -zv keycloak 8080

# Step 6: Verify the token endpoint specifically
curl -s http://localhost:8080/realms/master/.well-known/openid-configuration | jq '.token_endpoint'

You can analyze tokens returned from a working Keycloak instance using our JWT Token Analyzer to verify the token structure is correct.

Preventing Connection Issues

To avoid connection refused errors in the first place:

  1. Always use health checks in Docker Compose and Kubernetes. Never rely on depends_on alone.
  2. Implement retry logic in your application for initial Keycloak connections.
  3. Use Skycloak’s managed hosting to eliminate infrastructure-level connection issues entirely. Skycloak handles networking, SSL, health monitoring, and high availability.
  4. Monitor Keycloak’s health endpoint with your observability stack. See our Keycloak insights for built-in monitoring.
  5. Document your networking setup. Knowing which ports, networks, and hostname configurations are in use prevents debugging sessions later.

Further Reading


Tired of debugging Keycloak infrastructure issues? Skycloak provides managed Keycloak hosting with built-in monitoring, automatic failover, and guaranteed SLA. See pricing to get started.

Guilliano Molaire
Written by Guilliano Molaire Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Ready to simplify your authentication?

Deploy production-ready Keycloak in minutes. Unlimited users, flat pricing, no SSO tax.

© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman