From 32b6a49bc8f28b4d2cec87487a68284b109bea45 Mon Sep 17 00:00:00 2001 From: Maxim Vershinin Date: Sun, 6 Sep 2026 19:50:08 +0500 Subject: [PATCH] feat (role): adds nginx installation role, tests are required --- roles/install_nginx/files/nginx/.htpasswd | 1 + roles/install_nginx/files/nginx/.htpasswd_old | 1 + roles/install_nginx/files/nginx/fastcgi.conf | 27 +++++ .../install_nginx/files/nginx/fastcgi_params | 57 ++++++++++ roles/install_nginx/files/nginx/mime.types | 101 ++++++++++++++++++ .../modules-enabled/50-mod-http-auth-pam.conf | 1 + .../modules-enabled/50-mod-http-dav-ext.conf | 1 + .../modules-enabled/50-mod-http-echo.conf | 1 + .../modules-enabled/50-mod-http-geoip2.conf | 1 + .../50-mod-http-subs-filter.conf | 1 + .../50-mod-http-upstream-fair.conf | 1 + .../nginx/modules-enabled/50-mod-stream.conf | 1 + .../modules-enabled/70-mod-stream-geoip2.conf | 1 + roles/install_nginx/files/nginx/nginx.conf | 24 +++++ roles/install_nginx/files/nginx/proxy_params | 33 ++++++ .../files/nginx/snippets/error_pages.conf | 1 + .../nginx/snippets/error_pages_content.conf | 1 + .../files/nginx/snippets/fastcgi-php.conf | 13 +++ roles/install_nginx/tasks/main.yaml | 30 ++++++ 19 files changed, 297 insertions(+) create mode 100644 roles/install_nginx/files/nginx/.htpasswd create mode 100644 roles/install_nginx/files/nginx/.htpasswd_old create mode 100644 roles/install_nginx/files/nginx/fastcgi.conf create mode 100644 roles/install_nginx/files/nginx/fastcgi_params create mode 100644 roles/install_nginx/files/nginx/mime.types create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-auth-pam.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-dav-ext.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-echo.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-geoip2.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-subs-filter.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-http-upstream-fair.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/50-mod-stream.conf create mode 120000 roles/install_nginx/files/nginx/modules-enabled/70-mod-stream-geoip2.conf create mode 100644 roles/install_nginx/files/nginx/nginx.conf create mode 100644 roles/install_nginx/files/nginx/proxy_params create mode 120000 roles/install_nginx/files/nginx/snippets/error_pages.conf create mode 120000 roles/install_nginx/files/nginx/snippets/error_pages_content.conf create mode 100644 roles/install_nginx/files/nginx/snippets/fastcgi-php.conf create mode 100644 roles/install_nginx/tasks/main.yaml diff --git a/roles/install_nginx/files/nginx/.htpasswd b/roles/install_nginx/files/nginx/.htpasswd new file mode 100644 index 0000000..eb63321 --- /dev/null +++ b/roles/install_nginx/files/nginx/.htpasswd @@ -0,0 +1 @@ +max:$apr1$NPIFdkB/$hya7NW2rdTGEKBDm0PH3g0 diff --git a/roles/install_nginx/files/nginx/.htpasswd_old b/roles/install_nginx/files/nginx/.htpasswd_old new file mode 100644 index 0000000..afeaf23 --- /dev/null +++ b/roles/install_nginx/files/nginx/.htpasswd_old @@ -0,0 +1 @@ +max:$apr1$/3oBTCwW$u9OMKSD56v8czs5rZ0rDp0 diff --git a/roles/install_nginx/files/nginx/fastcgi.conf b/roles/install_nginx/files/nginx/fastcgi.conf new file mode 100644 index 0000000..d53a628 --- /dev/null +++ b/roles/install_nginx/files/nginx/fastcgi.conf @@ -0,0 +1,27 @@ + +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/roles/install_nginx/files/nginx/fastcgi_params b/roles/install_nginx/files/nginx/fastcgi_params new file mode 100644 index 0000000..71c1c94 --- /dev/null +++ b/roles/install_nginx/files/nginx/fastcgi_params @@ -0,0 +1,57 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; + +# !!! Security workaround !!! +# Do not use HTTP_HOST as "$http_host". +# +# "$http_host" is the Host header exactly as supplied by the client. +# This is unsafe when a client sends an absolute-form request target together +# with a different Host header, for example: +# +# GET https://example.com/ HTTP/1.1 +# Host: malformedhost +# +# In such a case, passing "$http_host" upstream exposes the raw client-supplied +# Host value ("malformedhost") to the backend application, even though it does +# not match the effective request target. Applications often use HTTP_HOST for +# redirects, absolute URL generation, virtual host routing, or security checks; +# forwarding the raw Host header can therefore lead to incorrect or unsafe +# behaviour. +# +# Newer nginx versions (since 1.30.0) introduce variables "$is_request_port" and +# "$request_port", allowing HTTP_HOST to be constructed as: +# $host$is_request_port$request_port +# +# In stable/oldstable packages we use "$host" as a security workaround. +# It avoids forwarding an untrusted raw Host header to the backend. +# +# Note: this changes behaviour compared to previous versions, because "$host" +# does not preserve the client-supplied port, while "$http_host" typically +# does. Existing deployments that rely on "$http_host" containing a port number +# may therefore break or behave differently after this change. + +fastcgi_param HTTP_HOST $host; diff --git a/roles/install_nginx/files/nginx/mime.types b/roles/install_nginx/files/nginx/mime.types new file mode 100644 index 0000000..cf968c0 --- /dev/null +++ b/roles/install_nginx/files/nginx/mime.types @@ -0,0 +1,101 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/avif avif; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + font/woff woff; + font/woff2 woff2; + + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/wasm wasm; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xslt+xml xsl xslt; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-matroska mkv; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-auth-pam.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-auth-pam.conf new file mode 120000 index 0000000..2c9098d --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-auth-pam.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-auth-pam.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-dav-ext.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-dav-ext.conf new file mode 120000 index 0000000..4bcd08d --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-dav-ext.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-dav-ext.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-echo.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-echo.conf new file mode 120000 index 0000000..2ca55aa --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-echo.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-echo.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-geoip2.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-geoip2.conf new file mode 120000 index 0000000..e2655c3 --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-geoip2.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-geoip2.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-subs-filter.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-subs-filter.conf new file mode 120000 index 0000000..60fc893 --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-subs-filter.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-subs-filter.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-upstream-fair.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-upstream-fair.conf new file mode 120000 index 0000000..2dc0c72 --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-http-upstream-fair.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-http-upstream-fair.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/50-mod-stream.conf b/roles/install_nginx/files/nginx/modules-enabled/50-mod-stream.conf new file mode 120000 index 0000000..7f65cc5 --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/50-mod-stream.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-stream.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/modules-enabled/70-mod-stream-geoip2.conf b/roles/install_nginx/files/nginx/modules-enabled/70-mod-stream-geoip2.conf new file mode 120000 index 0000000..612a5e1 --- /dev/null +++ b/roles/install_nginx/files/nginx/modules-enabled/70-mod-stream-geoip2.conf @@ -0,0 +1 @@ +/usr/share/nginx/modules-available/mod-stream-geoip2.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/nginx.conf b/roles/install_nginx/files/nginx/nginx.conf new file mode 100644 index 0000000..015ecd1 --- /dev/null +++ b/roles/install_nginx/files/nginx/nginx.conf @@ -0,0 +1,24 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; +include /etc/nginx/modules-enabled/*.conf; + + +events { + worker_connections 768; +} + +http { + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent"'; + include /etc/nginx/conf.d/*.conf; + + # Hide NGINX version from responses + server_tokens off; + # Use modern TLS protocols only + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; +} diff --git a/roles/install_nginx/files/nginx/proxy_params b/roles/install_nginx/files/nginx/proxy_params new file mode 100644 index 0000000..8ef8794 --- /dev/null +++ b/roles/install_nginx/files/nginx/proxy_params @@ -0,0 +1,33 @@ +# !!! Security workaround !!! +# Do not set the `Host` header as "$http_host". +# +# "$http_host" is the Host header exactly as supplied by the client. +# This is unsafe when a client sends an absolute-form request target together +# with a different Host header, for example: +# +# GET https://example.com/ HTTP/1.1 +# Host: malformedhost +# +# In such a case, passing "$http_host" upstream exposes the raw client-supplied +# Host value ("malformedhost") to the backend application, even though it does +# not match the effective request target. Applications often use HTTP_HOST for +# redirects, absolute URL generation, virtual host routing, or security checks; +# forwarding the raw Host header can therefore lead to incorrect or unsafe +# behaviour. +# +# Newer nginx versions (since 1.30.0) introduce variables "$is_request_port" and +# "$request_port", allowing `Host` to be constructed as: +# $host$is_request_port$request_port +# +# In stable/oldstable packages we use "$host" as a security workaround. +# It avoids forwarding an untrusted raw Host header to the backend. +# +# Note: this changes behaviour compared to previous versions, because "$host" +# does not preserve the client-supplied port, while "$http_host" typically +# does. Existing deployments that rely on "$http_host" containing a port number +# may therefore break or behave differently after this change. + +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; diff --git a/roles/install_nginx/files/nginx/snippets/error_pages.conf b/roles/install_nginx/files/nginx/snippets/error_pages.conf new file mode 120000 index 0000000..361f567 --- /dev/null +++ b/roles/install_nginx/files/nginx/snippets/error_pages.conf @@ -0,0 +1 @@ +/srv/http/default/snippets/error_pages.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/snippets/error_pages_content.conf b/roles/install_nginx/files/nginx/snippets/error_pages_content.conf new file mode 120000 index 0000000..44a9b3a --- /dev/null +++ b/roles/install_nginx/files/nginx/snippets/error_pages_content.conf @@ -0,0 +1 @@ +/srv/http/default/snippets/error_pages_content.conf \ No newline at end of file diff --git a/roles/install_nginx/files/nginx/snippets/fastcgi-php.conf b/roles/install_nginx/files/nginx/snippets/fastcgi-php.conf new file mode 100644 index 0000000..467a9e7 --- /dev/null +++ b/roles/install_nginx/files/nginx/snippets/fastcgi-php.conf @@ -0,0 +1,13 @@ +# regex to split $uri to $fastcgi_script_name and $fastcgi_path +fastcgi_split_path_info ^(.+?\.php)(/.*)$; + +# Check that the PHP script exists before passing it +try_files $fastcgi_script_name =404; + +# Bypass the fact that try_files resets $fastcgi_path_info +# see: http://trac.nginx.org/nginx/ticket/321 +set $path_info $fastcgi_path_info; +fastcgi_param PATH_INFO $path_info; + +fastcgi_index index.php; +include fastcgi.conf; diff --git a/roles/install_nginx/tasks/main.yaml b/roles/install_nginx/tasks/main.yaml new file mode 100644 index 0000000..33afb3e --- /dev/null +++ b/roles/install_nginx/tasks/main.yaml @@ -0,0 +1,30 @@ +--- + +- name: Install NGINX on apt-based systems + become: true + ansible.builtin.apt: + name: nginx + state: present + update_cache: true + +- name: Enable systemd service + ansible.builtin.service: + name: nginx + state: started + enabled: true + +# We don't want to activate this config right away, so push it after service started +- name: Configure NGINX, by pushing the config directory + become: true + ansible.builtin.copy: + src: "{{ role_path }}/files/nginx" + dst: "/etc/nginx" + +- name: Install custom error pages + become: true + ansible.builtin.shell: | + mkdir -p /srv/http/default + git clone https://github.com/denysvitali/nginx-error-pages /srv/http/default + ln -s /srv/http/default/snippets/error_pages.conf /etc/nginx/snippets/error_pages.conf + ln -s /srv/http/default/snippets/error_pages_content.conf /etc/nginx/snippets/error_pages_content.conf +