[NOT NETDATA RELATED] Nginx Amplify "Regex location has no anchors in regex pattern". How to fix corresponding lines in Nginx virtual host?

I am running Nginx with Nginx Amplify. In my Amplify>Analyzer>Static Analysis Section I am gettin the following errors:

Regex location has no anchors in regex pattern Regex location has a regex pattern without ^ or $. This is a configuration style that is prone to errors. It may also lead to a situation when requests partially matching the regex pattern are incorrectly routed to this location. Always use ^ or $ achor in a regex pattern.

Check the following files: /etc/nginx/conf.d/01-mail.example.com, line 27 /etc/nginx/conf.d/01-mail.example.com, line 89 /etc/nginx/sites-enabled/03-example2.com.conf, line 176 /etc/nginx/sites-enabled/03-example2.com.conf, line 199 /etc/nginx/sites-enabled/03-example2.com.conf, line 265

My 01-mail.example.com virtual host file looks like this:

server {
    # Restrict access to LAN & Work IP & Apartment IP's
    allow xxx.xxx.xx.x/24; #  LAN IP Address
    allow xxx.xx.xxx.xxx/32; # Work IP address
    allow xxx.xx.xxx.xxx/32; # Apt. IP Address
    deny all;
    #error_page 403 =444;

    # Begin Server Directives
    server_name mail.example.com;
    root /var/www/roundcube/;
    index index.php index.html index.htm;

    # Logs
    error_log /var/log/nginx/mail.example.com.error.log;
    access_log /var/log/nginx/mail.example.com.access.log;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        include snippets/fastcgi-php.conf;
    }

    location ~ /.well-known/acme-challenge {
        allow all;
    }
    location ~ ^/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
        deny all;
    }
    location ~ ^/(bin|SQL)/ {
        deny all;
    }
    # A long browser cache lifetime can speed up repeat visits to your page
    location ~ \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
        access_log off;
        log_not_found off;
        expires 360d;
    }

    listen *:443 ssl;
    http2 on;
    ssl_certificate /etc/letsencrypt/live/mail.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/ssl/private/dhparams4096.pem; # Managed by admin

    add_header Strict-Transport-Security "max-age=31536000" always; # managed by Certbot

    ssl_trusted_certificate /etc/letsencrypt/live/mail.example.com/chain.pem; # managed by Certbot
    ssl_stapling on; # managed by Certbot
    ssl_stapling_verify on; # managed by Certbot

}
server {
    if ($host = mail.example.com) {
        return 301 https://$host$request_uri;
    }
    # managed by Certbot

    # Restrict access to LAN & Work IP & Apartment IP's
    allow xxx.xxx.xx.x/24; #  LAN IP Address
    allow xxx.xx.xxx.xxx/32; # Work IP address
    allow xxx.xx.xxx.xxx/32; # Apt. IP Address
    deny all;
    #error_page 403 =444;

    # Begin Server Directives
    listen *:80;
    server_name mail.example.com;
    root /var/www/roundcube/;
    index index.php index.html index.htm;

    error_log /var/log/nginx/mail.example.com.error.log;
    access_log /var/log/nginx/mail.example.com.error.log;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        #try_files $uri =404;
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        include snippets/fastcgi-php.conf;
    }

    location ~ /.well-known/acme-challenge {
        allow all;
    }
    location = ^/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
        deny all;
    }
    location ~ ^/(bin|SQL)/ {
        deny all;
    }
    # LINUXBABE + Extra Extensions
    # A long browser cache lifetime can speed up repeat visits to your page
    location ~ \.(txt|flv|pdf|avi|mov|ppt|wmv|mp3|ogg|webm|aac|jpg|ogg|ogv|svgz|eot|otf|mp4|rss|atom|zip|tgz|gz|rar|bz2|doc|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|jpeg|gif|png|swf|jpeg|webp|svg|woff|woff2|ttf|css|js|ico|xml|otf|woff|woff2)$ {
        access_log off;
        log_not_found off;
        expires 1y;
    }
}

It seems the lines Amplify is referencing is:

location ~ /.well-known/acme-challenge {

on line 27, and …

location ~ /.well-known/acme-challenge {

on line 89.

My 03-example2.com.conf virtual host file looks like this:

server {
    listen 80;
    server_name example2.com www.example2.com;
    return 301 https://$host$request_uri;
}

server {
    listen *:443 ssl;
    http2 on;
    server_name example2.com www.example2.com;
    root /var/www/example2.com/;

    ##
    # SECURITY HEADERS
    ##

    # Strict Transport Security Response Header
    # Use "always" Paramater to help prevent MITM attacks.
    # ADMIN Note: Including the Preload Paramerter will cause web browsers to cache this header
    # permanently in their browser code for about two months. Use only if you want to permanently
    # commit this header to your site. If you change it, it will take a long time for changes to
    # be reflected in the web browsers.
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # Content Security Policy (CSP)
    #add_header Content-Security-Policy "frame-ancestors 'self';";
    # https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
    add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
    #add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'";
    # https://walterebert.com/blog/using-csp-wordpress/
    #add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com;" always;
    # https://nowherelan.com/2018/12/27/secure-your-wordpress-site-with-the-content-security-policy-csp-http-header-in-apache/
    #add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com *.wp.com *.wordpress.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com *.wp.com *.wordpress.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com *.wp.com *.wordpress.com; frame-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com"

    # Secure MIME Types with X-Content-Type-Options. Below line adds the X-Frame-Options header in Nginx.
    add_header X-Content-Type-Options "nosniff" always;

    # Referrer Policy
    #add_header Referrer-Policy "strict-origin";
    # https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # Permissions Policy
    add_header Permissions-Policy "geolocation=(), autoplay=(), encrypted-media=(), midi=(), usb=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=(self)";

    # X-FastCGI-Cache
    # This line adds the X-FastCGI-Cache header in the HTTP response. It can be used to validate whether
    # the request has been served from the FastCGI cache or not.
    # ADMIN Note: Linuxbabe originally had this directive in "location ~ \.php$ {", however, we don't use it
    # there because it invalidates any other currently used headers and only implements itself.
    add_header X-FastCGI-Cache $upstream_cache_status always;

    # Clear Site Data
    # When we use a webpage, we can leave various pieces of data in the browser that we’d like to clear
    # out if the user logs out or deletes their account. Clear Site Data gives us a reliable way to do
    # that.
    # ADMIN Note: We decided to enable it globally on all pages via:
    add_header Clear-Site-Data "*";

    # X-Frame Options
    # Prevent click jacking by adding an X-Frame-Options header
    add_header x-frame-options "SAMEORIGIN" always;

    # X-SSS Protections
    # Enable X-XSS-Protection header in Nginx
    add_header X-XSS-Protection "1; mode=block" always;

    # LINUXBABE
    # If you allow people to upload files, or are concerned about intruders using a different flaw to get
    # files onto your server AND the content on your domain should not be accessed via other websites
    # possibly trying to impersonate you, then yes X-Permitted-Cross-Domain-Policies "none" will provide a
    # security benefit. The attack is less relevant these days, as any user of modern software first
    # needs to be tricked into allowing Flash or active PDF content.
    # If your website is just a regular website with nothing that requires a login to access, then you don't need it.
    # https://www.linuxbabe.com/ubuntu/install-wordpress-ubuntu-20-04-nginx-mariadb-php7-4-lemp
    # https://security.stackexchange.com/questions/166024/does-the-x-permitted-cross-domain-policies-header-have-any-benefit-for-my-websit
    add_header X-Permitted-Cross-Domain-Policies none;

    # LINUXBABE (User recommendation)
    # Ignore Cache Control
    # Keep fastcgi working if it's not getting hits
    # ADMIN Note: Only use this if fastcgi cache status is not getting hits
    #fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

    ##
    # SSL
    ##

    # Certificate Path (signed)
    ssl_certificate /etc/letsencrypt/live/example2.com/fullchain.pem; # Managed by ADMIN
    # Certificate Path (intermediate)
    ssl_certificate_key /etc/letsencrypt/live/example2.com/privkey.pem; # Managed by ADMIN
    # Certificate Path (Chain of trust of OCSP response using Root CA and intermediate certificates)
    ssl_trusted_certificate /etc/letsencrypt/live/example2.com/chain.pem; # Managed by ADMIN
    # Perfect Forward Secrecy (Diffie Hellman 4096) Path
    ssl_dhparam /etc/ssl/private/dhparams4096.pem; # Managed by ADMIN

    # Mozilla Modern Compatibilty
    # Strict Settings with OCSP stapling turned on for A+ Rating at ssllabs.com
    ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLERequires nginx >= 1.13.0 else use TLSv1.2 # Dropping TLSv1.1 for modern compatability.
    ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m; # About 40000 sessions
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 1.1.1.1 1.0.0.1;

    ##
    # LOGS
    ##

    # ADMIN Note: Adding "if=$log_ip" to the end of access log lines will exclude your own ip address from access logs to prevent skewing data

    # Access Log (Netdata)
    access_log /var/log/nginx/example2.com.access.log netdata if=$log_ip;
    # Access Log (Amplify)
    access_log /var/log/nginx/example2.com.access.log apm if=$log_ip;
    # Error Log
    error_log /var/log/nginx/example2.com.error.log warn;

    ##
    # PAGESPEED
    ##

    # ADMIN Note: Pagespeed is broken on Nginx v1.25.1 and up, so we should comment all of it out here and in the "nginx.conf" file

    # Settings per this virtual host
    # Enable Pagespeed module
    #pagespeed on;
    #pagespeed Domain http*://*.example2.com;

    # Settings per all virtual hosts
    #include /etc/nginx/pagespeed.conf;

    ##
    # LOCATION DIRECTIVES 1
    ##

    index index.php index.html index.htm index.nginx-debian.html;

    # ADMIN
    # https://serverfault.com/questions/1137324/difference-between-3-similar-nginx-location-directives-provided-in-three-separat/1137342#1137342
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    ### BEGIN: "Converter for Media" Wordpress Plugin
    set $ext_avif ".avif";
    if ($http_accept !~* "image/avif") {
        set $ext_avif "";
    }

    set $ext_webp ".webp";
    if ($http_accept !~* "image/webp") {
        set $ext_webp "";
    }

    location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif|webp)$ {
        add_header Vary Accept;
        expires 365d;
        try_files
            /wp-content/uploads-webpc/$path.$ext$ext_avif
            /wp-content/uploads-webpc/$path.$ext$ext_webp
            $uri =404;
    }
    ### END: "Converter for Media" Wordpress Plugin

    # ADMIN
    # https://serverfault.com/questions/755662/nginx-disable-htaccess-and-hidden-files-but-allow-well-known-directory
    # location ~ /.well-known {
    location ~ /\.well-known {
        allow all;
    }

    # ADMIN
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    # ADMIN
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # LINUXBABE
    location ~ ^/wp-json/ {
        rewrite ^/wp-json/(.*?)$ /?rest_route=/$1 last;
    }

    # LINUXBABE
    location ~ /wp-sitemap.*\.xml {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # LINUXBABE
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    # LINUXBABE
    location = /50x.html {
        root /var/www/html;
    }

    # ADMIN
    # DISALLOW ACCESS of /xmlrpc.php
    # EXCEPT FROM internal IP's and Home & Apartment IP's.
    #location ^~ /xmlrpc.php$ {
        #allow xxx.xxx.xx.x/24; #   LAN IP Address
        #allow xxx.xxx.xx.x/32; # Home IP address
        #allow xxx.xxx.xx.x/32; # Apt. IP Address
        #deny all;
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        #include snippets/fastcgi-php.conf;
    #}

    # ADMIN
    # DISALLOW ACCESS of /admin
    # EXCEPT FROM internal IP's and Home & Apartment IP's
    location ^~ /admin/ {
        #satify all;
        allow xxx.xxx.xx.x/24; #   LAN IP Address
        allow xxx.xxx.xx.x/32; # Home IP address
        allow xxx.xxx.xx.x/32; # Apt. IP Address
        deny all;
        # Require basic auth login for allowed IP's
        auth_basic "You Don't belong here. Get out!";
        auth_basic_user_file /etc/nginx/basic_auth/auth.admin;
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        include snippets/fastcgi-php.conf;
    }

    # ADMIN
    # DISALLOW ACCESS of /wp-login.php
    # EXCEPT FROM internal IP's and Home & Apartment IP's.
    #location ^~ /wp-login.php {
        #allow xxx.xxx.xx.x/24; #   LAN IP Address
        #allow xxx.xxx.xx.x; # Home IP address
        #allow xxx.xxx.xx.x; # Apt. IP Address
        #deny all;
        # Require basic auth login for allowed IP's
        #auth_basic "You Don't belong here. Get out!";
        #auth_basic_user_file /etc/nginx/basic_auth/auth.wp-login;
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        #include snippets/fastcgi-php.conf;
    #}

    # ADMIN
    # DISALLOW ACCESS of PHP In Upload Folder
    location /wp-content/uploads/ {
        location ~ \.php$ {
            deny all;
        }
    }

    # ADMIN
    # DISALLOW ACCESS of hidden files
    location ~ /\. {
        access_log off;
        log_not_found off;
        deny all;
    }

    ##
    # BEGIN: CACHE / SKIP CACHE
    ##

    # LINUXBABE
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    # Don't Skip Cache by Default
    set $skip_cache 0;

    # LINUXBABE
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    # POST requests should always go to PHP
    if ($request_method = POST) {
        set $skip_cache 1;
    }

    # LINUXBABE
    # URLs containing query strings should always go to PHP
    # ADMIN Note: You might want to be sure to turn off query strings in H-code wordpress theme, and other themes
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    if ($query_string != "") {
        set $skip_cache 1;
    }

    # LINUXBABE
    # Don't cache uris containing the following segments
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    # https://easyengine.io/wordpress-nginx/tutorials/plugins/woocommerce/
    # https://docs.cleavr.io/guides/woocommerce/
    if ($request_uri ~* "/wp-admin/|/wp-json/|/login/|/register/|/shopping-cart.*|.*add-to-cart.*|.*empty-cart.*|/cart.*|/checkout.*|/addons.*|/my-account.*|/wishlist.*|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
        set $skip_cache 1;
    }

    # LINUXBABE
    # Don't use the cache for logged in users or recent commenters
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }

    # LINUXBABE
    # Cache Bypass for specified IP's
    # Test the upstream (PHP-FPM and MariaDB) response time. By adding the following
    # lines we tell Nginx to bypass the FastCGI cache for our own public and local IP addresses.
    # Skip the fastCGI Cache for "Apartment Public IP|Work Public IP|Apartment LAN Subdomain".
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    #if ($remote_addr ~* "xxx.xxx.xx.x|108.231.125.254|xxx.xxx.xx.x|192.168.25..*") {
    #    set $skip_cache 1;
    #}

    ##
    # END: CACHE / SKIP CACHE
    ##

    # LINUXBABE
    # Google Sitemaps / Yoast SEO Rules:
    # If you use the Yoast SEO or Google XML Sitemap plugins to generate sitemap, then
    # you need to move the Yoast/Google XML rewrite rules here, below the skip cache rules (below this line).
    # https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
    # Rules:

    ##
    # LOCATION DIRECTIVES 2
    ##

    # LINUXBABE
    # Pass Fastcgi to PHP
    location ~ \.php$ {
        # Pass FastCGI to PHP7.4 with included settings in the snippet
        include snippets/fastcgi-php.conf;
        # FastCGI Cache
        #fastcgi_cache off;
        fastcgi_cache example2.com;
        fastcgi_cache_valid 200 301 302 12h;
        fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
        fastcgi_cache_min_uses 1;
        fastcgi_cache_lock on;
        # Tell Nginx to send requests to upstream PHP-FPM server, instead of trying to find files in the
        # cache. If the value of $skip_cache is 1, then the first directive tells Nginx to send request
        # to upstream PHP-FPM server, instead of trying to find files in the cache.
        # ADMIN Note: fastcgi_cache_bypass $skip_cache and fastcgi_no_cache $skip_cache should be
        # uncommented if using google XML sitemap plugin, or Yoast SEO Plugin, or if you want to
        # enable the skip cache rules above.
        fastcgi_cache_bypass $skip_cache;
        # This directive tells Nginx not to cache the response.
        fastcgi_no_cache $skip_cache;
    }

    ##
    # NGINX CACHE PURGING in WORDPRESS with Nginx_Cache_Purge MODULE
    ##

    # Cache Purge
    # This enables the ngx_http_cache_purge_module.so module to work with Nginx Helper in Wordpress.
    # Cache Purging should be restricted to allowed IP addresses.
    # If not set, an attacker may be able to wipe your nginx fastcgi cache using simple GET requests. # (Linuxbabe User Comment).
    # This location block enables cache purge but restricts it to your ip address and to your loopback address.
    # Note: This is broken and we haven't tried to fix it. So, we are using wordpress Nginx Helper cache purge instead. Comment this out.
    #location ~ /purge(/.*) {
        #allow 127.0.0.1; # Server Loopback Address
        #allow xxx.xxx.xx.x; # Server IPv4 address
        #deny all;
        # Enable http-cache-purge module in nginx for above IP addresses
        #fastcgi_cache_purge example2.com "$scheme$request_method$host$1";
    #}

    # LINUXBABE (+ ADMIN Extra Extensions)
    # Speed up repeat visits to your page with a long browser cache lifetime
    location ~ \.(txt|flv|pdf|avi|mov|ppt|wmv|mp3|ogg|webm|aac|jpg|ogg|ogv|svgz|eot|otf|mp4|rss|atom|zip|tgz|gz|rar|bz2|doc|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|jpeg|gif|png|swf|jpeg|webp|svg|woff|woff2|ttf|css|js|ico|xml|otf|woff|woff2)$ {
        access_log off;
        log_not_found off;
        expires 1y;
    }
}

It seems the lines Amplify is referencing is:

location ~ /\.well-known {

on line 176,

location ~ /wp-sitemap.*\.xml {

on line 199, and

location ~ /\. {

on line 265.

What should I find and replace in each of the corresponding lines to satisfy Amplify’s recommended suggestions?

Is there anyone out there in the community who can answer this?

Hi @Danrancan ,

Closing this post since this isn’t related to Netdata.

Regards,
Hugo