Problem: 50keycloak.inst fails with crashing apache

#Problem:
50keycloak.inst fails with crashing apache.
Installation of keycloak to migrate the simplesamlphp to keycloak fails during joinscript. The join.log shows the following:

RUNNING 50keycloak.inst
2026-06-15 10:49:50.640211394+02:00 (in joinscript_init)
Create ucs/web/overview/entries/admin/keycloak/description/de
Create ucs/web/overview/entries/admin/keycloak/description
Create ucs/web/overview/entries/admin/keycloak/label
Create ucs/web/overview/entries/admin/keycloak/link
Create ucs/web/overview/entries/admin/keycloak/icon
Create ucs/web/overview/entries/admin/keycloak/link-target
Module: create_portal_entries
No modification: cn=keycloak,cn=entry,cn=portals,cn=univention,dc=sun,dc=schein,dc=me
Object exists: cn=ldapacl,cn=univention,dc=sun,dc=schein,dc=me
INFO: No change of core data of object 67keycloak.
No modification: cn=67keycloak,cn=ldapacl,cn=univention,dc=sun,dc=schein,dc=me

Waiting for activation of the extension object 67keycloak: OK
Object exists: cn=services,cn=univention,dc=sun,dc=schein,dc=me
Object created: cn=keycloak DB,cn=services,cn=univention,dc=sun,dc=schein,dc=me
Object modified: cn=ucs01,cn=dc,cn=computers,dc=sun,dc=schein,dc=me
File: /etc/apache2/sites-available/univention-keycloak.conf
File: /etc/apache2/sites-available/univention-keycloak.conf
Enabling site univention-keycloak.
To activate the new configuration, you need to run:
  systemctl reload apache2
Job for apache2.service failed because the control process exited with error code.
See "systemctl status apache2.service" and "journalctl -xe" for details.
Multifile: /etc/postgresql/15/main/pg_hba.conf
Warning: The file '/etc/postgresql/11/main/pg_hba.conf' is not registered as an UCR template.
Multifile: /etc/postgresql/15/main/pg_hba.conf
Adding A record "ucs-sso-ng 10.200.43.30" to zone sun.schein.me...
done
15.06.26 10:49:57.893  DEBUG_INIT
15.06.26 10:49:57.895  DEBUG_EXIT
waiting for ucs-sso-ng.sun.schein.de ...
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 162, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw)
  File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 80, in create_connection
    raise err
  File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 70, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

Here we see, that the apache does not come up, after the configuration for keycloak was inserted.
After fixing that (see investigation part, the joinscripts got an other failure)

Object exists: cn=ldapacl,cn=univention,dc=sun,dc=schein,dc=me
INFO: No change of core data of object 67keycloak.
No modification: cn=67keycloak,cn=ldapacl,cn=univention,dc=sun,dc=schein,dc=me

Waiting for activation of the extension object 67keycloak: OK
File: /etc/apache2/sites-available/univention-keycloak.conf
File: /etc/apache2/sites-available/univention-keycloak.conf
Enabling site univention-keycloak.
To activate the new configuration, you need to run:
  systemctl reload apache2
Multifile: /etc/postgresql/15/main/pg_hba.conf
Warning: The file '/etc/postgresql/11/main/pg_hba.conf' is not registered as an UCR template.
Multifile: /etc/postgresql/15/main/pg_hba.conf
Adding A record "ucs-sso-ng 10.200.43.30" to zone sun.schein.me...
done
16.06.26 16:37:51.935  DEBUG_INIT
16.06.26 16:37:51.938  DEBUG_EXIT
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/contrib/pyopenssl.py", line 453, in wrap_socket
    cnx.do_handshake()
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1915, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1647, in _raise_ssl_error
    _raise_current_error()
  File "/usr/lib/python3/dist-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')]

Investigation:

To check why apache was not starting up anymore a view of the configuration file showed, that the certificate line were missing:

SSLCertificateFile /etc/univention/ssl/ucs-sso-ng.sun.schein.me/cert.pem
SSLCertificateKeyFile /etc/univention/ssl/ucs-sso-ng.sun.schein.me/private.key

cat /etc/apache2/sites-available/univention-keycloak.conf
[...]
<VirtualHost *:443>
    ServerName ucs-sso-ng.sun.schein.me

    SSLEngine on
    SSLProxyEngine on
    SSLCertificateFile /etc/univention/ssl/ucs-sso-ng.sun.schein.me/cert.pem
    SSLCertificateKeyFile /etc/univention/ssl/ucs-sso-ng.sun.schein.me/private.key
    SSLCACertificateFile /etc/univention/ssl/ucsCA/CAcert.pem
[...]

After fixing apache (see solution part) the next error in the logfile happens during the call of:

univention-keycloak realm get
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/contrib/pyopenssl.py", line 453, in wrap_socket
    cnx.do_handshake()
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1915, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1647, in _raise_ssl_error
    _raise_current_error()
  File "/usr/lib/python3/dist-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')]

During handling of the above exception, another exception occurred:
[...]

Here we can first check the url.

curl -v -l ucs-sso-ng.sun.schein.me
*   Trying 10.200.43.30...
* TCP_NODELAY set
* Connected to ucs-sso-ng.sun.schein.me (10.200.43.30) port 80 (#0)
> GET / HTTP/1.1
> Host: ucs-sso-ng.sun.schein.me
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Wed, 17 Jun 2026 07:21:07 GMT
< Server: Apache/2.4.59 (Univention)
< Location: https://ucs-sso-ng.sun.schein.me/
< Content-Length: 347
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://ucs-sso-ng.sun.schein.me/">here</a>.</p>
<hr>
<address>Apache/2.4.59 (Univention) Server at ucs-sso-ng.sun.schein.me Port 80</address>
</body></html>
* Connection #0 to host ucs-sso-ng.sun.schein.me left intact

Because we got a 301 redirect, we need to follow the request and get

root@ucs01:~/univention-support# curl -v -L ucs-sso-ng.sun.schein.me
*   Trying 10.200.43.30...
* TCP_NODELAY set
* Connected to ucs-sso-ng.sun.schein.me (10.200.43.30) port 80 (#0)
> GET / HTTP/1.1
> Host: ucs-sso-ng.sun.schein.me
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Wed, 17 Jun 2026 07:21:22 GMT
< Server: Apache/2.4.59 (Univention)
< Location: https://ucs-sso-ng.sun.schein.me/
< Content-Length: 347
< Content-Type: text/html; charset=iso-8859-1
<
* Ignoring the response-body
* Connection #0 to host ucs-sso-ng.sun.schein.me left intact
* Clear auth, redirects to port from 80 to 443
* Issue another request to this URL: 'https://ucs-sso-ng.sun.schein.me/'
*   Trying 10.200.43.30...
* TCP_NODELAY set
* Connected to ucs-sso-ng.sun.schein.me (10.200.43.30) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 1
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

This indicates, that the ucsCA may not be present in the certificate store in /etc/ssl/certs or the certificate is signed with an older or newer ucsCA certificate. So the CA and cert signature are not matching.

Solution:

For apache crashing issue:

The certificate and key come from:

ucr get keycloak/apache2/ssl/certificate
ucr get keycloak/apache2/ssl/key

If these ucr variables are empty, than the certificate in /etc/univention/ssl/<sso_fqdn>/cert.pem is used.
In this case these directory with its cert and key was removed. With ucs 5.0-8 we created these certificates va default, but never check them during the joinscript. With 5.2-x the 49univention-keycloak-client.inst creates the certificates.
So if you are not using your own certificate you can generate the certificates like this:

fqdn="$(echo "$(ucr get ucs/server/sso/uri)" | sed -E 's|^[a-zA-Z]+://([^/]+).*|\1|')"
univention-certificate new -name "$fqdn" -days 1825

The ucr variables does not need to be defined, if you are using our default ucs-sso-ng.domain.name

For the certificate issue:

If the ucsCA is missing in the certificate store you can simply add the certificate with
update-ca-certificate --fresh

In some cases, apache has not loaded the new certificate. If the error above persists, it is a good idea to reload apache.
systemctl reload apache2