diff --git a/roles/debian/nginx/defaults/main.yml b/roles/debian/nginx/defaults/main.yml index f348f9eab..dc18d90ba 100644 --- a/roles/debian/nginx/defaults/main.yml +++ b/roles/debian/nginx/defaults/main.yml @@ -40,6 +40,8 @@ nginx: client_body_buffer_size: 512k fastcgi_buffer_size: 512k fastcgi_buffers: "8 256k" + cache_behavior_private: "add_header Cache-Control \"private, max-age=604800\"" + cache_behavior_public: "add_header Cache-Control \"public, max-age=604800\"" # You can inject custom directives into the main nginx.conf file here by providing them as a list of strings. #custom_directives: [] # Group prefix. Useful for grouping by environments. diff --git a/roles/debian/nginx/tasks/domain.yml b/roles/debian/nginx/tasks/domain.yml index 3da1f900b..be355855e 100644 --- a/roles/debian/nginx/tasks/domain.yml +++ b/roles/debian/nginx/tasks/domain.yml @@ -1,59 +1,54 @@ --- -# If auth_enabled is defined and yes, and auth_pass is not defined or is defined but empty, generate a random password. -- name: Generate random htauth password. - ansible.builtin.set_fact: - _nginx_htauth_pass: "{{ lookup('password', _ce_provision_data_dir + '/' + inventory_hostname + '/nginx-passwords/' + domain.server_name) }}" +- name: Set up basic auth. when: - domain.basic_auth.auth_enabled is defined - domain.basic_auth.auth_enabled - - domain.basic_auth.auth_pass is not defined or domain.basic_auth.auth_pass | length == 0 + block: + # If auth_enabled is defined and yes, and auth_pass is not defined or is defined but empty, generate a random password. + - name: Generate random htauth password. + ansible.builtin.set_fact: + _nginx_htauth_pass: "{{ lookup('password', _ce_provision_data_dir + '/' + inventory_hostname + '/nginx-passwords/' + domain.server_name) }}" + when: + - domain.basic_auth.auth_pass is not defined or domain.basic_auth.auth_pass | length == 0 -# If auth_enabled is defined and yes, and auth_pass is defined and not empty, use that password instead. -- name: Set fact if htauth password is provided. - ansible.builtin.set_fact: - _nginx_htauth_pass: "{{ domain.basic_auth.auth_pass }}" - when: - - domain.basic_auth.auth_enabled is defined - - domain.basic_auth.auth_enabled - - domain.basic_auth.auth_pass is defined - - domain.basic_auth.auth_pass | length > 0 + # If auth_enabled is defined and yes, and auth_pass is defined and not empty, use that password instead. + - name: Set fact if htauth password is provided. + ansible.builtin.set_fact: + _nginx_htauth_pass: "{{ domain.basic_auth.auth_pass }}" + when: + - domain.basic_auth.auth_pass is defined + - domain.basic_auth.auth_pass | length > 0 -- name: Print basic htauth password. - ansible.builtin.debug: - msg: Basic auth password is {{ _nginx_htauth_pass }} - when: - - domain.basic_auth.auth_enabled is defined - - domain.basic_auth.auth_enabled - - _nginx_htauth_pass is defined + - name: Print basic htauth password. + ansible.builtin.debug: + msg: Basic auth password is {{ _nginx_htauth_pass }} + when: + - _nginx_htauth_pass is defined -# Create a basic htauth file if a username is supplied. -- name: Create basic htauth file. - community.general.web_infrastructure.htpasswd: - path: "/etc/nginx/passwords/{{ domain.server_name }}.htpasswd" - name: "{{ domain.basic_auth.auth_user }}" - password: "{{ _nginx_htauth_pass }}" - owner: root - group: root - mode: 0644 - when: - - domain.basic_auth.auth_enabled is defined - - domain.basic_auth.auth_enabled - - domain.basic_auth.auth_user is defined - - domain.basic_auth.auth_user | length > 0 + # Create a basic htauth file if a username is supplied. + - name: Create basic htauth file. + community.general.web_infrastructure.htpasswd: + path: "/etc/nginx/passwords/{{ domain.server_name }}.htpasswd" + name: "{{ domain.basic_auth.auth_user }}" + password: "{{ _nginx_htauth_pass }}" + owner: root + group: root + mode: 0644 + when: + - domain.basic_auth.auth_user is defined + - domain.basic_auth.auth_user | length > 0 -# Place provided basic htauth file if a path is supplied. -- name: Copy basic htauth file to server. - ansible.builtin.copy: - src: "{{ domain.basic_auth.auth_file }}" - dest: "/etc/nginx/passwords/{{ domain.server_name }}.provided.htpasswd" - owner: root - group: root - mode: 0644 - when: - - domain.basic_auth.auth_enabled is defined - - domain.basic_auth.auth_enabled - - domain.basic_auth.auth_file is defined - - domain.basic_auth.auth_file | length > 0 + # Place provided basic htauth file if a path is supplied. + - name: Copy basic htauth file to server. + ansible.builtin.copy: + src: "{{ domain.basic_auth.auth_file }}" + dest: "/etc/nginx/passwords/{{ domain.server_name }}.provided.htpasswd" + owner: root + group: root + mode: 0644 + when: + - domain.basic_auth.auth_file is defined + - domain.basic_auth.auth_file | length > 0 - name: Copy vhost in place. ansible.builtin.template: diff --git a/roles/debian/nginx/tasks/main.yml b/roles/debian/nginx/tasks/main.yml index 65f2ae662..04c2bbc3e 100644 --- a/roles/debian/nginx/tasks/main.yml +++ b/roles/debian/nginx/tasks/main.yml @@ -54,7 +54,6 @@ force: true with_items: - _common - - _common_cloudfront - custom - docker_registry - drupal_common @@ -100,6 +99,7 @@ loop_control: loop_var: domain when: + - domain.ssl is defined - nginx.domains is defined - nginx.domains | length > 0 - nginx.recreate_vhosts diff --git a/roles/debian/nginx/tasks/ssl.yml b/roles/debian/nginx/tasks/ssl.yml index d5a755077..518aa7fc6 100644 --- a/roles/debian/nginx/tasks/ssl.yml +++ b/roles/debian/nginx/tasks/ssl.yml @@ -5,59 +5,48 @@ path: "/etc/nginx/sites-enabled/{{ domain.server_name }}.conf" register: _nginx_vhost_link -- name: Temporarily place a vhost for LetsEncrypt to work. - ansible.builtin.template: - src: vhost_letsencrypt.j2 - dest: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" - owner: root - group: root - mode: 0644 +- name: LetsEncrypt create vhosts. when: - - domain.ssl is defined - domain.ssl.handling == 'letsencrypt' - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 # if services[] is defined we can assume we are running certbot on port 80 or 443 + block: + - name: Temporarily place a vhost for LetsEncrypt to work. + ansible.builtin.template: + src: vhost_letsencrypt.j2 + dest: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" + owner: root + group: root + mode: 0644 -- name: Enable vhost. - ansible.builtin.file: - src: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" - dest: "/etc/nginx/sites-enabled/{{ domain.server_name }}.conf" - state: link - when: - - domain.ssl is defined - - domain.ssl.handling == 'letsencrypt' - - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 + - name: Enable vhost. + ansible.builtin.file: + src: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" + dest: "/etc/nginx/sites-enabled/{{ domain.server_name }}.conf" + state: link -- name: Reload the nginx service. - ansible.builtin.service: - name: nginx - state: reloaded - when: - - domain.ssl is defined - - domain.ssl.handling == 'letsencrypt' - - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 + - name: Reload the nginx service. + ansible.builtin.service: + name: nginx + state: reloaded - name: Generates SSL keys. ansible.builtin.include_role: name: debian/ssl public: true - when: domain.ssl is defined vars: ssl: "{{ domain.ssl }}" -- name: Delete the link to the vhost for LetsEncrypt. - ansible.builtin.file: - path: "/etc/nginx/sites-enabled/{{ domain.server_name }}.conf" - state: absent +- name: LetsEncrypt cleanup vhosts. when: - - domain.ssl is defined - domain.ssl.handling == 'letsencrypt' - - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 + - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 # if services[] is defined we can assume we are running certbot on port 80 or 443 + block: + - name: Delete the link to the vhost for LetsEncrypt. + ansible.builtin.file: + path: "/etc/nginx/sites-enabled/{{ domain.server_name }}.conf" + state: absent -- name: Delete the temporary vhost for LetsEncrypt. - ansible.builtin.file: - path: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" - state: absent - when: - - domain.ssl is defined - - domain.ssl.handling == 'letsencrypt' - - _nginx_vhost_link.stat.islnk is not defined or domain.ssl.services | length > 0 + - name: Delete the temporary vhost for LetsEncrypt. + ansible.builtin.file: + path: "/etc/nginx/sites-available/{{ domain.server_name }}.conf" + state: absent diff --git a/roles/debian/nginx/templates/_common.j2 b/roles/debian/nginx/templates/_common.j2 index 79b1b114c..6129a309d 100644 --- a/roles/debian/nginx/templates/_common.j2 +++ b/roles/debian/nginx/templates/_common.j2 @@ -3,7 +3,7 @@ gzip on; gzip_proxied any; gzip_static on; -gzip_http_version 1.0; +gzip_http_version 1.1; gzip_disable "MSIE [1-6]\."; gzip_vary {{ nginx.http.gzip_vary }}; gzip_comp_level 6; diff --git a/roles/debian/nginx/templates/_common_cloudfront.j2 b/roles/debian/nginx/templates/_common_cloudfront.j2 deleted file mode 100644 index f448699e0..000000000 --- a/roles/debian/nginx/templates/_common_cloudfront.j2 +++ /dev/null @@ -1,11 +0,0 @@ -### {{ ansible_managed }} - -gzip off; -proxy_buffer_size {{ nginx.http.proxy_buffer_size }}; -proxy_buffers {{ nginx.http.proxy_buffers }}; -client_body_buffer_size {{ nginx.http.client_body_buffer_size }}; -fastcgi_buffer_size {{ nginx.http.fastcgi_buffer_size }} ; -fastcgi_buffers {{ nginx.http.fastcgi_buffers }} ; -client_max_body_size {{ nginx.client_max_body_size }} ; -# Disable content sniffing, since it's an attack vector. -add_header X-Content-Type-Options nosniff; \ No newline at end of file diff --git a/roles/debian/nginx/templates/drupal10.j2 b/roles/debian/nginx/templates/drupal10.j2 index b9aac5f1b..2bef01860 100644 --- a/roles/debian/nginx/templates/drupal10.j2 +++ b/roles/debian/nginx/templates/drupal10.j2 @@ -97,25 +97,35 @@ location ~* /(?:modules|libraries)/(?:contrib/)?(?:ad|tinybrowser|f?ckeditor|tin # Allow private files support location ~* ^/system/files/.*\.(png|jpg|jpeg|gif|ico|svg)$ { # If the image does not exist, it must be a private file. try_files $uri @rewrite; - expires 7d; +{% if nginx.http.cache_behavior_private %} + {{ nginx.http.cache_behavior_private }}; +{% endif %} log_not_found off; } # For Drupal 10 onwards this has changed - see https://www.drupal.org/node/2888767#nginx-php-fpm location ~ ^/sites/.*/files/(css|js|styles)/ { try_files $uri @rewrite_drupal10; - expires 7d; +{% if nginx.http.cache_behavior_public %} + {{ nginx.http.cache_behavior_public }}; +{% endif %} } # Allow public files and image styles. location ~ ^/sites/.*/files/.* { try_files $uri @rewrite; +{% if nginx.http.cache_behavior_public %} + {{ nginx.http.cache_behavior_public }}; +{% endif %} } # This Nginx config is DENY FIRST, so only these file extensions are permitted. # Core and contrib assets can be pretty much anywhere. location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|eot|woff2|ttf|otf)$ { try_files $uri @rewrite =404; +{% if nginx.http.cache_behavior_public %} + {{ nginx.http.cache_behavior_public }}; +{% endif %} } # Allow robots.txt. diff --git a/roles/debian/nginx/templates/drupal_common.j2 b/roles/debian/nginx/templates/drupal_common.j2 index dee6f0af9..e87a61702 100644 --- a/roles/debian/nginx/templates/drupal_common.j2 +++ b/roles/debian/nginx/templates/drupal_common.j2 @@ -89,19 +89,26 @@ location ~* /(?:modules|libraries)/(?:contrib/)?(?:ad|tinybrowser|f?ckeditor|tin # Allow public files and image styles. location ~ ^/sites/.*/files/.* { try_files $uri @rewrite; +{% if nginx.http.cache_behavior_public %} + {{ nginx.http.cache_behavior_public }}; +{% endif %} } # Allow private files support location ~* ^/system/files/.*\.(png|jpg|jpeg|gif|ico|svg)$ { # If the image does not exist, it must be a private file. try_files $uri @rewrite; - expires 7d; - log_not_found off; +{% if nginx.http.cache_behavior_private %} + {{ nginx.http.cache_behavior_private }}; +{% endif %} } # This Nginx config is DENY FIRST, so only these file extensions are permitted. # Core and contrib assets can be pretty much anywhere. location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|eot|woff2|ttf|otf)$ { try_files $uri @rewrite =404; +{% if nginx.http.cache_behavior_public %} + {{ nginx.http.cache_behavior_public }}; +{% endif %} } # Allow robots.txt. diff --git a/roles/debian/nginx/templates/vhost_letsencrypt.j2 b/roles/debian/nginx/templates/vhost_letsencrypt.j2 index 72a5cdd45..b3f85d544 100644 --- a/roles/debian/nginx/templates/vhost_letsencrypt.j2 +++ b/roles/debian/nginx/templates/vhost_letsencrypt.j2 @@ -1,7 +1,7 @@ ### {{ ansible_managed }} server { - listen 443; + listen 80; server_name {{ domain.server_name }}; error_log {{ domain.error_log }} {{ domain.error_log_level }}; access_log {{ domain.access_log }} {{ domain.access_log_format | default('main') }}; diff --git a/roles/debian/nginx/templates/vhosts.j2 b/roles/debian/nginx/templates/vhosts.j2 index d16b3df96..9cf7b514a 100644 --- a/roles/debian/nginx/templates/vhosts.j2 +++ b/roles/debian/nginx/templates/vhosts.j2 @@ -28,11 +28,7 @@ server { access_log {{ domain.access_log }} {{ domain.access_log_format | default('main') }}; root "{{ domain.webroot }}"; include "/etc/nginx/conf.d/{{ domain.project_type }}"; -{% if domain.is_behind_cloudfront is defined and domain.is_behind_cloudfront %} - include "/etc/nginx/conf.d/_common_cloudfront"; -{% else %} include "/etc/nginx/conf.d/_common"; -{% endif %} {% if domain.ssl is defined and domain.ssl.handling == 'letsencrypt' %} {% if domain.ssl.web_server | default('standalone') == 'standalone' %} # Proxy for certbot (LetsEncrypt)