What is Keycloak Quarkus?
Keycloak Quarkus is the Keycloak server packaged as a Quarkus application instead of being deployed inside the WildFly application server. It became the default distribution in Keycloak 17, the WildFly distribution was removed in Keycloak 20, and every current release, including the 26.x line, runs only on Quarkus with keycloak.conf, KC_* variables and a build step.
If you search for “Keycloak Quarkus” today you are really searching for Keycloak itself, because there is no other distribution left. The phrase still matters for two groups of people: teams running an old WildFly-based Keycloak (version 16 or earlier, or an old Red Hat Single Sign-On 7.x install) who need to understand what changed, and people following an older tutorial that mentions standalone.xml, jboss-cli.sh or /auth URLs and wondering why none of it matches their server. This post explains the difference between the two distributions, why the Keycloak team made the switch, and what it means for how you configure and run Keycloak now. For the hands-on cutover, follow our WildFly to Quarkus migration guide.
Keycloak: a quick overview
Keycloak is an open-source identity and access management (IAM) server, which means it handles logging users in, issuing tokens to applications and deciding who can access what. Applications hand authentication over to Keycloak through standard protocols, mainly OpenID Connect (OIDC, an identity layer on top of OAuth 2.0) and SAML 2.0, so they never handle passwords themselves. Its main capabilities are:
- Single sign-on (SSO): a user logs in once and is signed in to every application that trusts the same Keycloak realm. See how this works on our single sign-on feature page.
- Identity brokering: Keycloak can send users to an external identity provider such as Google, Microsoft Entra ID or another SAML or OIDC provider, then issue its own tokens afterwards.
- User federation: Keycloak can read users from an existing LDAP or Active Directory directory instead of copying them.
- User, group and role management: an admin console and a REST Admin API for managing who exists and what they are allowed to do.
- Authorization and API security: access tokens that your APIs validate, plus optional fine-grained Authorization Services for resource-level policies.
None of these features changed when Keycloak moved to Quarkus. What changed is the runtime underneath them, which affects how you install, configure, extend and operate the server.
The legacy: Keycloak on WildFly
Up to and including Keycloak 16, the server shipped as an application deployed into WildFly, the open-source Java application server formerly known as JBoss AS. An application server is a general-purpose runtime that hosts many Java applications and manages shared services for them, such as database connection pools, messaging and clustering. Keycloak used those WildFly subsystems, so configuring Keycloak meant configuring WildFly.
In practice that had several costs:
- Configuration lived in WildFly XML. Settings such as the database, hostname, caches and proxy handling sat in
standalone.xmlorstandalone-ha.xml, and you changed them with XML edits orjboss-cli.shscripts. Many of those settings were WildFly concepts rather than Keycloak ones. - Everything was served under
/auth. The default context path put every endpoint below/auth, for examplehttps://sso.example.com/auth/realms/myrealm. - Custom providers were WildFly modules or deployments. Extensions such as custom authenticators or user storage providers were deployed into WildFly, sometimes with a
module.xmldescribing their dependencies. - The runtime carried more than Keycloak needed. WildFly provides a full set of Jakarta EE services, and Keycloak only used part of them, which made the server heavier to start and run than a purpose-built application.
The Keycloak team supported both distributions for a short overlap, and the Keycloak 17 release notes said WildFly would be supported until June 2022. The Keycloak 20 release notes then removed the WildFly distribution entirely. A Keycloak server that still starts from standalone.xml is therefore on version 19 or older and no longer receives security fixes.
The modern approach: Keycloak on Quarkus
Quarkus is a Java framework built for containers and Kubernetes. Its main idea is to do as much work as possible at build time, such as scanning classes, wiring dependencies and resolving configuration, so that the application starts with less to do and uses less memory at runtime. Keycloak on Quarkus is a single application built this way rather than a deployment inside a general-purpose server.
When the Keycloak team made Quarkus the default in version 17, the release notes described the new distribution as “faster, leaner, and a lot easier to configure”. The practical differences you notice as an operator are these:
- One configuration model. Every option has the same name in
conf/keycloak.conf, on the command line (--db-url-host) and as an environment variable (KC_DB_URL_HOST), as described in the Keycloak configuration guide. - A build step. Some options are build options, which are baked into an optimized server image, while the rest are runtime options. Splitting them this way is what lets the server start faster, and the next section explains how it works.
- Secure defaults in production mode.
kc.sh start-devgives you a relaxed development server, whilekc.sh startrefuses to run until you configure a hostname and either HTTPS or a reverse proxy that terminates TLS. - A container-first workflow. The official container image and the Keycloak Operator for Kubernetes and OpenShift are built around the Quarkus distribution.
Because there is no longer a choice of distribution, you will not find a separate “Keycloak Quarkus” download. The server you get from keycloak.org, from the quay.io/keycloak/keycloak image, or from a managed service is the Quarkus-based one.
WildFly vs Quarkus: what changed in Keycloak
The table below maps the main differences between the two distributions. If you are reading an older tutorial, this is the quickest way to translate its instructions into what you would do on Keycloak 26.x.
| Area | WildFly distribution (default up to Keycloak 16, legacy until 19) | Quarkus distribution (default since Keycloak 17) |
|---|---|---|
| Configuration | standalone.xml / standalone-ha.xml, jboss-cli.sh |
conf/keycloak.conf, kc.sh options, KC_* environment variables |
| Default base path | /auth (for example /auth/realms/myrealm) |
/ (for example /realms/myrealm) |
| Custom providers | Deployed into WildFly, optionally as modules | Plain JAR files in the providers/ directory, followed by a build |
| Startup model | Application server boots, then deploys Keycloak | kc.sh build, then kc.sh start --optimized (or plain kc.sh start, which builds implicitly) |
| Initial admin user | add-user-keycloak.sh script |
KC_BOOTSTRAP_ADMIN_USERNAME and KC_BOOTSTRAP_ADMIN_PASSWORD (Keycloak 26+) |
| Clustering | Infinispan and JGroups configured as WildFly subsystems | Embedded Infinispan with the jdbc-ping stack by default since 26.1 |
| Kubernetes | Legacy operator | New operator with Keycloak and KeycloakRealmImport resources, plus client resources in recent 26.x releases |
| Support status | Removed in Keycloak 20 | The only distribution, current line is 26.x |
Configuration moved from XML to keycloak.conf
On Quarkus you configure Keycloak through options, and each option can come from four places, which are checked in order of priority: command-line parameters, environment variables, a configuration file (conf/keycloak.conf by default) and a Java KeyStore for sensitive values. A WildFly datasource block in standalone.xml becomes a few lines like these:
# conf/keycloak.conf
db=postgres
db-url-host=db.internal
db-username=keycloak
# keep db-password out of this file: use KC_DB_PASSWORD or a Java KeyStore
hostname=https://sso.example.com
proxy-headers=xforwarded
The same settings work as environment variables, which is how most container deployments pass them:
export KC_DB=postgres
export KC_DB_URL_HOST=db.internal
export KC_DB_USERNAME=keycloak
export KC_DB_PASSWORD='change-me'
export KC_HOSTNAME=https://sso.example.com
export KC_PROXY_HEADERS=xforwarded
There is no automatic converter from standalone.xml (the official migrating to Quarkus guide says the configuration cannot be migrated automatically), so each WildFly setting has to be mapped to its Keycloak option by hand. The migration guide walks through the common mappings, and the reverse proxy post covers the proxy and hostname options in detail.
The /auth path is gone by default
The Quarkus distribution serves everything from the root path, so https://sso.example.com/auth/realms/myrealm becomes https://sso.example.com/realms/myrealm. This affects every application’s issuer URL, discovery URL and redirect configuration, and it is a frequent cause of an upgraded server that starts cleanly while every client fails to log in. If you cannot update all clients at once, you can keep the old path with the http-relative-path option, which is a build option, so it has to be set when the server is built:
bin/kc.sh build --http-relative-path=/auth
bin/kc.sh start --optimized
The build step and optimized startup
Quarkus separates build options from runtime options. Build options, such as the database vendor, enabled features, health endpoints and http-relative-path, are resolved once by kc.sh build and stored in the server image. Runtime options, such as database passwords and hostnames, are read every time the server starts. If you skip the explicit build, kc.sh start checks for and runs a build at every startup, which is convenient but slower. The configuration guide recommends building once and then starting with --optimized in production:
bin/kc.sh build --db=postgres --health-enabled=true
bin/kc.sh start --optimized --hostname=https://sso.example.com
In a container you usually do the build in a multi-stage Dockerfile, so the image you deploy is already optimized and starts quickly.
Custom providers are plain JARs
A custom provider is your own Java code plugged into one of Keycloak’s Service Provider Interfaces (SPIs), for example a custom authenticator or a user storage provider. On Quarkus you package it as a JAR, copy it into the providers/ directory and run kc.sh build again, as described in the provider configuration guide. WildFly module descriptors and jboss-deployment-structure.xml files are no longer used. Older providers often need code changes as well, because the Keycloak APIs they call have changed across versions, and Keycloak 22 moved from Java EE (javax.* packages) to Jakarta EE (jakarta.* packages) as part of its upgrade to Quarkus 3.
Creating the first admin user
The WildFly-era add-user-keycloak.sh script does not exist on Quarkus. On Keycloak 26 you create the first admin either from the welcome page over a local connection or with the KC_BOOTSTRAP_ADMIN_USERNAME and KC_BOOTSTRAP_ADMIN_PASSWORD environment variables on first startup. The older KEYCLOAK_ADMIN and KEYCLOAK_ADMIN_PASSWORD variables, which many Docker tutorials still use, were deprecated in Keycloak 26.0, and the same release added a bootstrap admin and recovery guide for regaining access when every admin is locked out.
Why move off a WildFly-based Keycloak now
If you are still on a WildFly-based Keycloak, the main reason to move is that your version has been out of support for years, and every fix since then has shipped only for the Quarkus distribution.
- Security fixes. Keycloak publishes fixes for vulnerabilities in new releases on the current line, and none of them reach Keycloak 19 or older. An identity server is one of the most exposed parts of your stack, so running an unpatched one is a real risk.
- Protocol and feature work. Everything added since Keycloak 20 exists only on Quarkus, including passkeys (a preview from Keycloak 23 and fully supported since 26.4), organizations for B2B multi-tenancy (supported from Keycloak 26.0) and standard token exchange (Keycloak 26.2). Our token exchange explainer covers the standard exchange, which only exists on these Quarkus-based releases.
- Java support. With WildFly removed, Keycloak 20 dropped OpenJDK 8 for the server and Keycloak 22 dropped Java 11, so an old Keycloak also pins you to an old Java runtime.
- Simpler operations. One options model, container images built for the job and an operator for Kubernetes make Keycloak easier to automate than the WildFly setup was.
Resource usage is also easier to plan on a modern Keycloak. Keycloak’s own sizing guidance, summarized in our production sizing post, is based on login rates rather than user counts: about one vCPU per 15 password logins per second, plus 150% CPU headroom, and roughly 1250 MB of base memory per pod.
Making the transition: what you need to know
Moving from WildFly to Quarkus is a distribution migration, and it usually comes together with a version upgrade. Your realm data lives in the database, and Keycloak migrates the database schema automatically when the new version first starts, so the work is mostly about configuration, URLs and extensions. A typical sequence looks like this:
- Back up the database and plan a maintenance window, because all nodes running the old version must be shut down before the new one migrates the schema.
- Pick the target version and read the release notes and upgrade guide between your version and it. Our Keycloak upgrade guide lists the breaking changes along the way.
- Translate your configuration from
standalone.xmlintokeycloak.confoptions orKC_*variables, including the database, hostname, proxy and cache settings. - Decide what to do about
/auth. Either update every client’s issuer, discovery and redirect URLs, or build with--http-relative-path=/authas a temporary bridge. - Rebuild custom providers and themes against the target version’s APIs, then place the JARs in
providers/and runkc.sh build. - Add the build step to your pipeline (a multi-stage Dockerfile or CI job) and start production nodes with
--optimized. - Replace admin bootstrap scripts with the
KC_BOOTSTRAP_ADMIN_*variables, and move Kubernetes deployments to the current Keycloak Operator. - Test logins for every client in a staging environment against a copy of production data before you cut over.
The detailed runbook, with configuration mappings and a cutover checklist, is in our WildFly to Quarkus migration guide.
Running Keycloak without managing the distribution
If you would rather not own the build step, cluster configuration and upgrades at all, Skycloak runs current Keycloak releases for you as a managed service. You keep standard Keycloak realms, clients and protocols, and you can still add custom providers through our extensions feature. If you are moving from a self-hosted server, our post on migrating self-hosted Keycloak to Skycloak explains how realm data comes across.
Frequently asked questions
Is Keycloak built on Quarkus?
Yes. Since Keycloak 17 the default distribution has been built on Quarkus, and since Keycloak 20 it is the only distribution. Every current release, including the 26.x line, is a Quarkus application, so “Keycloak Quarkus” and “Keycloak” now mean the same server.
Is Keycloak.X the same as Keycloak Quarkus?
Yes. Keycloak.X was the name of the Quarkus-based preview distribution, first shipped in Keycloak 12 alongside the WildFly server. It became the default distribution in Keycloak 17, so older articles and GitHub issues that mention Keycloak.X are describing the server you run today.
Does Keycloak still use the /auth path?
Not by default. The Quarkus distribution serves endpoints from the root, such as /realms/myrealm, instead of /auth/realms/myrealm. You can restore the old prefix with the http-relative-path build option, which is useful as a bridge while you update client configurations.
What is the difference between Quarkus and WildFly?
WildFly is a full Java application server that hosts many applications and provides shared services for them. Quarkus is a framework for building a single, self-contained Java application, and it moves much of the startup work to build time. For Keycloak, that change brought a simpler configuration model, a build step and container-friendly startup.
Summary
Keycloak on Quarkus is the only distribution that exists today, because the WildFly distribution was replaced in version 17 and removed in version 20, and the current 26.x releases run only on Quarkus. If you are reading old instructions, translate standalone.xml settings into keycloak.conf options, drop /auth from your URLs, package providers as JARs and add a build step. If you are still running a WildFly-based server, plan the migration now, because it no longer receives security fixes. If you would rather skip the operational work, you can compare Skycloak plans, estimate costs with our pricing calculator, and let us run Keycloak for you.