Upgrade from 15 to 21

Hi, we are planning to upgrade from v15 to v21, any advice? possible problem that we can face?

Thanks in advance.

Backup your database and try it on another instance to make sure you don’t encounter problems. Generally, Keycloak does okay with upgrades, but big version jumps can cause problems based on your data. If you encounter an issue, you might want to upgrade one major version at a time. Beyond that, if you encounter specific problems, post your entire findings here so that we can help you.

1 Like

Hello there,
Is there any clear description in upgrade from x to y version - major to major ? I’m running 15.x on Docker and would like to migrate to much higher version ( security etc ) but I don’t see recomendations what env. variables should be changed and etc. There are no infos on the docs (Running Keycloak in a container - Keycloak) what variables should be changed. Is there any quite clear source page where dummies will be guided ? Thanks for any help and cheers !

Each migration section in this document details what has to be done. You really need to go through each version to understand what has changed.
https://www.keycloak.org/docs/latest/upgrading/index.html#migration-changes

Hello xgp,
Thank you for reply. I checked the docs and I know what has been changed but still I’m struggle with upgrade or even migration process. As I follow Running Keycloak in a container - Keycloak set up all the env variables it doesn’t work. I would like to even create empty environment to export/import data/realms but still without results. I checked yt for some tutorials and mostly there is a server installation *.rpm etc 
 no containers. Maybe some of you have a ready cmd: to run the postgres db and keycloak which is capable to store data in this db ?
Cheers !

As I follow Running Keycloak in a container - Keycloak set up all the env variables it doesn’t work.

I CAN’T PRINT!

How about a little more context? Without knowing what you’re trying or what the errors are, I don’t think anyone here can help you.

Hello XGP,

I have used the statements based on the docu:

My db is correct as I assume:

# my db: postgres 15

root@oodc-dev:/home/vagrant/ca# psql -h 192.168.56.34 -U keycloak -p 5432 -d keycloak
Password for user keycloak:
psql (14.13 (Ubuntu 14.13-0ubuntu0.22.04.1), server 15.9 (Debian 15.9-1.pgdg120+1))
WARNING: psql major version 14, server major version 15.
         Some psql features might not work.
Type "help" for help.

root@oodc-dev:/home/vagrant/ca# psql -h localhost -U keycloak -p 5432 -d keycloak
Password for user keycloak:
psql (14.13 (Ubuntu 14.13-0ubuntu0.22.04.1), server 15.9 (Debian 15.9-1.pgdg120+1))
WARNING: psql major version 14, server major version 15.
         Some psql features might not work.
Type "help" for help.

psql -h 192.168.56.34 -U keycloak -p 5432 -d keycloak


keycloak=# \l
                              List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges
-----------+-------+----------+------------+------------+--------------------
 admindb   | admin | UTF8     | en_US.utf8 | en_US.utf8 |
 keycloak  | admin | UTF8     | en_US.utf8 | en_US.utf8 | =Tc/admin         +
           |       |          |            |            | admin=CTc/admin   +
           |       |          |            |            | keycloak=CTc/admin

and trying to run container

docker run --name mykeycloak -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me -e KC_LOG_LEVEL=trace quay.io/keycloak/keycloak:21.0.0 start --db=postgres --features=token-exchange --db-url=jdbc:postgresql://192.168.56.34:5432/keycloak --db-username=keycloak --db-password=keycloakpassword --https-key-store-file=/home/vagrant/ca/certificate.pem --https-key-store-password=mypass --hostname=192.168.56.34

I genereate self signed certificates like this:

openssl genpkey -algorithm RSA -out private_key.pem -aes256
openssl req -x509 -key private_key.pem -out certificate.pem -days 365

As a Common Name I used “localhost” Maybe this is the issue here ?
I would like to run the verions of 21 and try to import the data/realms from 15. Is that good idea as this is my test environment ( database has been backed up )
Cheers

If you don’t want to go through the documentation, check out this GPT we cooked up: ChatGPT - Keycloak Upgrade Assistant

You can ask it about the steps in order to go from 15 to 21.

If you see something fishy, don’t hesitate to let me know.

1 Like

Hello Gmolaire, Thank you. The guideline form gpt assistance are generated for noncontainer instance of keycloak. I have checket the steps from chat and from docs - nice wrap up !

Stop the Keycloak Server:
Skopiuj kod
./bin/kc.sh stop
Replace the Keycloak Installation:
Extract the Keycloak 16.1.1 archive.
Copy your existing configuration and custom files (e.g., themes) into the new Keycloak instance.
Run the Database Migration: Keycloak automatically applies database updates on startup. Ensure proper permissions for the database user.
Start the Server:
bash
./bin/kc.sh start

Maybe I should try do install noncontainer instance on host. Do upgrade procedure and extract what env. variables are used etc. I this moment I see issue “like above” with ssl certificates.
Trying with dev option in container it work but non dev = prod getting error’s like mentioned before.
Regards

You are possibly running into problems due to run kc.sh build before kc.sh start starting with keycloak 16 (change to quarkus as server base).
See Migrating to Quarkus distribution - Keycloak

Really,really carefully read all the upgrade guides for each version in between (note, your target version is already outdated as well, current is 26.0.x),

Hello bpedersen2,
I will try without build step before.
Cheers

Hello Ther,
Long time but still trying.
Now I can’t connect to the DB:

2025-02-03 13:56:45,241 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (production) mode
2025-02-03 13:56:45,241 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to obtain JDBC connection
2025-02-03 13:56:45,242 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2025-02-03 13:56:45,242 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection refused
2025-02-03 13:56:45,242 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the ‘–verbose’ option. Also you can use ‘–help’ to see the details about the usage of the particular command.
2025-02-03 13:57:03,825 INFO [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: , Hostname: localhost, Strict HTTPS: true, Path: , Strict BackChannel: false, Admin URL: , Admin: , Port: -1, Proxied: false
2025-02-03 13:57:05,531 WARN [io.quarkus.agroal.runtime.DataSources] (main) Datasource enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2025-02-03 13:57:05,881 WARN [io.agroal.pool] (agroal-11) Datasource ‘’: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2025-02-03 13:57:05,883 WARN [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread: keycloak-default) HHH000342: Could not obtain connection to query metadata: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:319)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.(PgConnection.java:247)
at org.postgresql.Driver.makeConnection(Driver.java:434)
at org.postgresql.Driver.connect(Driver.java:291)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:681)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:229)
at org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:103)
at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:49)
at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:35)
at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:535)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:516)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at org.postgresql.core.PGStream.createSocket(PGStream.java:241)
at org.postgresql.core.PGStream.(PGStream.java:98)
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:109)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:235)

 17 more

2025-02-03 13:57:06,563 INFO [org.infinispan.SERVER] (keycloak-cache-init) ISPN005054: Native IOUring transport not available, using NIO instead: io.netty.incubator.channel.uring.IOUring
2025-02-03 13:57:06,575 WARN [io.agroal.pool] (agroal-11) Datasource ‘’: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2025-02-03 13:57:06,644 WARN [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2025-02-03 13:57:06,673 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2025-02-03 13:57:06,706 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller ‘org.infinispan.jboss.marshalling.core.JBossUserMarshaller’
2025-02-03 13:57:07,044 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000088: Unable to use any JGroups configuration mechanisms provided in properties {}. Using default JGroups configuration!
2025-02-03 13:57:07,141 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000078: Starting JGroups channel ISPN
2025-02-03 13:57:07,145 INFO [org.jgroups.JChannel] (keycloak-cache-init) local_addr: 5ff41744-81b1-4f01-9c43-7a565e626958, name: 649f1fb4b388-60916
2025-02-03 13:57:07,151 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1MB, but the OS only allocated 212.99KB
2025-02-03 13:57:07,151 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 20MB, but the OS only allocated 212.99KB
2025-02-03 13:57:07,152 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1MB, but the OS only allocated 212.99KB
2025-02-03 13:57:07,152 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 25MB, but the OS only allocated 212.99KB
2025-02-03 13:57:07,163 INFO [org.jgroups.protocols.FD_SOCK2] (keycloak-cache-init) server listening on *.43694
2025-02-03 13:57:09,175 INFO [org.jgroups.protocols.pbcast.GMS] (keycloak-cache-init) 649f1fb4b388-60916: no members discovered after 2003 ms: creating cluster as coordinator
2025-02-03 13:57:09,185 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000094: Received new cluster view for channel ISPN: [649f1fb4b388-60916|0] (1) [649f1fb4b388-60916]
2025-02-03 13:57:09,191 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000079: Channel ISPN local address is 649f1fb4b388-60916, physical addresses are [172.17.0.5:59230]
2025-02-03 13:57:09,630 INFO [org.infinispan.CLUSTER] (main) ISPN000080: Disconnecting JGroups channel ISPN
2025-02-03 13:57:09,777 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (production) mode
2025-02-03 13:57:09,778 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to obtain JDBC connection
2025-02-03 13:57:09,778 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2025-02-03 13:57:09,778 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection refused
2025-02-03 13:57:09,778 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the ‘–verbose’ option. Also you can use ‘–help’ to see the details about the usage of the particular command.

starting container:

docker run -d --name keycloak -p 8443:8443 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin123 -e KC_DB_URL=“jdbc:postgresql://localhost:5432/keycloak” -e KC_DB_USERNAME=keycloak -e KC_DB_PASSWORD=keycloakpassword -v /opt/keycloak/certs/keystore.jks:/opt/keycloak/conf/keystore.jks Quay start --hostname=localhost --https-key-store-file=/opt/keycloak/conf/keystore.jks --https-key-store-password=keycertpass

root@vm1:/opt/keycloak/certs# psql -h localhost -U keycloak -d keycloak_db
Password for user keycloak:
psql (14.15 (Ubuntu 14.15-0ubuntu0.22.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type “help” for help.

keycloak_db=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-------------±----------±---------±------------±------------±----------------------
keycloak_db | keycloak | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
mass_db | maas_user | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
postgres | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
template0 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)

keycloak_db=# SELECT rolname, rolsuper, rolcreaterole, rolcreatedb FROM pg_roles WHERE rolname = ‘keycloak’;
rolname | rolsuper | rolcreaterole | rolcreatedb
----------±---------±--------------±------------
keycloak | t | f | f
(1 row)

root@vm1:/opt/keycloak/certs# pg_isready -h localhost -p 5432
localhost:5432 - accepting connections

What can be the reason here ? Does someone faced such an issue ?
Regards

Hello @miudinho, the reason here is that your Keycloak container try to reach the db using “localhost”, but from the container point of view, localhost is the container itself, not your host.

The default docker network driver is “bridge” (it isolate the networks of the container and the Docker host). With this default driver, to reach you docker host, I think you can use the IP of the “docker0” interface (use ifconfig docker0 on your host to find it).
If you really want to use localhost:5432 to reach your db from the container, you could use the “host” network driver (see Networking | Docker Docs for more information).

Dear skydrinker-tox, Thank you for pointig me out. It was that. After changing the localhost to IP adress of the host which hosted docker it starts. Now I need to fix some schem/role in postgres DB and I hope it will finisch succesully.
Many thanks and regards

1 Like