Use standalone httpd role

In order to unify approach for managing Apache Web server, we migrate
to usage of standalone `httpd` role instead of managing apache
separately inside service roles.

Depends-On: https://review.opendev.org/c/openstack/ansible-role-httpd/+/947678
Change-Id: I4127fd535820c1bae0208cd4a665678a491a37f8
This commit is contained in:
Dmitriy Rabotyagov
2025-04-18 18:03:49 +02:00
parent 62fcbf7500
commit d51fdc3039
12 changed files with 73 additions and 309 deletions

View File

@@ -166,9 +166,6 @@ horizon_endpoint_type: internalURL
horizon_server_name: "{{ ansible_facts['fqdn'] | default('horizon') }}"
horizon_apache_mpm_backend: "{{ openstack_apache_mpm_backend | default('event') }}"
horizon_apache_servertokens: "Prod"
horizon_apache_serversignature: "Off"
horizon_log_level: info
# It's combined log format without datetime, since it's already present in journald
horizon_apache_custom_log_format: '"%h %l %u \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""'
@@ -227,9 +224,6 @@ horizon_wsgi_threads_max: 16
horizon_wsgi_threads: "{{ [[ansible_facts['processor_vcpus'] | default(2) // 2, 1] | max, horizon_wsgi_threads_max] | min }}"
## Horizon SSL
horizon_ssl_cert: /etc/ssl/certs/horizon.pem
horizon_ssl_key: /etc/ssl/private/horizon.key
horizon_ssl_ca_cert: /etc/ssl/certs/horizon-ca.pem
horizon_ssl_protocol: "{{ ssl_protocol | default('ALL -SSLv2 -SSLv3 -TLSv1 -TLSv1.1') }}"
# TLS v1.2 and below
horizon_ssl_cipher_suite_tls12: >-
@@ -543,38 +537,8 @@ horizon_pki_dir: "{{ openstack_pki_dir | default('/etc/openstack_deploy/pki') }}
horizon_pki_setup_host: "{{ openstack_pki_setup_host | default('localhost') }}"
# horizon server certificate
horizon_pki_keys_path: "{{ horizon_pki_dir ~ '/certs/private/' }}"
horizon_pki_certs_path: "{{ horizon_pki_dir ~ '/certs/certs/' }}"
horizon_pki_intermediate_cert_name: "{{ openstack_pki_service_intermediate_cert_name | default('ExampleCorpIntermediate') }}"
horizon_pki_intermediate_cert_path: >-
{{ horizon_pki_dir ~ '/roots/' ~ horizon_pki_intermediate_cert_name ~ '/certs/' ~ horizon_pki_intermediate_cert_name ~ '.crt' }}
horizon_pki_regen_cert: ""
horizon_pki_san: "{{ openstack_pki_san | default('DNS:' ~ ansible_facts['hostname'] ~ ',IP:' ~ management_address) }}"
horizon_pki_certificates:
- name: "horizon_{{ ansible_facts['hostname'] }}"
provider: ownca
cn: "{{ ansible_facts['hostname'] }}"
san: "{{ horizon_pki_san }}"
signed_by: "{{ horizon_pki_intermediate_cert_name }}"
# Installation details for SSL certificates
horizon_pki_install_certificates:
- src: "{{ horizon_user_ssl_cert | default(horizon_pki_certs_path ~ 'horizon_' ~ ansible_facts['hostname'] ~ '-chain.crt') }}"
dest: "{{ horizon_ssl_cert }}"
owner: "{{ horizon_system_user_name }}"
group: "{{ horizon_system_group_name }}"
mode: "0644"
- src: "{{ horizon_user_ssl_key | default(horizon_pki_keys_path ~ 'horizon_' ~ ansible_facts['hostname'] ~ '.key.pem') }}"
dest: "{{ horizon_ssl_key }}"
owner: "{{ horizon_system_user_name }}"
group: "{{ horizon_system_group_name }}"
mode: "0600"
- src: "{{ horizon_user_ssl_ca_cert | default(horizon_pki_intermediate_cert_path) }}"
dest: "{{ horizon_ssl_ca_cert }}"
owner: "{{ horizon_system_user_name }}"
group: "{{ horizon_system_group_name }}"
mode: "0644"
condition: "{{ horizon_user_ssl_ca_cert is defined }}"
# Define user-provided SSL certificates
# horizon_user_ssl_cert: <path to cert on ansible deployment host>

View File

@@ -31,4 +31,3 @@
daemon_reload: "{{ (ansible_facts['service_mgr'] == 'systemd') | ternary('yes', omit) }}"
listen:
- "venv changed"
- "cert installed"

View File

@@ -13,93 +13,60 @@
# See the License for the specific language governing permissions and
# limitations under the License.
- name: Ensure apache2 MPM for Debian/Ubuntu
community.general.apache2_module:
name: "{{ item.name }}"
state: "{{ item.state }}"
ignore_configcheck: true
warn_mpm_absent: false
with_items: "{{ horizon_apache_mpms | sort(attribute='state') }}"
when:
- ansible_facts['pkg_mgr'] == 'apt'
notify: Restart wsgi process
- name: Ensure apache2 MPM for EL
ansible.builtin.copy:
content: |
LoadModule mpm_{{ horizon_apache_mpm_backend }}_module modules/mod_mpm_{{ horizon_apache_mpm_backend }}.so
dest: /etc/httpd/conf.modules.d/00-mpm.conf
mode: "0644"
when:
- ansible_facts['pkg_mgr'] == 'dnf'
notify: Restart wsgi process
# NOTE(hwoarang): Module enable/disable process is only functional on Debian
- name: Enable apache2 modules
community.general.apache2_module:
name: "{{ item.name }}"
state: "{{ item.state }}"
ignore_configcheck: true
with_items:
- "{{ horizon_apache_modules }}"
when:
- ansible_facts['pkg_mgr'] == 'apt'
notify: Restart wsgi process
- name: Drop apache2 configs
ansible.builtin.template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner | default(horizon_system_user_name) }}"
group: "{{ item.group | default(horizon_system_group_name) }}"
mode: "0644"
with_items: "{{ horizon_apache_configs }}"
notify: Restart wsgi process
- name: Disable default apache site
- name: Clean-up old vhost files
ansible.builtin.file:
path: "{{ item }}"
state: "absent"
with_items: "{{ horizon_apache_default_sites }}"
notify: Restart wsgi process
state: absent
loop: "{{ horizon_deprecated_apache_configs }}"
- name: Enable Horizon Site
ansible.builtin.file:
src: "{{ horizon_apache_site_available }}"
dest: "{{ horizon_apache_site_enabled }}"
state: "link"
when:
- horizon_apache_site_available is defined
- horizon_apache_site_enabled is defined
notify: Restart wsgi process
- name: Ensure Apache ServerName
ansible.builtin.lineinfile:
dest: "{{ horizon_apache_conf }}"
line: "ServerName {{ horizon_server_name }}"
notify: Restart wsgi process
- name: Ensure Apache ServerTokens
ansible.builtin.lineinfile:
dest: "{{ horizon_apache_security_conf }}"
regexp: "^ServerTokens"
line: "ServerTokens {{ horizon_apache_servertokens }}"
notify: Restart wsgi process
- name: Ensure Apache ServerSignature
ansible.builtin.lineinfile:
dest: "{{ horizon_apache_security_conf }}"
regexp: "^ServerSignature"
line: "ServerSignature {{ horizon_apache_serversignature }}"
notify: Restart wsgi process
# Removing the Listen (or listen.conf inclusion) from apache config to prevent
# conflicts with ports.conf on CentOS and openSUSE
- name: Remove Listen from Apache config
ansible.builtin.lineinfile:
dest: "{{ horizon_apache_security_conf }}"
regexp: "^(Listen.*)"
backrefs: true
line: "#\\1"
notify: Restart wsgi process
- name: Including HTTPD role
ansible.builtin.import_role:
name: httpd
vars:
httpd_pki_dir: "{{ horizon_pki_dir }}"
httpd_pki_setup_host: "{{ horizon_pki_setup_host }}"
httpd_ssl_protocol: "{{ horizon_ssl_protocol }}"
httpd_ssl_cipher_suite_tls12: "{{ horizon_ssl_cipher_suite_tls12 }}"
httpd_ssl_cipher_suite_tls13: "{{ horizon_ssl_cipher_suite_tls13 }}"
httpd_pki_regen_cert: "{{ horizon_pki_regen_cert }}"
httpd_extra_packages: "{{ horizon_apache_distro_packages }}"
httpd_extra_modules:
- name: "wsgi"
state: "present"
httpd_vhosts:
- name: openstack_dashboard
address: "{{ horizon_bind_address }}"
port: "{{ (horizon_backend_ssl | bool) | ternary(horizon_listen_ports.https, horizon_listen_ports.http) }}"
log_level: "{{ horizon_log_level }}"
log_format: "{{ horizon_apache_custom_log_format }}"
server_name: "{{ horizon_server_name }}"
headers:
- 'RequestHeader set {{ horizon_secure_proxy_ssl_header }} "{{ horizon_external_ssl | ternary("https", "http") }}"'
options:
- "WSGIScriptAlias {{ horizon_webroot }} {{ horizon_lib_wsgi_file }}"
- >-
WSGIDaemonProcess horizon user={{ horizon_system_user_name }} group={{ horizon_system_group_name }} processes={{ horizon_wsgi_processes | default(
horizon_wsgi_threads) }} threads={{ horizon_wsgi_threads }} python-path={{ horizon_lib_dir | dirname }}/site-packages
- "WSGIProcessGroup horizon"
- "WSGIApplicationGroup %{GLOBAL}"
- "Alias {{ horizon_webroot }}/static {{ horizon_lib_dir }}/static/"
directories:
- path: "{{ horizon_lib_wsgi_file | dirname }}"
options:
- "<Files {{ horizon_lib_wsgi_file | basename }} >"
- " Require all granted"
- "</Files>"
- path: "{{ horizon_lib_dir }}/static/"
options:
- Options -FollowSymlinks
- Require all granted
- AddOutputFilterByType DEFLATE application/json
- AddOutputFilterByType DEFLATE text/javascript
- AddOutputFilterByType DEFLATE text/plain
- AddOutputFilterByType DEFLATE text/xml
- AddOutputFilterByType DEFLATE text/html
ssl: "{{ horizon_backend_ssl | ternary(_horizon_httpd_vhost_ssl, false) }}"
tags:
- horizon-install
- horizon-config
- httpd

View File

@@ -41,15 +41,3 @@
- { path: "/openstack/venvs", mode: "0755", owner: "root", group: "root" }
- { path: "/etc/horizon", mode: "2750" }
- { path: "{{ horizon_system_user_home }}", mode: "2755" }
- { path: "/etc/pki/tls/certs", owner: "root", group: "root", condition: "{{ (ansible_facts['pkg_mgr'] == 'dnf') }}" }
- { path: "/etc/pki/tls/private", owner: "root", group: "root", condition: "{{ (ansible_facts['pkg_mgr'] == 'dnf') }}" }
- name: Create system links
ansible.builtin.file:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
state: "link"
with_items:
- { src: "/etc/pki/tls/certs", dest: "/etc/ssl/certs" }
- { src: "/etc/pki/tls/private", dest: "/etc/ssl/private" }
when: ansible_facts['pkg_mgr'] == 'dnf'

View File

@@ -53,26 +53,6 @@
tags:
- horizon-install
- name: Create and install SSL certificates
ansible.builtin.include_role:
name: pki
tasks_from: main_certs.yml
apply:
tags:
- horizon-config
- pki
vars:
pki_setup_host: "{{ horizon_pki_setup_host }}"
pki_dir: "{{ horizon_pki_dir }}"
pki_create_certificates: "{{ horizon_user_ssl_cert is not defined and horizon_user_ssl_key is not defined }}"
pki_regen_cert: "{{ horizon_pki_regen_cert }}"
pki_certificates: "{{ horizon_pki_certificates }}"
pki_install_certificates: "{{ horizon_pki_install_certificates }}"
when:
- horizon_backend_ssl
tags:
- always
- name: Importing horizon_post_install tasks
ansible.builtin.import_tasks: horizon_post_install.yml
tags:

View File

@@ -1,6 +0,0 @@
# {{ ansible_managed }}
# We place a blank file here
# Listen commands happen inside the individual VHost files
# This allows for multiple services VHosts to exist without
# overwriting Listen lines.

View File

@@ -1,82 +0,0 @@
# {{ ansible_managed }}
{% for horizon_listen_port in horizon_listen_ports.values() %}
Listen {{ horizon_bind_address }}:{{ horizon_listen_port }}
{% endfor %}
# If horizon is being served via SSL from this web server,
# then we must redirect HTTP requests to HTTPS.
{% if (horizon_backend_ssl | bool) %}
<VirtualHost {{ horizon_bind_address }}:{{ horizon_listen_ports.http }}>
ServerName {{ horizon_server_name }}
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R,L]
</VirtualHost>
{% endif %}
# If horizon is being served via SSL via a load balancer, we
# need to listen via HTTP on this web server. If SSL is not
# enabled, then the same applies.
<VirtualHost {{ horizon_bind_address }}:{{ (horizon_backend_ssl | bool) | ternary(horizon_listen_ports.https, horizon_listen_ports.http) }}>
ServerName {{ horizon_server_name }}
LogLevel {{ horizon_log_level }}
ErrorLog syslog:daemon
CustomLog "|/usr/bin/env logger -p daemon.info -t {{ horizon_system_service_name }}" {{ horizon_apache_custom_log_format }}
Options +FollowSymLinks
{% if horizon_backend_ssl | bool %}
SSLEngine on
SSLCertificateFile {{ horizon_ssl_cert }}
SSLCertificateKeyFile {{ horizon_ssl_key }}
{% if horizon_user_ssl_ca_cert is defined -%}
SSLCACertificateFile {{ horizon_ssl_ca_cert }}
{% endif -%}
SSLCompression Off
SSLProtocol {{ horizon_ssl_protocol }}
SSLHonorCipherOrder On
{% if horizon_ssl_cipher_suite_tls12 != "" -%}
SSLCipherSuite {{ horizon_ssl_cipher_suite_tls12 }}
{% endif -%}
{% if horizon_ssl_cipher_suite_tls13 != "" -%}
SSLCipherSuite TLSv1.3 {{ horizon_ssl_cipher_suite_tls13 }}
{% endif -%}
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
{% endif %}
{% if horizon_external_ssl | bool %}
RequestHeader set {{ horizon_secure_proxy_ssl_header }} "https"
{% else %}
RequestHeader set {{ horizon_secure_proxy_ssl_header }} "http"
{% endif %}
WSGIScriptAlias {{ horizon_webroot }} {{ horizon_lib_wsgi_file }}
WSGIDaemonProcess horizon user={{ horizon_system_user_name }} group={{ horizon_system_group_name }} processes={{ horizon_wsgi_processes | default(horizon_wsgi_threads) }} threads={{ horizon_wsgi_threads }} python-path={{ horizon_lib_dir | dirname }}/site-packages
WSGIProcessGroup horizon
WSGIApplicationGroup %{GLOBAL}
<Directory {{ horizon_lib_wsgi_file | dirname }}>
<Files {{ horizon_lib_wsgi_file | basename }} >
<IfVersion < 2.4>
Order allow,deny
Allow from all
</IfVersion>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
</Files>
</Directory>
Alias {{ horizon_webroot }}/static {{ horizon_lib_dir }}/static/
<Directory {{ horizon_lib_dir }}/static/>
Options -FollowSymlinks
<IfVersion < 2.4>
AllowOverride None
Order allow,deny
Allow from all
</IfVersion>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
</Directory>
</VirtualHost>

View File

@@ -26,8 +26,6 @@ horizon_devel_distro_packages:
- libpcre3-dev
horizon_apache_distro_packages:
- apache2
- apache2-utils
- libapache2-mod-wsgi-py3
horizon_distro_packages:
@@ -39,34 +37,6 @@ horizon_service_distro_packages:
- python3-django-horizon
- python3-memcache
horizon_apache_conf: "/etc/apache2/apache2.conf"
horizon_apache_security_conf: "/etc/apache2/conf-available/security.conf"
horizon_apache_site_available: "/etc/apache2/sites-available/openstack-dashboard.conf"
horizon_apache_site_enabled: "/etc/apache2/sites-enabled/openstack-dashboard.conf"
horizon_apache_configs:
- { src: "horizon_apache_ports.conf.j2", dest: "/etc/apache2/ports.conf", owner: "root", group: "root" }
- { src: "openstack_dashboard.conf.j2", dest: "{{ horizon_apache_site_available }}", owner: "root", group: "root" }
horizon_apache_default_sites:
- "/etc/apache2/sites-enabled/000-default.conf"
- "/etc/apache2/conf-enabled/other-vhosts-access-log.conf"
horizon_apache_mpms:
- name: "mpm_event"
state: "{{ (horizon_apache_mpm_backend == 'event') | ternary('present', 'absent') }}"
- name: "mpm_worker"
state: "{{ (horizon_apache_mpm_backend == 'worker') | ternary('present', 'absent') }}"
- name: "mpm_prefork"
state: "{{ (horizon_apache_mpm_backend == 'prefork') | ternary('present', 'absent') }}"
horizon_apache_modules:
- name: "wsgi"
state: "present"
- name: "ssl"
state: "present"
- name: "rewrite"
state: "present"
- name: "headers"
state: "present"
horizon_deprecated_apache_configs:
- /etc/apache2/sites-available/openstack-dashboard.conf
- /etc/apache2/sites-enabled/openstack-dashboard.conf

View File

@@ -13,16 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
horizon_package_list: >-
{{
horizon_distro_packages | union(
(
(horizon_use_uwsgi | bool) | ternary([], horizon_apache_distro_packages)
)
) | union(
horizon_service_distro_packages
)
}}
horizon_package_list: "{{ horizon_distro_packages | union(horizon_service_distro_packages) }}"
_horizon_bin: "/usr/bin"

View File

@@ -42,6 +42,18 @@ horizon_dashboard_panel_dir: "{{ horizon_lib_dir }}/openstack_dashboard/local/en
horizon_dashboard_settings_dir: "{{ horizon_lib_dir }}/openstack_dashboard/local/local_settings.d"
horizon_manage: "{{ horizon_bin }}/horizon-manage.py"
_horizon_httpd_vhost_ssl: |-
{% set ssl_options = {} %}
{% if (horizon_user_ssl_cert is defined and horizon_user_ssl_cert) and (horizon_user_ssl_key is defined and horizon_user_ssl_key) %}
{% set _ = ssl_options.update({'cert': horizon_user_ssl_cert, 'key': horizon_user_ssl_key}) %}
{% if horizon_user_ssl_ca_cert is defined and horizon_user_ssl_ca_cert %}
{% set _ = ssl_options.update({'ca': horizon_user_ssl_ca_cert}) %}
{% endif %}
{% else %}
{% set _ = ssl_options.update({'san': horizon_pki_san}) %}
{% endif %}
{{ ssl_options }}
_horizon_uwsgi_ini_requirements:
uwsgi:
static-map: "/static={{ horizon_lib_dir }}/static/"

View File

@@ -23,9 +23,6 @@ horizon_devel_distro_packages:
- pcre-devel
horizon_apache_distro_packages:
- httpd
- httpd-tools
- mod_ssl
- python3-mod_wsgi
horizon_distro_packages:
@@ -45,14 +42,5 @@ horizon_service_distro_packages:
- python3-django-horizon
- python3-memcached
horizon_apache_conf: "/etc/httpd/conf/httpd.conf"
horizon_apache_security_conf: "{{ horizon_apache_conf }}"
horizon_apache_configs:
- { src: "horizon_apache_ports.conf.j2", dest: "/etc/httpd/conf.d/ports.conf", owner: "root", group: "root" }
- { src: "openstack_dashboard.conf.j2", dest: "/etc/httpd/conf.d/openstack-dashboard.conf", owner: "root", group: "root" }
horizon_apache_default_sites:
- "/etc/httpd/conf.d/userdir.conf"
- "/etc/httpd/conf.d/welcome.conf"
- "/etc/httpd/conf.d/ssl.conf"
horizon_deprecated_apache_configs:
- /etc/httpd/conf.d/openstack-dashboard.conf

View File

@@ -13,14 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
horizon_package_list: >-
{{
horizon_distro_packages | union(
(
(horizon_use_uwsgi | bool) | ternary([], horizon_apache_distro_packages)
)
)
}}
horizon_package_list: "{{ horizon_distro_packages }}"
_horizon_bin: "/openstack/venvs/horizon-{{ horizon_venv_tag }}/bin"