Short outage method: Stop → Backup → Upgrade → Start
Example upgrade: 26.4.6 → 26.5.2
This post upgrades a Keycloak tarball installation that runs as a non-root user and is managed by systemd, using MariaDB as the database backend.
This Post Is Based On
If you don’t already have a working Keycloak (tarball + systemd) setup with MariaDB and NGINX SSL termination, follow this first:
Assumptions
- Current install path:
/opt/keycloak - Keycloak runs as user:
keycloak - systemd unit:
/etc/systemd/system/keycloak.service - Database name:
keycloak(MariaDB) - You can accept a short outage
- Sanity check (must be a real directory)
ls -ld /opt/keycloakIf the output contains ->, /opt/keycloak is a symlink. This in-place upgrade flow doesn’t apply; convert it to a directory first or use a symlink cutover method.
- Check the current version
/opt/keycloak/bin/kc.sh --versionExample:
Keycloak 26.4.6
JVM: 21.x- Stop Keycloak (planned short outage)
sudo systemctl stop keycloak
sudo systemctl status keycloak --no-pagerNote: Keycloak often exits with code 143 (SIGTERM). Some systemd units show this as “failed (exit-code)” even when shutdown is clean.
- Backup the MariaDB database (Keycloak stopped)
Dump the DB to /root
Redirection must run as root, so use sudo sh -c:
sudo sh -c 'mysqldump --single-transaction --routines --triggers keycloak > /root/keycloak_db_$(date +%F).sql'Verify the dump exists
sudo sh -c 'ls -lh /root/keycloak_db_*.sql | tail -n 1'- Backup the Keycloak directory
sudo tar -C /opt -czf /root/keycloak_dir_$(date +%F).tar.gz keycloakVerify:
sudo sh -c 'ls -lh /root/keycloak_dir_*.tar.gz | tail -n 1'- Download and extract the new Keycloak release
Set the target version (example: 26.5.2):
export KC_VER=26.5.2Download + extract + move into /opt:
cd /tmp
wget -O keycloak-${KC_VER}.tar.gz \
https://github.com/keycloak/keycloak/releases/download/${KC_VER}/keycloak-${KC_VER}.tar.gz
tar -xzf keycloak-${KC_VER}.tar.gz
sudo mv keycloak-${KC_VER} /opt/keycloak-${KC_VER}
sudo chown -R keycloak:keycloak /opt/keycloak-${KC_VER}- Copy config and customizations
- Copy
keycloak.conf
sudo cp /opt/keycloak/conf/keycloak.conf /opt/keycloak-${KC_VER}/conf/keycloak.conf
sudo chown keycloak:keycloak /opt/keycloak-${KC_VER}/conf/keycloak.conf- Copy providers (JARs) if you have any
if [ -d /opt/keycloak/providers ]; then
sudo rsync -a /opt/keycloak/providers/ /opt/keycloak-${KC_VER}/providers/
sudo chown -R keycloak:keycloak /opt/keycloak-${KC_VER}/providers
fi- Copy themes (if any)
if [ -d /opt/keycloak/themes ]; then
sudo rsync -a /opt/keycloak/themes/ /opt/keycloak-${KC_VER}/themes/
sudo chown -R keycloak:keycloak /opt/keycloak-${KC_VER}/themes
fi- Build the new Keycloak installation
This is recommended for tarball installs (especially when using providers/themes):
sudo -u keycloak /opt/keycloak-${KC_VER}/bin/kc.sh build- Switch
/opt/keycloakto the new version
Rename the old install directory (example: 26.4.6):
sudo mv /opt/keycloak /opt/keycloak-26.4.6Point /opt/keycloak to the new version:
sudo mv /opt/keycloak-${KC_VER} /opt/keycloak
sudo chown -R keycloak:keycloak /opt/keycloak- Update systemd to start
--optimized
Edit the service file:
sudo vi /etc/systemd/system/keycloak.serviceExample unit:
[Unit]
Description=Keycloak Server
After=network.target mariadb.service
Requires=mariadb.service
[Service]
User=keycloak
Group=keycloak
WorkingDirectory=/opt/keycloak
ExecStart=/opt/keycloak/bin/kc.sh start --optimized --log=console,file --log-file=/opt/keycloak/logs/keycloak.log
Restart=always
SuccessExitStatus=143
Environment="JAVA_OPTS=-Xms256m -Xmx512m"
[Install]
WantedBy=multi-user.targetReload systemd:
sudo systemctl daemon-reloadEnsure the log directory exists:
sudo install -d -o keycloak -g keycloak /opt/keycloak/logsStart Keycloak:
sudo systemctl start keycloak
sudo systemctl status keycloak --no-pager- Verify the upgrade
- Confirm version
/opt/keycloak/bin/kc.sh --versionExample:
Keycloak 26.5.2
JVM: 21.0.9- Check logs (current boot only)
sudo journalctl -u keycloak -b --no-pager | tail -n 200Or last 5 minutes:
sudo journalctl -u keycloak --since "5 minutes ago" --no-pagerDid this guide save you time?
Support this site