From 26f523867d48dd93f3a122b4152e710ddc11c2b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Mon, 15 Jul 2024 17:07:05 +0200 Subject: [PATCH] Replace Nginx with Apache2 In order to reduce amount of tech involved in deployment and better share commond resources and approaches Nginx web server is replaced with Apache2 now. Depends-On: https://review.opendev.org/c/openstack/openstack-ansible/+/924157 Change-Id: Ib8c7e985c710241bd97153130b77fcb1e904bfe1 --- defaults/main.yml | 37 +++++++-- handlers/main.yml | 10 +-- ...replace_nginx_apache-f62e453f44acf790.yaml | 8 ++ tasks/repo_install.yml | 17 +--- tasks/repo_post_install.yml | 68 ++++++++++------ tasks/repo_pre_install.yml | 12 ++- templates/apache_mpm.conf.j2 | 10 +++ templates/apache_ports.conf.j2 | 6 ++ templates/nginx.conf.j2 | 79 ------------------- templates/openstack-slushee.vhost.j2 | 25 ------ templates/openstack_slushee.vhost.j2 | 41 ++++++++++ tests/test-repo-server-functional.yml | 9 --- vars/debian.yml | 39 ++++++++- vars/redhat.yml | 28 ++++++- 14 files changed, 220 insertions(+), 169 deletions(-) create mode 100644 releasenotes/notes/replace_nginx_apache-f62e453f44acf790.yaml create mode 100644 templates/apache_mpm.conf.j2 create mode 100644 templates/apache_ports.conf.j2 delete mode 100644 templates/nginx.conf.j2 delete mode 100644 templates/openstack-slushee.vhost.j2 create mode 100644 templates/openstack_slushee.vhost.j2 diff --git a/defaults/main.yml b/defaults/main.yml index 240cb06..8bda2d5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -16,10 +16,6 @@ ## Verbosity Options debug: False -## Cap the maximum number of threads / workers when a user value is unspecified. -repo_nginx_threads_max: 16 -repo_nginx_threads: "{{ [[ansible_facts['processor_vcpus'] | default(2) // 2, 1] | max, repo_nginx_threads_max] | min }}" - ## APT Cache Options cache_timeout: 600 @@ -32,13 +28,39 @@ repo_worker_connections: 1024 repo_server_name: openstack-slushee repo_service_home_folder: /var/www -repo_service_user_name: nginx +repo_service_user_name: www-data repo_service_group_name: www-data +repo_system_service_name: "{{ _repo_system_service_name }}" # Main web server port repo_server_bind_address: "{{ openstack_service_bind_address | default('0.0.0.0') }}" repo_server_port: 8181 +repo_vhost_enable_path: "{{ _repo_vhost_enable_path }}" + +repo_apache_conf: "{{ _repo_apache_conf }}" +repo_apache_configs: "{{ _repo_apache_configs }}" +repo_apache_custom_log_format: '"%h %l %u \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' +repo_apache_default_sites: "{{ _repo_apache_default_sites }}" +repo_apache_log_level: info +# List of modules to enable are respected only for Debian Family +repo_apache_modules: "{{ _repo_apache_modules }}" + +# MPM tunables +repo_apache_mpm_backend: "{{ openstack_apache_mpm_backend | default('event') }}" +repo_apache_threads_max: "{{ openstack_apache_threads_max | default(16) }}" +repo_apache_mpm_server_limit: "{{ [[ansible_facts['processor_vcpus'] | default(2) // 2, 1] | max, repo_apache_threads_max | int] | min }}" +repo_apache_mpm_start_servers: "{{ openstack_apache_start_servers | default(2) }}" +repo_apache_mpm_min_spare_threads: "{{ openstack_apache_min_spare_threads | default(25) }}" +repo_apache_mpm_max_spare_threads: "{{ openstack_apache_max_spare_threads | default(75) }}" +repo_apache_mpm_thread_limit: "{{ openstack_apache_thread_limit | default(64) }}" +repo_apache_mpm_thread_child: "{{ openstack_apache_thread_child | default(25) }}" +repo_apache_mpm_max_requests: "{{ repo_apache_mpm_server_limit | int * repo_apache_mpm_thread_child | int }}" +repo_apache_mpm_max_conn_child: "{{ openstack_apache_max_conn_child | default(0) }}" + +repo_apache_security_conf: "{{ _repo_apache_security_conf }}" +## Cap the maximum number of threads / workers when a user value is unspecified. + # This directory is used by the repo_build, and will cause problems if synced # to repo_containers with other releases. repo_build_global_links_dirname: links @@ -92,6 +114,11 @@ repo_pki_certificates: repo_ssl_cert: /etc/ssl/certs/repo.pem repo_ssl_key: /etc/ssl/private/repo.key repo_ssl_ca_cert: /etc/ssl/certs/repo-ca.pem +repo_ssl_protocol: "{{ ssl_protocol | default('ALL -SSLv2 -SSLv3 -TLSv1 -TLSv1.1') }}" +# TLS v1.2 and below +repo_ssl_cipher_suite_tls12: "{{ ssl_cipher_suite | default('ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM') }}" +# TLS v1.3 +repo_ssl_cipher_suite_tls13: "{{ ssl_cipher_suite_tls13 | default('TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256') }}" # Installation details for SSL certificates repo_pki_install_certificates: diff --git a/handlers/main.yml b/handlers/main.yml index 3e7a433..0bb8d5f 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -13,15 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -- name: Reload nginx +- name: Restart web server service: - name: "nginx" + name: "{{ repo_system_service_name }}" enabled: yes - state: restarted + state: "restarted" daemon_reload: "{{ (ansible_facts['service_mgr'] == 'systemd') | ternary('yes', omit) }}" - register: _restart - until: _restart is success - retries: 5 - delay: 2 listen: - "cert installed" diff --git a/releasenotes/notes/replace_nginx_apache-f62e453f44acf790.yaml b/releasenotes/notes/replace_nginx_apache-f62e453f44acf790.yaml new file mode 100644 index 0000000..1844a9c --- /dev/null +++ b/releasenotes/notes/replace_nginx_apache-f62e453f44acf790.yaml @@ -0,0 +1,8 @@ +--- + +upgrade: + - | + A web server for repo containers/hosts has been changed from Nginx to + Apache. + This was made to reduce amount of services we manage with roles and to + better align approaches and development vectors. diff --git a/tasks/repo_install.yml b/tasks/repo_install.yml index 3eb78f6..b00f1a8 100644 --- a/tasks/repo_install.yml +++ b/tasks/repo_install.yml @@ -13,20 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -- name: Remove old nginx repo - yum_repository: - name: "nginx" +# TODO: remove this task after 2025.1 (Epoxy) release +- name: Remove nginx web server + package: + name: nginx-* state: absent - register: _repo_removed - when: - - ansible_facts['pkg_mgr'] == 'dnf' - -- name: Clean yum metadata when nginx repo is removed - command: dnf clean metadata - changed_when: false - when: - - ansible_facts['pkg_mgr'] == 'dnf' - - _repo_removed is changed - name: Install distro packages package: diff --git a/tasks/repo_post_install.yml b/tasks/repo_post_install.yml index ea07a08..9a7352b 100644 --- a/tasks/repo_post_install.yml +++ b/tasks/repo_post_install.yml @@ -19,33 +19,53 @@ name: pack.threads value: '0' -- name: Remove default nginx file - file: - path: "{{ item.path }}" - state: "{{ item.state | default('absent') }}" - mode: "0644" - with_items: - - path: "/etc/nginx/sites-enabled/default" - notify: - - Reload nginx +- name: Enable apache2 modules + apache2_module: + name: "{{ item.name }}" + state: "{{ item.state }}" + ignore_configcheck: yes + with_items: "{{ repo_apache_modules }}" + when: + - ansible_facts['pkg_mgr'] == 'apt' + notify: Restart web server -- name: Drop NGINX configuration files +- name: Disable default apache site + file: + path: "{{ item }}" + state: "absent" + with_items: "{{ repo_apache_default_sites }}" + notify: Restart web server + +- name: Ensure Apache configuration + lineinfile: + dest: "{{ repo_apache_conf }}" + line: "{{ item }}" + notify: Restart web server + with_items: + - "ServerName {{ repo_server_name }}" + - "ErrorLog syslog:daemon" + +- name: Create Apache config template: - src: "{{ item.src }}" - dest: "{{ item.dest }}" + src: "{{ item['src'] }}" + dest: "{{ item['dest'] }}" + owner: "{{ item['owner'] }}" + group: "{{ item['group'] }}" mode: "0644" - with_items: - - src: "nginx.conf.j2" - dest: "/etc/nginx/nginx.conf" - - src: "openstack-slushee.vhost.j2" - dest: "/etc/nginx/sites-available/openstack-slushee.vhost" - notify: - - Reload nginx + with_items: "{{ repo_apache_configs }}" + notify: Restart web server -- name: Enable openstack-slushee site +- name: Enable repo site file: - src: "/etc/nginx/sites-available/openstack-slushee.vhost" - dest: "/etc/nginx/sites-enabled/openstack-slushee.vhost" + src: "/etc/{{ repo_system_service_name }}/sites-available/openstack_slushee.conf" + dest: "{{ repo_vhost_enable_path }}/openstack_slushee.conf" state: "link" - notify: - - Reload nginx + notify: Restart web server + +- name: Remove Listen from Apache config + lineinfile: + dest: "{{ repo_apache_security_conf }}" + regexp: '^(Listen.*)' + backrefs: yes + line: '#\1' + notify: Restart web server diff --git a/tasks/repo_pre_install.yml b/tasks/repo_pre_install.yml index 1d52091..d8b7a9e 100644 --- a/tasks/repo_pre_install.yml +++ b/tasks/repo_pre_install.yml @@ -52,11 +52,11 @@ state: "{{ item.state | default('directory') }}" owner: "{{ repo_service_user_name }}" group: "{{ repo_service_group_name }}" - mode: "{{ item.mode | default('02755') }}" + mode: "{{ item.mode | default('2755') }}" with_items: - path: "{{ repo_service_home_folder }}" - path: "{{ repo_service_home_folder }}/.ssh" - mode: "02700" + mode: "2700" - path: "{{ repo_service_home_folder }}/repo" - path: "{{ repo_service_home_folder }}/repo/links" - path: "{{ repo_service_home_folder }}/repo/os-releases" @@ -64,10 +64,13 @@ - path: "{{ repo_service_home_folder }}/repo/pools" - path: "{{ repo_service_home_folder }}/repo/venvs" - path: "{{ repo_service_home_folder }}/repo/constraints" + - path: "/etc/{{ repo_system_service_name }}/sites-available" - path: "/var/lib/nginx" + state: absent - path: "/var/log/nginx" - mode: "0775" + state: absent +# NOTE: Remove after 2025.1 (Epoxy) release - name: File and directory setup (root user) file: path: "{{ item.path }}" @@ -77,5 +80,8 @@ mode: "0755" with_items: - path: "/etc/nginx/conf.d" + state: absent - path: "/etc/nginx/sites-available" + state: absent - path: "/etc/nginx/sites-enabled" + state: absent diff --git a/templates/apache_mpm.conf.j2 b/templates/apache_mpm.conf.j2 new file mode 100644 index 0000000..f881458 --- /dev/null +++ b/templates/apache_mpm.conf.j2 @@ -0,0 +1,10 @@ + + ServerLimit {{ repo_apache_mpm_server_limit }} + StartServers {{ repo_apache_mpm_start_servers }} + MinSpareThreads {{ repo_apache_mpm_min_spare_threads }} + MaxSpareThreads {{ repo_apache_mpm_max_spare_threads }} + ThreadLimit {{ repo_apache_mpm_thread_limit }} + ThreadsPerChild {{ repo_apache_mpm_thread_child }} + MaxRequestWorkers {{ repo_apache_mpm_max_requests }} + MaxConnectionsPerChild {{ repo_apache_mpm_max_conn_child }} + diff --git a/templates/apache_ports.conf.j2 b/templates/apache_ports.conf.j2 new file mode 100644 index 0000000..3c32de3 --- /dev/null +++ b/templates/apache_ports.conf.j2 @@ -0,0 +1,6 @@ +# {{ 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. diff --git a/templates/nginx.conf.j2 b/templates/nginx.conf.j2 deleted file mode 100644 index 91092e1..0000000 --- a/templates/nginx.conf.j2 +++ /dev/null @@ -1,79 +0,0 @@ -user {{ repo_service_user_name }} {{ repo_service_group_name }}; -pid {{ repo_nginx_pid }}; - -worker_processes {{ repo_nginx_threads }}; - -events { - worker_connections {{ repo_worker_connections }}; - multi_accept on; -} - -http { - # Basic Settings - include /etc/nginx/mime.types; - default_type application/octet-stream; - sendfile off; - tcp_nopush on; - tcp_nodelay on; - client_header_timeout 10m; - client_body_timeout 10m; - send_timeout 10m; - proxy_read_timeout 600s; - proxy_send_timeout 600s; - proxy_connect_timeout 600s; - - # Added Larger Post Max - client_max_body_size 5M; - - keepalive_timeout 60 15; - types_hash_max_size 2048; - - # Logging Settings - log_format gzip '$remote_addr - $remote_user [$time_local] ' - '"$request" $status $bytes_sent ' - '"$http_referer" "$http_user_agent" "$gzip_ratio"'; - access_log /var/log/nginx/access.log gzip buffer=32k; - error_log /var/log/nginx/error.log notice; - - # Gzip Settings - gzip on; - gzip_disable "msie6"; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_min_length 1100; - gzip_buffers 16 8k; - - # Turn on gzip for all content types that should benefit from it. - gzip_types application/ecmascript; - gzip_types application/javascript; - gzip_types application/json; - gzip_types application/pdf; - gzip_types application/postscript; - gzip_types application/x-javascript; - gzip_types image/svg+xml; - gzip_types text/css; - gzip_types text/csv; - - # "gzip_types text/html" is assumed. - gzip_types text/javascript; - gzip_types text/plain; - gzip_types text/xml; - - gzip_http_version 1.0; - - # Custom Header - add_header X-WHOAMI "OpenStack Private Slushee Repository {{ inventory_hostname }}"; - - # Virtual Host Configs - include /etc/nginx/conf.d/*.conf; - include /etc/nginx/sites-enabled/*; - - # Map Mobile - map $http_user_agent $is_mobile { - default 0; - ~*android|ip(hone|od)|windows\s+(?:ce|phone) 1; - ~*symbian|sonyericsson|samsung|lg|blackberry 1; - ~*mobile 1; - } -} diff --git a/templates/openstack-slushee.vhost.j2 b/templates/openstack-slushee.vhost.j2 deleted file mode 100644 index b4850cf..0000000 --- a/templates/openstack-slushee.vhost.j2 +++ /dev/null @@ -1,25 +0,0 @@ -server { - listen {{ repo_server_bind_address }}:{{ repo_server_port }}; - server_name {{ repo_server_name }}; - - {% if repo_backend_ssl | bool -%} - ssl on; - ssl_certificate {{ repo_ssl_cert }}; - ssl_certificate_key {{ repo_ssl_key }}; - {% if repo_user_ssl_ca_cert is defined -%} - ssl_trusted_certificate {{ repo_ssl_ca_cert }}; - {% endif -%} - {% endif -%} - - # Logging - access_log /var/log/nginx/{{ repo_server_name }}.access.log gzip buffer=32k; - error_log /var/log/nginx/{{ repo_server_name }}.error.log notice; - - absolute_redirect off; - - location / { - root {{ repo_service_home_folder }}/repo/; - autoindex on; - expires -1; - } -} diff --git a/templates/openstack_slushee.vhost.j2 b/templates/openstack_slushee.vhost.j2 new file mode 100644 index 0000000..5cc3257 --- /dev/null +++ b/templates/openstack_slushee.vhost.j2 @@ -0,0 +1,41 @@ +# {{ ansible_managed }} + +Listen {{ repo_server_bind_address }}:{{ repo_server_port }} + + + ServerName {{ repo_server_name }} + LogLevel {{ repo_apache_log_level }} + ErrorLog syslog:daemon + CustomLog "|/usr/bin/env logger -p daemon.info -t {{ repo_system_service_name }}" {{ repo_apache_custom_log_format }} + DocumentRoot {{ repo_service_home_folder }}/repo +{% if repo_backend_ssl | bool %} + SSLEngine on + SSLCertificateFile {{ repo_ssl_cert }} + SSLCertificateKeyFile {{ repo_ssl_key }} + {% if repo_user_ssl_ca_cert is defined -%} + SSLCACertificateFile {{ repo_ssl_ca_cert }} + {% endif -%} + SSLCompression Off + SSLProtocol {{ repo_ssl_protocol }} + SSLHonorCipherOrder On + {% if repo_ssl_cipher_suite_tls12 != "" -%} + SSLCipherSuite {{ repo_ssl_cipher_suite_tls12 }} + {% endif -%} + {% if repo_ssl_cipher_suite_tls13 != "" -%} + SSLCipherSuite TLSv1.3 {{ repo_ssl_cipher_suite_tls13 }} + {% endif -%} + SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown +{% endif %} + + Header set X-WHOAMI "OpenStack Private Slushee Repository {{ inventory_hostname }}" + + + Options +FollowSymlinks +Indexes + AllowOverride None + AddOutputFilterByType DEFLATE application/json + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/xml + Require ip {{ (container_networks['management_address']['address'] ~ '/' ~ container_networks['management_address']['netmask']) | ipaddr('subnet') }} + + diff --git a/tests/test-repo-server-functional.yml b/tests/test-repo-server-functional.yml index 64aeaa9..355bee2 100644 --- a/tests/test-repo-server-functional.yml +++ b/tests/test-repo-server-functional.yml @@ -17,15 +17,6 @@ hosts: repo_all user: root tasks: - - name: Check nginx is running - shell: "ps auxf | grep nginx" - register: ps_auxf_nginx - until: ps_auxf_nginx.stdout.find('master process') != -1 - retries: 5 - delay: 2 - tags: - - skip_ansible_lint - - name: Check service is available uri: url: "http://localhost:8181" diff --git a/vars/debian.yml b/vars/debian.yml index 1e41a1c..6543683 100644 --- a/vars/debian.yml +++ b/vars/debian.yml @@ -15,12 +15,47 @@ systemd_utils_prefix: "/lib/systemd" -repo_nginx_pid: /run/nginx.pid +_repo_system_service_name: apache2 + +_repo_vhost_enable_path: "/etc/{{ repo_system_service_name }}/sites-enabled" + +_repo_apache_modules: + - name: "ssl" + state: "present" + - name: "mpm_{{ repo_apache_mpm_backend }}" + state: "present" + - name: "rewrite" + state: "present" + - name: "headers" + state: "present" + - name: "deflate" + state: "present" + +_repo_apache_default_sites: + - "{{ repo_vhost_enable_path }}/000-default.conf" + - /etc/apache2/conf-enabled/other-vhosts-access-log.conf + +_repo_apache_configs: + - src: "apache_ports.conf.j2" + dest: "/etc/apache2/ports.conf" + owner: "root" + group: "root" + - src: "openstack_slushee.vhost.j2" + dest: "/etc/{{ repo_system_service_name }}/sites-available/openstack_slushee.conf" + owner: "root" + group: "root" + - src: "apache_mpm.conf.j2" + dest: "/etc/apache2/mods-available/mpm_{{ repo_apache_mpm_backend }}.conf" + owner: "root" + group: "root" + +_repo_apache_conf: "/etc/apache2/apache2.conf" +_repo_apache_security_conf: "/etc/apache2/conf-available/security.conf" # NOTE(jrosser) remove this once rsync cleanup tasks are no longer required rsyncd_service_name: rsync repo_server_distro_packages: - git - - nginx-extras + - apache2 - sudo diff --git a/vars/redhat.yml b/vars/redhat.yml index 83c1301..5bade0c 100644 --- a/vars/redhat.yml +++ b/vars/redhat.yml @@ -15,12 +15,36 @@ systemd_utils_prefix: "/lib/systemd" -repo_nginx_pid: /run/nginx.pid +_repo_system_service_name: httpd + +_repo_vhost_enable_path: "/etc/{{ repo_system_service_name }}/conf.d" + +_repo_apache_default_sites: + - "/etc/httpd/conf.d/userdir.conf" + - "/etc/httpd/conf.d/welcome.conf" + +_repo_apache_configs: + - src: "apache_ports.conf.j2" + dest: "{{ repo_vhost_enable_path }}/ports.conf" + owner: "root" + group: "root" + - src: "openstack_slushee.vhost.j2" + dest: "/etc/{{ repo_system_service_name }}/sites-available/openstack_slushee.conf" + owner: "root" + group: "root" + - src: "apache_mpm.conf.j2" + dest: "/etc/httpd/conf.modules.d/mpm_{{ repo_apache_mpm_backend }}.conf" + owner: "root" + group: "root" + +_repo_apache_conf: "/etc/httpd/conf/httpd.conf" +_repo_apache_security_conf: "{{ repo_apache_conf }}" # NOTE(jrosser) remove this when rsyncd cleanup task are no longer required rsyncd_service_name: rsyncd repo_server_distro_packages: - git - - nginx + - httpd + - "{{ repo_backend_ssl | ternary('mod_ssl', '') }}" - sudo