From 1fc880900a07374cf269ce9a5925b6fb9c3ca22e Mon Sep 17 00:00:00 2001 From: Sylvain Arrachart Date: Tue, 10 Oct 2023 16:27:53 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Cr=C3=A9ation=20du=20r=C3=B4le=20site=5Fsta?= =?UTF-8?q?tic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roles/site_static/README.md | 38 +++++++++++++++++++++ roles/site_static/defaults/main.yml | 2 ++ roles/site_static/handlers/main.yml | 2 ++ roles/site_static/meta/main.yml | 52 +++++++++++++++++++++++++++++ roles/site_static/tasks/main.yml | 2 ++ roles/site_static/vars/main.yml | 2 ++ 6 files changed, 98 insertions(+) create mode 100644 roles/site_static/README.md create mode 100644 roles/site_static/defaults/main.yml create mode 100644 roles/site_static/handlers/main.yml create mode 100644 roles/site_static/meta/main.yml create mode 100644 roles/site_static/tasks/main.yml create mode 100644 roles/site_static/vars/main.yml diff --git a/roles/site_static/README.md b/roles/site_static/README.md new file mode 100644 index 00000000..225dd44b --- /dev/null +++ b/roles/site_static/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/site_static/defaults/main.yml b/roles/site_static/defaults/main.yml new file mode 100644 index 00000000..324a816b --- /dev/null +++ b/roles/site_static/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for site_static diff --git a/roles/site_static/handlers/main.yml b/roles/site_static/handlers/main.yml new file mode 100644 index 00000000..4cc253b8 --- /dev/null +++ b/roles/site_static/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for site_static diff --git a/roles/site_static/meta/main.yml b/roles/site_static/meta/main.yml new file mode 100644 index 00000000..c572acc9 --- /dev/null +++ b/roles/site_static/meta/main.yml @@ -0,0 +1,52 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/roles/site_static/tasks/main.yml b/roles/site_static/tasks/main.yml new file mode 100644 index 00000000..36043a42 --- /dev/null +++ b/roles/site_static/tasks/main.yml @@ -0,0 +1,2 @@ +--- +# tasks file for site_static diff --git a/roles/site_static/vars/main.yml b/roles/site_static/vars/main.yml new file mode 100644 index 00000000..e2fb1aad --- /dev/null +++ b/roles/site_static/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for site_static -- GitLab From 6f7c0885190be6bfba7df42e5a06ba0e8c5f4475 Mon Sep 17 00:00:00 2001 From: oiseauroch Date: Wed, 11 Oct 2023 11:59:39 +0200 Subject: [PATCH 2/5] create static role --- roles/site_static/defaults/main.yml | 3 + roles/site_static/files/50-mod-brotli.conf | 1 + roles/site_static/tasks/install.yml | 40 +++++++++++ roles/site_static/tasks/main.yml | 8 +++ roles/site_static/tasks/nginx_brotli.yml | 52 +++++++++++++++ roles/site_static/tasks/uninstall.yml | 0 roles/site_static/tasks/update.yml | 0 roles/site_static/templates/nginx.j2 | 78 ++++++++++++++++++++++ 8 files changed, 182 insertions(+) create mode 100644 roles/site_static/files/50-mod-brotli.conf create mode 100644 roles/site_static/tasks/install.yml create mode 100644 roles/site_static/tasks/nginx_brotli.yml create mode 100644 roles/site_static/tasks/uninstall.yml create mode 100644 roles/site_static/tasks/update.yml create mode 100644 roles/site_static/templates/nginx.j2 diff --git a/roles/site_static/defaults/main.yml b/roles/site_static/defaults/main.yml index 324a816b..b67875c0 100644 --- a/roles/site_static/defaults/main.yml +++ b/roles/site_static/defaults/main.yml @@ -1,2 +1,5 @@ --- # defaults file for site_static +app_instance_root: "{{ www_root }}/{{ app_instance_id }}" +app_instance_www_root: "{{ app_instance_root }}" +site_src: public diff --git a/roles/site_static/files/50-mod-brotli.conf b/roles/site_static/files/50-mod-brotli.conf new file mode 100644 index 00000000..9f7b7ed8 --- /dev/null +++ b/roles/site_static/files/50-mod-brotli.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_brotli_filter_module.so; # for compressing responses on-the-fly \ No newline at end of file diff --git a/roles/site_static/tasks/install.yml b/roles/site_static/tasks/install.yml new file mode 100644 index 00000000..348dc27e --- /dev/null +++ b/roles/site_static/tasks/install.yml @@ -0,0 +1,40 @@ +--- + +- name: create directory + file: + path: "{{ app_instance_www_root }}" + state: directory + +- name: Create LetsEncrypt certificate + import_role: + name: _letsencrypt_certificate + +- name: Copy site from the Tower + copy: + src: "{{ site_src }}" + dest: "{{ app_instance_www_root }}" + remote_src: false + +- import_tasks: nginx_brotli.yml + +- name: "enable module for {{ app_domain }}" + copy: + src: "files/50-mod-brotli.conf" + dest: "/etc/nginx/modules-enabled/{{ app_instance_id }}.conf" + remote_src: false + notify: reload nginx + + +- name: nginx configuration + template: + src: nginx.j2 + dest: "/etc/nginx/sites-available/{{ app_instance_id }}.conf" + +- name: "enable site for {{ app_domain }}" + file: + state: link + path: "/etc/nginx/sites-enabled/{{ app_instance_id }}.conf" + src: "/etc/nginx/sites-available/{{ app_instance_id }}.conf" + notify: reload nginx + + diff --git a/roles/site_static/tasks/main.yml b/roles/site_static/tasks/main.yml index 36043a42..18398295 100644 --- a/roles/site_static/tasks/main.yml +++ b/roles/site_static/tasks/main.yml @@ -1,2 +1,10 @@ --- # tasks file for site_static +- import_tasks: install.yml + when: app_run in ['install', 'reinstall'] + +- import_tasks: upgrade.yml + when: app_run == 'upgrade' + +- import_tasks: uninstall.yml + when: app_run == 'uninstall' \ No newline at end of file diff --git a/roles/site_static/tasks/nginx_brotli.yml b/roles/site_static/tasks/nginx_brotli.yml new file mode 100644 index 00000000..caeaa461 --- /dev/null +++ b/roles/site_static/tasks/nginx_brotli.yml @@ -0,0 +1,52 @@ +### Brotli Install +- name: Gather the apt package facts + package_facts: + manager: auto + +- name: Get Nginx version and set variable + set_fact: + nginx_version: "{{ ansible_facts.packages['nginx'][0].version | regex_search('^[0-9.]*') }}" + +- name: Check if module is present (and if so skip nginx compiling) + stat: + path: /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so + become: yes + register: module_exists + +- name: Download and unarchive Nginx source code of version {{ nginx_version }} + unarchive: + src: https://nginx.org/download/nginx-{{ nginx_version }}.tar.gz + dest: ~/ + remote_src: yes + when: not module_exists.stat.exists + +- name: Git clone Brotli module (google/ngx_brotli) + git: + repo: https://github.com/google/ngx_brotli.git + dest: ~/ngx_brotli + when: not module_exists.stat.exists + +- name: Configure Brotli module + command: + chdir: ~/nginx-{{ nginx_version }} + cmd: ./configure --with-compat --add-dynamic-module=../ngx_brotli + when: not module_exists.stat.exists + +- name: Make Brotli module (Dynamically loaded) + make: + chdir: ~/nginx-{{ nginx_version }} + target: modules + when: not module_exists.stat.exists + +- name: Copy compiled Brotli module to /usr/share/nginx/modules + copy: + remote_src: yes + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: 0644 + with_items: + - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_filter_module.so", dest: "/usr/share/nginx/modules" } + - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_static_module.so", dest: "/usr/share/nginx/modules" } + when: not module_exists.stat.exists \ No newline at end of file diff --git a/roles/site_static/tasks/uninstall.yml b/roles/site_static/tasks/uninstall.yml new file mode 100644 index 00000000..e69de29b diff --git a/roles/site_static/tasks/update.yml b/roles/site_static/tasks/update.yml new file mode 100644 index 00000000..e69de29b diff --git a/roles/site_static/templates/nginx.j2 b/roles/site_static/templates/nginx.j2 new file mode 100644 index 00000000..2500fe0e --- /dev/null +++ b/roles/site_static/templates/nginx.j2 @@ -0,0 +1,78 @@ +server { + listen 80; + listen [::]:80; + server_name {{ app_domain | mandatory }}; + # enforce https + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name {{ app_domain | mandatory }}; + + ssl_certificate /etc/letsencrypt/live/{{ app_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ app_domain }}/privkey.pem; + + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Robots-Tag none; + add_header X-Download-Options noopen; + add_header X-Permitted-Cross-Domain-Policies none; + add_header Strict-Transport-Security "max-age=15768000"; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; + + + root {{ app_instance_www_root }}; + + access_log {{ www_log | mandatory }}/{{ app_instance_id }}/access.log; + error_log {{ www_log | mandatory }}/{{ app_instance_id }}/error.log; + + index index.html; + + location = /favicon.ico { # Optional + log_not_found off; + access_log off; + } + + location = /robots.txt { # Optional + allow all; + log_not_found off; + access_log off; + } + + location ~* \.(png|jpg|jpeg|gif|ico)$ { # Optional + expires max; + log_not_found off; + } + + location / { + # improve performance for static content inspired by + # https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/ + sendfile on; + sendfile_max_chunk 2m; + tcp_nopush on; + # compression + # Enable gzip but do not remove ETag headers + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + # Brotli Settings + brotli on; + brotli_comp_level 4; + brotli_buffers 32 8k; + brotli_min_length 100; + brotli_static on; + brotli_types image/jpeg image/bmp image/svg+xml text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon; + + expires 7d; + } +} -- GitLab From b798ddc3b81eed857eb7d5ea428d60398ec48271 Mon Sep 17 00:00:00 2001 From: Admin paquerette Date: Wed, 11 Oct 2023 16:53:08 +0200 Subject: [PATCH 3/5] create role static --- .gitignore | 1 + roles/site_static/handlers/main.yml | 5 +++++ roles/site_static/tasks/install.yml | 15 +++++---------- roles/site_static/tasks/nginx_brotli.yml | 17 ++++++++++++++++- roles/site_static/tasks/upgrade.yml | 0 roles/site_static/templates/nginx.j2 | 10 +--------- 6 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 roles/site_static/tasks/upgrade.yml diff --git a/.gitignore b/.gitignore index 48943b8d..3f2c88db 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ releases/* contract/* paquerette_utils.conf.yml hz_token +public/ # IDE .idea diff --git a/roles/site_static/handlers/main.yml b/roles/site_static/handlers/main.yml index 4cc253b8..5d62aff8 100644 --- a/roles/site_static/handlers/main.yml +++ b/roles/site_static/handlers/main.yml @@ -1,2 +1,7 @@ --- # handlers file for site_static +# handlers file for rustform + +- name: reload nginx + service: name=nginx state=reloaded + diff --git a/roles/site_static/tasks/install.yml b/roles/site_static/tasks/install.yml index 348dc27e..ecec9130 100644 --- a/roles/site_static/tasks/install.yml +++ b/roles/site_static/tasks/install.yml @@ -14,16 +14,11 @@ src: "{{ site_src }}" dest: "{{ app_instance_www_root }}" remote_src: false - -- import_tasks: nginx_brotli.yml - -- name: "enable module for {{ app_domain }}" - copy: - src: "files/50-mod-brotli.conf" - dest: "/etc/nginx/modules-enabled/{{ app_instance_id }}.conf" - remote_src: false - notify: reload nginx - + +- name: create log dir + file: + state: directory + path: "/mnt/vdb/log/nginx/{{ app_instance_id }}" - name: nginx configuration template: diff --git a/roles/site_static/tasks/nginx_brotli.yml b/roles/site_static/tasks/nginx_brotli.yml index caeaa461..2b24e0e0 100644 --- a/roles/site_static/tasks/nginx_brotli.yml +++ b/roles/site_static/tasks/nginx_brotli.yml @@ -12,6 +12,21 @@ path: /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so become: yes register: module_exists + +- name: install dependencies + apt: + name: + - curl + - build-essential + - vim + - dpkg-dev + - gnupg2 + - libpcre3 + - zlib1g-dev + - libpcre3-dev + update_cache: yes + state: present + when: not module_exists.stat.exists - name: Download and unarchive Nginx source code of version {{ nginx_version }} unarchive: @@ -49,4 +64,4 @@ with_items: - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_filter_module.so", dest: "/usr/share/nginx/modules" } - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_static_module.so", dest: "/usr/share/nginx/modules" } - when: not module_exists.stat.exists \ No newline at end of file + when: not module_exists.stat.exists diff --git a/roles/site_static/tasks/upgrade.yml b/roles/site_static/tasks/upgrade.yml new file mode 100644 index 00000000..e69de29b diff --git a/roles/site_static/templates/nginx.j2 b/roles/site_static/templates/nginx.j2 index 2500fe0e..d697708d 100644 --- a/roles/site_static/templates/nginx.j2 +++ b/roles/site_static/templates/nginx.j2 @@ -27,7 +27,7 @@ server { add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; - root {{ app_instance_www_root }}; + root {{ app_instance_www_root }}/public; access_log {{ www_log | mandatory }}/{{ app_instance_id }}/access.log; error_log {{ www_log | mandatory }}/{{ app_instance_id }}/error.log; @@ -65,14 +65,6 @@ server { gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; - # Brotli Settings - brotli on; - brotli_comp_level 4; - brotli_buffers 32 8k; - brotli_min_length 100; - brotli_static on; - brotli_types image/jpeg image/bmp image/svg+xml text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon; - expires 7d; } } -- GitLab From 1d7d34ff112b2d7fc65d457b53d2f5916820b4ba Mon Sep 17 00:00:00 2001 From: oiseauroch Date: Wed, 11 Oct 2023 17:12:16 +0200 Subject: [PATCH 4/5] update README --- roles/site_static/README.md | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/roles/site_static/README.md b/roles/site_static/README.md index 225dd44b..fb44487f 100644 --- a/roles/site_static/README.md +++ b/roles/site_static/README.md @@ -1,38 +1,37 @@ -Role Name -========= +# site_statitque -A brief description of the role goes here. +Installation d'un environement pour servir un site statique -Requirements ------------- +## Files created -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +- `/etc/letsencrypt/live/{{ app_domain }}/` : certificats lets encrypt +- `{{ app_instance_www_root}} : dossier servi par nginx +- `/mnt/vdb/log/nginx/{{ app_instance_id }}` : fichier de log nginx +- `/etc/nginx/sites-available/{{ app_instance_id }}.conf : fichier de conf nginx +- `/etc/nginx/sites-enabled/{{ app_instance_id }}.conf : lien symbolique fichier de conf nginx -Role Variables --------------- +## Files modified -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +## Role dependency -Dependencies ------------- +- _letsencrypt_certificate -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. +## Variables -Example Playbook ----------------- +### Default + - app_instance_root: "{{ www_root }}/{{ app_instance_id }}" + - app_instance_www_root: "{{ app_instance_root }}" + -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: +### host_vars + + - app_domain + - app_instance_id + - site_src - - hosts: servers - roles: - - { role: username.rolename, x: 42 } +## Custom instructions -License -------- -BSD +## Limitations and improvements -Author Information ------------------- - -An optional section for the role authors to include contact information, or a website (HTML is not allowed). + - [ ] add brotli compression -- GitLab From b3bc2abf00031c6e765c122ca4dcb93a5cf63965 Mon Sep 17 00:00:00 2001 From: oiseauroch Date: Wed, 11 Oct 2023 19:22:44 +0200 Subject: [PATCH 5/5] resolving review --- roles/site_static/files/50-mod-brotli.conf | 1 - roles/site_static/tasks/nginx_brotli.yml | 67 ---------------------- 2 files changed, 68 deletions(-) delete mode 100644 roles/site_static/files/50-mod-brotli.conf delete mode 100644 roles/site_static/tasks/nginx_brotli.yml diff --git a/roles/site_static/files/50-mod-brotli.conf b/roles/site_static/files/50-mod-brotli.conf deleted file mode 100644 index 9f7b7ed8..00000000 --- a/roles/site_static/files/50-mod-brotli.conf +++ /dev/null @@ -1 +0,0 @@ -load_module modules/ngx_http_brotli_filter_module.so; # for compressing responses on-the-fly \ No newline at end of file diff --git a/roles/site_static/tasks/nginx_brotli.yml b/roles/site_static/tasks/nginx_brotli.yml deleted file mode 100644 index 2b24e0e0..00000000 --- a/roles/site_static/tasks/nginx_brotli.yml +++ /dev/null @@ -1,67 +0,0 @@ -### Brotli Install -- name: Gather the apt package facts - package_facts: - manager: auto - -- name: Get Nginx version and set variable - set_fact: - nginx_version: "{{ ansible_facts.packages['nginx'][0].version | regex_search('^[0-9.]*') }}" - -- name: Check if module is present (and if so skip nginx compiling) - stat: - path: /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so - become: yes - register: module_exists - -- name: install dependencies - apt: - name: - - curl - - build-essential - - vim - - dpkg-dev - - gnupg2 - - libpcre3 - - zlib1g-dev - - libpcre3-dev - update_cache: yes - state: present - when: not module_exists.stat.exists - -- name: Download and unarchive Nginx source code of version {{ nginx_version }} - unarchive: - src: https://nginx.org/download/nginx-{{ nginx_version }}.tar.gz - dest: ~/ - remote_src: yes - when: not module_exists.stat.exists - -- name: Git clone Brotli module (google/ngx_brotli) - git: - repo: https://github.com/google/ngx_brotli.git - dest: ~/ngx_brotli - when: not module_exists.stat.exists - -- name: Configure Brotli module - command: - chdir: ~/nginx-{{ nginx_version }} - cmd: ./configure --with-compat --add-dynamic-module=../ngx_brotli - when: not module_exists.stat.exists - -- name: Make Brotli module (Dynamically loaded) - make: - chdir: ~/nginx-{{ nginx_version }} - target: modules - when: not module_exists.stat.exists - -- name: Copy compiled Brotli module to /usr/share/nginx/modules - copy: - remote_src: yes - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ ansible_user }}" - group: "{{ ansible_user }}" - mode: 0644 - with_items: - - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_filter_module.so", dest: "/usr/share/nginx/modules" } - - { src: "~/nginx-{{ nginx_version }}/objs/ngx_http_brotli_static_module.so", dest: "/usr/share/nginx/modules" } - when: not module_exists.stat.exists -- GitLab