# Alliance BorΓ©ale - Keycloak Tasks (database, nginx, realms, firewall) # Date: 2025-10-31 --- # ========================================== # DATABASE.YML # ========================================== - name: "πŸ—„οΈ Ensure PostgreSQL is installed" ansible.builtin.include_role: name: postgresql when: "'postgresql_servers' in group_names" - name: "πŸ—„οΈ Create Keycloak database" community.postgresql.postgresql_db: name: "{{ keycloak.db.database }}" encoding: UTF8 state: present become: true become_user: postgres - name: "πŸ‘€ Create Keycloak database user" community.postgresql.postgresql_user: name: "{{ keycloak.db.username }}" password: "{{ keycloak.db.password }}" state: present become: true become_user: postgres no_log: true - name: "πŸ” Grant privileges to Keycloak user" community.postgresql.postgresql_privs: database: "{{ keycloak.db.database }}" roles: "{{ keycloak.db.username }}" type: database privs: ALL state: present become: true become_user: postgres # ========================================== # NGINX.YML # ========================================== - name: "πŸ“¦ Ensure Nginx is installed" ansible.builtin.apt: name: nginx state: present - name: "πŸ” Generate self-signed SSL certificate" ansible.builtin.command: cmd: > openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/{{ keycloak.hostname }}.key -out /etc/ssl/certs/{{ keycloak.hostname }}.crt -subj "/C=CA/ST=Quebec/L=Montreal/O=Chezlepro/CN={{ keycloak.hostname }}" creates: "/etc/ssl/certs/{{ keycloak.hostname }}.crt" when: nginx.ssl.cert_source == 'self-signed' - name: "βš™οΈ Configure Nginx for Keycloak" ansible.builtin.template: src: nginx-keycloak.conf.j2 dest: /etc/nginx/sites-available/keycloak owner: root group: root mode: '0644' notify: reload nginx - name: "πŸ”— Enable Nginx site" ansible.builtin.file: src: /etc/nginx/sites-available/keycloak dest: /etc/nginx/sites-enabled/keycloak state: link notify: reload nginx - name: "🚫 Remove default Nginx site" ansible.builtin.file: path: /etc/nginx/sites-enabled/default state: absent notify: reload nginx - name: "βœ… Start and enable Nginx" ansible.builtin.systemd: name: nginx state: started enabled: true # ========================================== # REALMS.YML # ========================================== - name: "🏰 Check if realm exists" ansible.builtin.uri: url: "http://127.0.0.1:{{ keycloak.http_port }}/admin/realms/{{ item.name }}" method: GET user: "{{ keycloak.admin_user }}" password: "{{ keycloak.admin_password }}" force_basic_auth: true status_code: [200, 404] loop: "{{ keycloak.realms }}" register: realm_check changed_when: false no_log: true - name: "🏰 Create realm configuration file" ansible.builtin.template: src: realm-config.json.j2 dest: "/tmp/realm-{{ item.name }}.json" owner: keycloak group: keycloak mode: '0640' loop: "{{ keycloak.realms }}" when: realm_check.results[0].status == 404 - name: "🏰 Import realm" ansible.builtin.command: cmd: > /opt/keycloak/bin/kc.sh import --file /tmp/realm-{{ item.name }}.json --override false become: true become_user: keycloak loop: "{{ keycloak.realms }}" when: realm_check.results[0].status == 404 register: realm_import changed_when: "'imported' in realm_import.stdout" # ========================================== # FIREWALL.YML # ========================================== - name: "πŸ”₯ Configure firewall for Keycloak" ansible.builtin.blockinfile: path: /etc/nftables.conf marker: "# {mark} ANSIBLE MANAGED - Keycloak" insertbefore: "# Log dropped packets" block: | # Keycloak - Internal HTTP (backend only) ip saddr 127.0.0.1 tcp dport {{ keycloak.http_port }} accept comment "Keycloak HTTP" # Nginx - HTTPS (public) tcp dport 443 accept comment "HTTPS (Keycloak via Nginx)" tcp dport 80 accept comment "HTTP redirect" notify: reload nftables