diff --git a/files/org.postgresql.module.xml b/files/org.postgresql.module.xml
deleted file mode 100644
index 1d6b000faf657c2bfaca3b0dc63ea81a77bbc5bf..0000000000000000000000000000000000000000
--- a/files/org.postgresql.module.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" ?>
-<module xmlns="urn:jboss:module:1.3" name="org.postgresql">
-
-    <resources>
-        <resource-root path="postgresql.jar"/>
-    </resources>
-
-    <dependencies>
-        <module name="javax.api"/>
-        <module name="javax.transaction.api"/>
-    </dependencies>
-</module>
diff --git a/handlers/main.yml b/handlers/main.yml
index 07d700ffabc550d71d48802e16321a83fec69984..97c3ac86cf83a9f6e53c1a1f6a0c81a9544b44a8 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,4 +1,10 @@
 ---
+- name: build keycloak
+  ansible.builtin.command: bin/kc.sh build
+  args:
+    chdir: "{{ keycloak_jboss_home }}"
+  become_user: keycloak
+
 - name: restart keycloak
   ansible.builtin.systemd:
     daemon_reload: true
diff --git a/tasks/main.yml b/tasks/main.yml
index 791df20266309f0417c8625aed25e3d79570ce1f..b6fa97801c67f55ff799b166d68eccedc738c66f 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -14,8 +14,7 @@
   ansible.builtin.apt:
     name:
       - zulu-11
-      - libpostgresql-jdbc-java
-      - python-lxml
+      - git
     state: present
     update_cache: true
     cache_valid_time: 3600
@@ -46,55 +45,24 @@
     group: root
     remote_src: true
   when: not keycloak_directory.stat.exists
-  notify: restart keycloak
+  notify:
+    - build keycloak
+    - restart keycloak
 
-- name: Set folder permissions
+- name: Create keycloak log directory
   ansible.builtin.file:
+    state: directory
+    path: "/car/log/keycloak"
     owner: keycloak
     group: keycloak
-    path: "{{ keycloak_jboss_home }}/standalone"
-    recurse: true
-
-- name: Create postgresql module folder in keycloak
-  ansible.builtin.file:
-    path: "{{ keycloak_jboss_home }}/modules/system/layers/keycloak/org/postgresql/main/"
-    state: directory
     mode: 0755
 
-- name: Add postgresql jar to keycloak
+- name: Set folder permissions
   ansible.builtin.file:
-    src: /usr/share/java/postgresql.jar
-    dest: "{{ keycloak_jboss_home }}/modules/system/layers/keycloak/org/postgresql/main/postgresql.jar"
-    state: link
-
-- name: Add postgresql module definition to keycloak
-  ansible.builtin.copy:
-    src: org.postgresql.module.xml
-    dest: "{{ keycloak_jboss_home }}/modules/system/layers/keycloak/org/postgresql/main/module.xml"
-    mode: 0644
-
-- name: Check if postgresql module is already in JBoss
-  ansible.builtin.xml:
-    path: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
-    xpath: /x:server/x:profile/y:subsystem/y:datasources/y:drivers/y:driver[@name='postgresql']
-    count: true
-    namespaces:
-      x: urn:jboss:domain:19.0
-      y: urn:jboss:domain:datasources:6.0
-  register: keycloak_postgresql_module_installed
-
-- name: Install postgresql module in JBoss
-  ansible.builtin.xml:
-    path: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
-    xpath: /x:server/x:profile/y:subsystem/y:datasources/y:drivers
-    add_children:
-      - <driver name="postgresql" module="org.postgresql"><xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class></driver>
-    input_type: xml
-    namespaces:
-      x: urn:jboss:domain:19.0
-      y: urn:jboss:domain:datasources:6.0
-  notify: restart keycloak
-  when: keycloak_postgresql_module_installed.count == 0
+    owner: keycloak
+    group: keycloak
+    path: "{{ keycloak_jboss_home }}"
+    recurse: true
 
 - name: Create user and db on server
   ansible.builtin.import_role:
@@ -105,37 +73,16 @@
       password: "{{ keycloak_pgdb_pass }}"
     db_host: "{{ keycloak_pgdb_host }}"
 
-- name: Add postgresql config in JBoss
-  ansible.builtin.xml:
-    path: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
-    xpath: /x:server/x:profile/y:subsystem/y:datasources/y:datasource[@pool-name='KeycloakDS']
-    set_children:
-      - "<connection-url>jdbc:postgresql://{{ hostvars[keycloak_pgdb_host]['ansible_default_ipv4']['address'] }}/{{ keycloak_pgdb_user }}</connection-url>"
-      - <driver>postgresql</driver>
-      - <pool><max-pool-size>10</max-pool-size></pool>
-      - "<security><user-name>{{ keycloak_pgdb_user }}</user-name><password>{{ keycloak_pgdb_pass }}</password></security>"
-      - <validation>
-        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"></valid-connection-checker>
-        <validate-on-match>true</validate-on-match>
-        <background-validation>false</background-validation>
-        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
-        </validation>
-    input_type: xml
-    namespaces:
-      x: urn:jboss:domain:19.0
-      y: urn:jboss:domain:datasources:6.0
-  notify: restart keycloak
-
-- name: Make keycloak reverse proxy aware
-  ansible.builtin.xml:
-    path: "{{ keycloak_jboss_home }}/standalone/configuration/standalone.xml"
-    xpath: /x:server/x:profile/y:subsystem/y:server/y:http-listener
-    attribute: proxy-address-forwarding
-    value: "{{ keycloak_proxy_address_forwarding }}"
-    namespaces:
-      x: urn:jboss:domain:19.0
-      y: urn:jboss:domain:undertow:12.0
-  notify: restart keycloak
+- name: Copy Keycloak config file
+  ansible.builtin.template:
+    src: keycloak.conf.j2
+    dest: "{{ keycloak_jboss_home }}/conf/keycloak.conf"
+    owner: keycloak
+    group: keycloak
+    mode: 0644
+  notify:
+    - build keycloak
+    - restart keycloak
 
 - name: Install systemd unit file
   ansible.builtin.template:
@@ -144,26 +91,38 @@
     mode: 0644
   notify: restart keycloak
 
-- name: Add master realm admin to keycloak
-  ansible.builtin.command: "{{ keycloak_jboss_home }}/bin/add-user-keycloak.sh -r master -u {{ keycloak_master_realm_admin_user }} -p {{ keycloak_master_realm_admin_pass }}"
-  args:
-    creates: "{{ keycloak_jboss_home }}/standalone/configuration/keycloak-add-user.json"
-  notify: restart keycloak
+- name: Inform about setting up admin user
+  ansible.builtin.debug:
+    msg: |
+      You can now set up the admin user by accessing Keycloak on localhost:8080
+      Use these credentials:
+      USER: {{ keycloak_master_realm_admin_user }}
+      PASSWORD: {{ keycloak_master_realm_admin_pass }}
   when: not keycloak_directory.stat.exists
 
+- name: Suppress Git safe directory warnings
+  community.general.git_config:
+    name: safe.directory
+    scope: global
+    value: "*"
+
 - name: Install custom keycloak themes
   ansible.builtin.git:
     dest: "{{ keycloak_jboss_home }}/themes/{{ item.name }}"
     repo: "{{ item.repository }}"
     version: master
   with_items: "{{ keycloak_custom_themes }}"
-  notify: restart keycloak
+  notify:
+    - build keycloak
+    - restart keycloak
 
 - name: Install custom keycloak deployments
   ansible.builtin.get_url:
-    dest: "{{ keycloak_jboss_home }}/standalone/deployments/{{ item.name }}"
+    dest: "{{ keycloak_jboss_home }}/providers/{{ item.name }}"
     url: "{{ item.url }}"
     force: true
     mode: 644
   with_items: "{{ keycloak_custom_deployments }}"
-  notify: restart keycloak
+  notify:
+    - build keycloak
+    - restart keycloak
diff --git a/templates/keycloak.conf.j2 b/templates/keycloak.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8450374307278f374191755861406d5e9e4734ac
--- /dev/null
+++ b/templates/keycloak.conf.j2
@@ -0,0 +1,20 @@
+# Basic settings for running in production. Change accordingly before deploying the server.
+
+# Database
+db=postgres
+db-username={{ keycloak_pgdb_user }}
+db-password={{ keycloak_pgdb_pass }}
+db-url-database={{ keycloak_pgdb_user }}
+db-url-host={{ hostvars[keycloak_pgdb_host]['ansible_default_ipv4']['address'] }}
+
+# Observability
+
+# If the server should expose healthcheck endpoints.
+health-enabled=true
+# If the server should expose metrics endpoints.
+metrics-enabled=true
+
+# HTTP
+proxy=edge
+hostname={{ keycloak_hostname }}
+
diff --git a/templates/keycloak.service.j2 b/templates/keycloak.service.j2
index 8bdc06a3733ceb7675ade09edaffe6aa2ed1c6dd..8ec1a5c4075874cbd6bfd757e2d134b9e525eed4 100644
--- a/templates/keycloak.service.j2
+++ b/templates/keycloak.service.j2
@@ -1,21 +1,38 @@
 [Unit]
-Description=Keycloak
-After=network.target
+Description=Keycloak server
+After=network-online.target
+Wants=network-online.target systemd-networkd-wait-online.service
 
 [Service]
-Type=simple
-Environment=LAUNCH_JBOSS_IN_BACKGROUND=1
-Environment=JBOSS_PIDFILE=/run/keycloak/keycloak.pid
-Environment=JBOSS_HOME={{ keycloak_jboss_home }}
-Environment=JBOSS_LOG_DIR={{ keycloak_log_dir }}
-Environment="JAVA_OPTS=-Xms1024m -Xmx1536m"
 User=keycloak
 Group=keycloak
-RuntimeDirectory=keycloak
-LimitNOFILE=102642
-PIDFile=/run/keycloak/keycloak.pid
-ExecStart={{ keycloak_jboss_home }}/bin/standalone.sh -b 0.0.0.0
+ExecStart={{ keycloak_jboss_home }}/bin/kc.sh start
 Restart=on-failure
+ReadWritePaths={{ keycloak_jboss_home }}
+ReadWritePaths=/var/log/keycloak
+# Disable timeout logic and wait until process is stopped
+TimeoutStopSec=0
+# SIGTERM signal is used to stop the Java process
+KillSignal=SIGTERM
+# Send the signal only to the JVM rather than its control group
+KillMode=process
+# Java process is never killed
+SendSIGKILL=no
+# When a JVM receives a SIGTERM signal it exits with code 143
+SuccessExitStatus=143
+
+# Hardening options
+CapabilityBoundingSet=
+AmbientCapabilities=
+NoNewPrivileges=true
+ProtectHome=true
+ProtectSystem=strict
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectControlGroups=true
+PrivateTmp=true
+PrivateDevices=true
+LockPersonality=true
 
 [Install]
 WantedBy=multi-user.target