--- - name: "⚙️ Apply the site settings to the running instance" ansible.builtin.command: argv: - container - exec - -i - -e - "DISCOURSE_FORCE_HTTPS={{ DISCOURSE_TLS_ENABLED | bool | string | lower }}" - -e - "DISCOURSE_LOCAL_LOGINS={{ DISCOURSE_LOCAL_LOGIN_ENABLED | bool | string | lower }}" - -e - "DISCOURSE_LDAP_SITE_SETTINGS={{ (DISCOURSE_PLUGINS['discourse-ldap-auth'].config.site_settings if DISCOURSE_LDAP_ENABLED | bool else {}) | to_json }}" - -e - "DISCOURSE_OIDC_ENABLED={{ DISCOURSE_OIDC_ENABLED | bool | string | lower }}" - -e - "DISCOURSE_OIDC_VERBOSE={{ MODE_DEBUG | bool | string | lower }}" - -e - "DISCOURSE_OIDC_DISCOVERY_DOCUMENT={{ OIDC.CLIENT.DISCOVERY_DOCUMENT if DISCOURSE_OIDC_ENABLED | bool else '' }}" - -e - "DISCOURSE_OIDC_CLIENT_ID={{ OIDC.CLIENT.ID if DISCOURSE_OIDC_ENABLED | bool else '' }}" - -e - "DISCOURSE_OIDC_CLIENT_SECRET={{ OIDC.CLIENT.SECRET if DISCOURSE_OIDC_ENABLED | bool else '' }}" - -e - "DISCOURSE_OIDC_LOGOUT_REDIRECT={{ DISCOURSE_OIDC_LOGOUT_REDIRECT_URL if DISCOURSE_OIDC_ENABLED | bool else '' }}" - "{{ DISCOURSE_CONTAINER }}" # nocheck: container-exec-resolver the launcher names the container itself, so the bare name resolves in both modes - rails - r - "{{ lookup('file', 'ruby/apply_settings.rb') }}" changed_when: false no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" - name: "🔑 Ensure the administrator account carries the current password" ansible.builtin.command: argv: - container - exec - -i - -e - "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'administrator').email }}" - -e - "DISCOURSE_ADMIN_USERNAME={{ lookup('users', 'administrator').username }}" - -e - "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'administrator').password }}" - "{{ DISCOURSE_CONTAINER }}" # nocheck: container-exec-resolver the launcher names the container itself, so the bare name resolves in both modes - rails - r - "{{ lookup('file', 'ruby/ensure_admin_user.rb') }}" changed_when: false no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" - name: "🔎 Read the applied settings back out of the running instance" ansible.builtin.command: argv: - container - exec - -i - -e - "DISCOURSE_ADMIN_EMAIL={{ lookup('users', 'administrator').email }}" - -e - "DISCOURSE_ADMIN_PASSWORD={{ lookup('users', 'administrator').password }}" - -e - "DISCOURSE_OIDC_ENABLED={{ DISCOURSE_OIDC_ENABLED | bool | string | lower }}" - -e - "DISCOURSE_OIDC_CLIENT_SECRET={{ OIDC.CLIENT.SECRET if DISCOURSE_OIDC_ENABLED | bool else '' }}" - "{{ DISCOURSE_CONTAINER }}" # nocheck: container-exec-resolver the launcher names the container itself, so the bare name resolves in both modes - rails - r - "{{ lookup('file', 'ruby/verify_settings.rb') }}" register: discourse_settings_readback changed_when: false no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" - name: "🛑 Refuse an instance the rotated credentials did not reach" ansible.builtin.assert: that: - "'administrator_present=true' in discourse_settings_readback.stdout_lines" - "'administrator_admin=true' in discourse_settings_readback.stdout_lines" - "'administrator_active=true' in discourse_settings_readback.stdout_lines" - "'administrator_password_matches=true' in discourse_settings_readback.stdout_lines" - "not DISCOURSE_OIDC_ENABLED | bool or 'oidc_secret_matches=true' in discourse_settings_readback.stdout_lines" - "not DISCOURSE_OIDC_ENABLED | bool or 'oidc_enabled=true' in discourse_settings_readback.stdout_lines" - "not DISCOURSE_OIDC_ENABLED | bool or 'oidc_host_allowed=true' in discourse_settings_readback.stdout_lines" fail_msg: >- The administrator account, the OIDC client secret or the internal-host allowlist of the running Discourse does not match the inventory, so a rotated credential or a site setting never reached it.