This guide deploys Keycloak with PostgreSQL using Docker Compose.
/opt/keycloak stack directory- name: Deploy Keycloak on Debian family
hosts: keycloak_debian
become: true
vars:
keycloak_dir: /opt/keycloak
keycloak_admin_user: admin
keycloak_admin_password: change-me-admin
keycloak_db_password: change-me-db
keycloak_version: "26.5.3" # Use latest stable version
tasks:
- name: Install Docker packages
ansible.builtin.apt:
update_cache: true
name:
- docker.io
- docker-compose-plugin
state: present
- name: Add docker group to keycloak user
ansible.builtin.group:
name: docker
state: present
- name: Add keycloak user to docker group
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: true
- name: Enable and start Docker
ansible.builtin.systemd:
name: docker
enabled: true
state: started
- name: Ensure stack directory exists
ansible.builtin.file:
path: "{{ keycloak_dir }}"
state: directory
mode: "0755"
- name: Write Keycloak env file
ansible.builtin.copy:
dest: "{{ keycloak_dir }}/.env"
mode: "0600"
content: |
KEYCLOAK_ADMIN={{ keycloak_admin_user }}
KEYCLOAK_ADMIN_PASSWORD={{ keycloak_admin_password }}
KC_DB=postgres
KC_DB_URL_HOST=postgres
KC_DB_URL_DATABASE=keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD={{ keycloak_db_password }}
# Additional Keycloak configuration
KC_PROXY=reverse
KC_HTTP_RELATIVE_PATH=/auth
- name: Write Docker Compose file
ansible.builtin.copy:
dest: "{{ keycloak_dir }}/docker-compose.yml"
mode: "0644"
content: |
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
volumes:
- ./postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak"]
interval: 10s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:{{ keycloak_version }}
command: start
restart: unless-stopped
env_file:
- .env
ports:
- "8080:8080"
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"]
interval: 30s
timeout: 10s
retries: 3
- name: Start Keycloak stack
ansible.builtin.command: docker compose up -d
args:
chdir: "{{ keycloak_dir }}"
- name: Wait for Keycloak to be ready
ansible.builtin.uri:
url: http://localhost:8080/health/ready
method: GET
status_code: 200
register: result
until: result.status == 200
retries: 30
delay: 10
- name: Deploy Keycloak on RHEL family
hosts: keycloak_rhel
become: true
vars:
keycloak_dir: /opt/keycloak
keycloak_admin_user: admin
keycloak_admin_password: change-me-admin
keycloak_db_password: change-me-db
keycloak_version: "26.5.3" # Use latest stable version
tasks:
- name: Install Docker packages
ansible.builtin.dnf:
name:
- docker
- docker-compose-plugin
state: present
- name: Add docker group to keycloak user
ansible.builtin.group:
name: docker
state: present
- name: Add keycloak user to docker group
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: true
- name: Enable and start Docker
ansible.builtin.systemd:
name: docker
enabled: true
state: started
- name: Ensure stack directory exists
ansible.builtin.file:
path: "{{ keycloak_dir }}"
state: directory
mode: "0755"
- name: Write Keycloak env file
ansible.builtin.copy:
dest: "{{ keycloak_dir }}/.env"
mode: "0600"
content: |
KEYCLOAK_ADMIN={{ keycloak_admin_user }}
KEYCLOAK_ADMIN_PASSWORD={{ keycloak_admin_password }}
KC_DB=postgres
KC_DB_URL_HOST=postgres
KC_DB_URL_DATABASE=keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD={{ keycloak_db_password }}
# Additional Keycloak configuration
KC_PROXY=reverse
KC_HTTP_RELATIVE_PATH=/auth
- name: Write Docker Compose file
ansible.builtin.copy:
dest: "{{ keycloak_dir }}/docker-compose.yml"
mode: "0644"
content: |
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
volumes:
- ./postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak"]
interval: 10s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:{{ keycloak_version }}
command: start
restart: unless-stopped
env_file:
- .env
ports:
- "8080:8080"
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"]
interval: 30s
timeout: 10s
retries: 3
- name: Start Keycloak stack
ansible.builtin.command: docker compose up -d
args:
chdir: "{{ keycloak_dir }}"
- name: Wait for Keycloak to be ready
ansible.builtin.uri:
url: http://localhost:8080/health/ready
method: GET
status_code: 200
register: result
until: result.status == 200
retries: 30
delay: 10
ansible-playbook -i inventory.ini keycloak-install.yml
start instead of start-dev command for productionkeycloak_debian.