{% macro nginx_option(option) -%} {% if option.value is boolean -%} {{ option.key | lower }} {{ 'on' if option.value else 'off' }}; {% elif option.value is string -%} {{ option.key | lower }} {{ option.value }}; {% elif option.value | type_debug == "list" -%} {% if option.key in nginx_multi_list -%} {% for suboption in option.value -%} {{ option.key | lower }} {{ suboption }}; {% endfor -%} {% else -%} {{ option.key | lower }} {{ option.value | join(nginx_list_join[option.key] | d(' ')) }}; {% endif -%} {% endif -%} {% endmacro -%} {% macro nginx_option_block(block) -%} {% if block | type_debug == 'dict' -%} {% for option in (block | d({}) | dict2items) -%} {{ nginx_option(option) -}} {% endfor -%} {% endif -%} {% endmacro -%} {%- macro nginx_include(conf, dir) -%} include {{ (nginx_cfg.conf_dir ~ '/' ~ (dir | d('custom')) ~ '/' ~ conf ~ '.conf') | quote -}}; {%- endmacro -%} {% macro nginx_security_headers(source) -%} {% set nginx_sel_source = (source | d(nginx_cfg)) -%} {% for header in (nginx_sel_source.security.headers | d({}) | dict2items) -%} {% if header.value is string -%} add_header {{ header.key ~ ' "' ~ header.value ~ '"' }} always; {% endif -%} {% endfor -%} {% if (nginx_sel_source.security.csp is mapping) and (nginx_sel_source.security.csp | d({}) | dict2items | length) > 0 -%} {% set all_csp = [] -%} {% for csp in (nginx_sel_source.security.csp | d({}) | dict2items) -%} {% set all_csp = all_csp.append(csp.key ~ ' ' ~ csp.value) -%} {% endfor -%} {% if nginx_sel_source.security.csp_in_report_mode | d(false) == true -%} add_header {{ 'Content-Security-Policy-Report-Only "' ~ (all_csp | join('; ')) ~ '"' }} always; {% else -%} add_header {{ 'Content-Security-Policy "' ~ (all_csp | join('; ')) ~ '"' }} always; {% endif -%} {% endif -%} {% if (nginx_sel_source.security.pp is mapping) and (nginx_sel_source.security.pp | d({}) | dict2items | length) > 0 -%} {% set all_fp = [] -%} {% set all_pp = [] -%} {% for pp in (nginx_sel_source.security.pp | d({}) | dict2items) -%} {% set all_fp = all_fp.append(pp.key ~ ' ' ~ ("'none'" if (pp.value | length == 0) else pp.value)) -%} {% set all_pp = all_pp.append(pp.key ~ '=(' ~ pp.value ~ ')') -%} {% endfor -%} add_header {{ 'Feature-Policy "' ~ (all_fp | join('; ')) ~ '"' }} always; add_header {{ 'Permissions-Policy "' ~ (all_pp | join(', ')) ~ '"' }} always; {% endif -%} {% endmacro -%} {% macro nginx_allow(combined) -%} {% if (combined.external_tld | d(false) == true) or (combined.tld is defined and combined.tld == tld) or (combined.int_net | d(true) == false) -%} allow all; {% for bogon in (bogons | d([])) -%} deny {{ bogon }}; {% endfor -%} {% else -%} allow {{ int_net }}; {% endif -%} {% endmacro -%} {% macro nginx_server_name(combined, srv) -%} {% if combined.is_root | d(false) == false -%} {% set nginx_sn_prefix = (srv.name | d(combined.override_server_name | d(inventory_hostname))) ~ '.' -%} {% else -%} {% set nginx_sn_prefix = '' -%} {% endif -%} {% if combined.tld is string -%} {% set nginx_sn_tld = combined.tld -%} {% else -%} {% set nginx_sn_tld = host_tld -%} {% endif -%} {% if srv.no_tld | d(false) == true -%} server_name {{ srv.name }}; {% else -%} server_name {{ nginx_sn_prefix ~ nginx_sn_tld }}; {% endif -%} {% endmacro -%} {% macro nginx_stapling() -%} {% if nginx_cfg.enable_stapling | d(false) == true -%} ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1; {% else -%} ssl_stapling off; {% endif -%} {% endmacro -%} user {{ nginx_cfg.user }} {{ nginx_cfg.group }}; error_log syslog:server=unix:/dev/log,facility=local2 {{ nginx_cfg.log_level | d('notice') }}; {{ nginx_option_block(nginx_cfg.conf.root) }} {{ nginx_include('*', 'modules') }} {{ nginx_include('main*') }} events { {{ nginx_option_block(nginx_cfg.conf.events) }} } http { {{ nginx_option_block(nginx_cfg.conf.http) }} include {{ (nginx_cfg.conf_dir ~ '/mime.types') | quote }}; {# ssl_dhparam {{ (nginx_cfg.conf_dir ~ '/tls/' ~ nginx_cfg.dhparam_file) | quote }}; #} {% if nginx_cfg.security_headers | d(false) == true -%} {{ nginx_security_headers(nginx_cfg) }} {% endif %} {{ nginx_include('http*') }} {% set nginx_http = (nginx_cfg.servers | d([]) | selectattr('http', 'defined') | selectattr('http', 'equalto', true) | list) -%} {% set nginx_https = (nginx_cfg.servers | d([]) | rejectattr('http', 'defined') | list) -%} {# custom HTTP servers -#} {% for srv in nginx_http -%} {% set combined = (nginx_cfg | combine(srv, recursive=true)) -%} server { listen 80; {% if srv.ipv6 | d(true) == true %}listen [::]:80;{% endif %} {{ nginx_allow(combined) }} {{ nginx_server_name(combined, srv) }} {% if (srv.security_headers | d(false) == true) and (nginx_cfg.security_headers | d(false) == false) %} {{ nginx_security_headers(srv) }} {% endif %} {{ nginx_include(srv.conf) }} } {% endfor %} {# default HTTP server -#} {% if nginx_cfg.add_default_http_server | d(true) == true -%} server { listen 80 default_server; listen [::]:80 default_server; {{ nginx_allow(combined) }} {{ nginx_server_name(combined, {}) }} {% if nginx_cfg.default_http_config is not defined -%} location / { return 301 https://$host$request_uri; } {% else -%} {{ nginx_include(nginx_cfg.default_http_config) }} {% endif -%} } {% endif -%} {# custom HTTPS servers #} {% for srv in nginx_https -%} {% set combined = (nginx_cfg | combine(srv, recursive=true)) -%} server { listen 443 ssl http2; {% if srv.ipv6 | d(true) == true %}listen [::]:443 ssl http2;{% endif %} {% if combined.certs | d(true) == true -%} ssl_certificate {{ (nginx_cfg.conf_dir ~ '/tls/' ~ nginx_cfg.cert_rsa_name ~ '.crt') | quote }}; ssl_certificate_key {{ (nginx_cfg.conf_dir ~ '/tls/' ~ nginx_cfg.cert_rsa_name ~ '.key') | quote }}; ssl_certificate {{ (nginx_cfg.conf_dir ~ '/tls/' ~ nginx_cfg.cert_ecc_name ~ '.crt') | quote }}; ssl_certificate_key {{ (nginx_cfg.conf_dir ~ '/tls/' ~ nginx_cfg.cert_ecc_name ~ '.key') | quote }}; {%- endif %} {{ nginx_allow(combined) }} {{ nginx_server_name(combined, srv) }} {{ nginx_stapling() }} {% if (srv.security_headers | d(false) == true) and (nginx_cfg.security_headers | d(false) == false) %} {{ nginx_security_headers(srv) }} {% endif %} {{ nginx_include(srv.conf) }} } {% endfor %} }