diff --git a/roles/archweb/templates/ipxe.archlinux.org.j2 b/roles/archweb/templates/ipxe.archlinux.org.j2
index e1b2d9429cfac3a62c13ef67f70e97736e5db5ea..5fbeac4e060608eb6cdb837bf6250104446d558a 100644
--- a/roles/archweb/templates/ipxe.archlinux.org.j2
+++ b/roles/archweb/templates/ipxe.archlinux.org.j2
@@ -30,7 +30,7 @@ server {
     ssl_certificate_key  /etc/letsencrypt/live/{{ archweb_domain }}/privkey.pem;
     ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}/chain.pem;
 
-    location /releng/netboot {
+    location /releng/netboot/ {
         access_log   /var/log/nginx/{{ archweb_domain }}/access.log main;
         access_log   /var/log/nginx/{{ archweb_domain }}/access.log.json json_main;
         include uwsgi_params;
@@ -38,11 +38,11 @@ server {
     }
 
     # Cache django's css, js and png files.
-    location /static {
+    location /static/ {
         expires 30d;
         add_header Pragma public;
         add_header Cache-Control "public";
-        alias /srv/http/archweb/collected_static;
+        alias /srv/http/archweb/collected_static/;
     }
 
     location / {
diff --git a/roles/archweb/templates/maintenance-nginx.d.conf.j2 b/roles/archweb/templates/maintenance-nginx.d.conf.j2
index 5b5a1c4ff4109ca3ebe9e666b073380086fc887e..ad112acf36dae0de1200eac6b349ce02e657f87f 100644
--- a/roles/archweb/templates/maintenance-nginx.d.conf.j2
+++ b/roles/archweb/templates/maintenance-nginx.d.conf.j2
@@ -78,12 +78,12 @@ server {
 
     error_page 503 /503.html;
 
-    location /.well-known/matrix/server {
+    location = /.well-known/matrix/server {
         default_type application/json;
         return 200 '{"m.server": "{{ matrix_domain }}:443"}';
     }
 
-    location /.well-known/matrix/client {
+    location = /.well-known/matrix/client {
         default_type application/json;
         add_header Access-Control-Allow-Origin *;
         return 200 '{"m.homeserver": {"base_url": "https://{{ matrix_domain }}"}, "m.identity_server": {"base_url": "https://matrix.org"} }';
diff --git a/roles/archweb/templates/nginx.d.conf.j2 b/roles/archweb/templates/nginx.d.conf.j2
index c1ac77b62177e1e07c7df78228478360a0d674cd..57c86168513483f5f594db61d3dfcc7de37b95c4 100644
--- a/roles/archweb/templates/nginx.d.conf.j2
+++ b/roles/archweb/templates/nginx.d.conf.j2
@@ -38,7 +38,7 @@ server {
 
     include snippets/letsencrypt.conf;
 
-    location /.well-known {
+    location /.well-known/ {
         add_header Access-Control-Allow-Origin *;
         return 301 https://$server_name$request_uri;
     }
@@ -62,7 +62,7 @@ server {
     ssl_certificate_key  /etc/letsencrypt/live/{{ archweb_domain }}/privkey.pem;
     ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}/chain.pem;
 
-    location /.well-known {
+    location /.well-known/ {
         add_header Access-Control-Allow-Origin *;
         return 301 https://{{ archweb_domain }}{{ domain['redirect']|default('$request_uri') }};
     }
@@ -108,12 +108,12 @@ server {
     ssl_certificate_key  /etc/letsencrypt/live/{{ archweb_domain }}/privkey.pem;
     ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}/chain.pem;
 
-    location /.well-known/matrix/server {
+    location = /.well-known/matrix/server {
         default_type application/json;
         return 200 '{"m.server": "{{ matrix_domain }}:443"}';
     }
 
-    location /.well-known/matrix/client {
+    location = /.well-known/matrix/client {
         default_type application/json;
         add_header Access-Control-Allow-Origin *;
         return 200 '{"m.homeserver": {"base_url": "https://{{ matrix_domain }}"}, "m.identity_server": {"base_url": "https://matrix.org"} }';
diff --git a/roles/dbscripts/templates/nginx.d.conf.j2 b/roles/dbscripts/templates/nginx.d.conf.j2
index 771dc27ea8a31e8c50bb00d6be617799b33aab27..35dbca43c4f76792af8386c0974b2f9d1fb0b52e 100644
--- a/roles/dbscripts/templates/nginx.d.conf.j2
+++ b/roles/dbscripts/templates/nginx.d.conf.j2
@@ -19,7 +19,7 @@ server {
     access_log   /var/log/nginx/{{ repos_domain }}/access.log reduced;
     access_log   /var/log/nginx/{{ repos_domain }}/access.log.json json_reduced;
 
-    location /lastupdate {
+    location = /lastupdate {
         allow all;
     }
 
diff --git a/roles/flyspray/templates/nginx.d.conf.j2 b/roles/flyspray/templates/nginx.d.conf.j2
index a658ddcfd11e4d845f2b2a50f51f97c181a94357..5731c2b0ba929b6eb2b328f4f8c61965454ca07d 100644
--- a/roles/flyspray/templates/nginx.d.conf.j2
+++ b/roles/flyspray/templates/nginx.d.conf.j2
@@ -43,15 +43,15 @@ server {
         deny all;
     }
 
-    location /setup {
+    location /setup/ {
         deny all;
     }
 
-    location /attachments {
+    location /attachments/ {
         location ~ \.php$ {return 403;}
     }
 
-    location /cache {
+    location /cache/ {
         location ~ \.php$ {return 403;}
     }
 
diff --git a/roles/keycloak/templates/nginx.d.conf.j2 b/roles/keycloak/templates/nginx.d.conf.j2
index 083a947df5c69f0812565690023629d67ab887ba..78672f4f8c8df8f0930b82aca593509eec4b9a20 100644
--- a/roles/keycloak/templates/nginx.d.conf.j2
+++ b/roles/keycloak/templates/nginx.d.conf.j2
@@ -31,7 +31,7 @@ server {
     root {{ keycloak_domain }};
 
     # https://w3c.github.io/webappsec-change-password-url/
-    location /.well-known/change-password {
+    location = /.well-known/change-password {
         return 302 https://$server_name/auth/realms/archlinux/account/#/security/signingin;
     }
 
diff --git a/roles/mailman/templates/nginx.d.conf.j2 b/roles/mailman/templates/nginx.d.conf.j2
index 3266d9dd83fc7b964b946a370b2550a2dd1822fa..e399179be94a7ce7b7e57f17533401eceffc0547 100644
--- a/roles/mailman/templates/nginx.d.conf.j2
+++ b/roles/mailman/templates/nginx.d.conf.j2
@@ -29,16 +29,16 @@ server {
     ssl_trusted_certificate /etc/letsencrypt/live/{{ lists_domain }}/chain.pem;
 
     # redirect old urls
-    location /mailman {
+    location /mailman/ {
         rewrite ^/mailman/(.*) /$1 permanent;
     }
 
-    location /icons {
-        alias /usr/lib/mailman/icons;
+    location /icons/ {
+        alias /usr/lib/mailman/icons/;
     }
 
-    location /pipermail {
-        alias /var/lib/mailman/archives/public;
+    location ~ ^/pipermail(?:/(.*))?$ {
+        alias /var/lib/mailman/archives/public/$1;
         add_header Cache-Control "public, no-cache";
         autoindex on;
     }
diff --git a/roles/mta_sts/templates/nginx.d.conf.j2 b/roles/mta_sts/templates/nginx.d.conf.j2
index 1cfd0c6defc7aeedb9d155008b41a59f86299f2e..31e9b74e478413b72d5fd608e24215253d1613c3 100644
--- a/roles/mta_sts/templates/nginx.d.conf.j2
+++ b/roles/mta_sts/templates/nginx.d.conf.j2
@@ -30,7 +30,7 @@ server {
     ssl_certificate_key  /etc/letsencrypt/live/{{ domain }}/privkey.pem;
     ssl_trusted_certificate /etc/letsencrypt/live/{{ domain }}/chain.pem;
 
-    location /.well-known/mta-sts.txt {
+    location = /.well-known/mta-sts.txt {
         default_type text/plain;
         return 200 'version: STSv1\nmode: testing\nmax_age: 604800\nmx: {{ config.mx | join('\\nmx: ')}}\n';
     }
diff --git a/roles/nginx/templates/letsencrypt.conf b/roles/nginx/templates/letsencrypt.conf
index 99dd6c628499f32bd2bc064968c3bff521cd1d24..2d43755b49022dd1fdece07b94a3ead69f40d488 100644
--- a/roles/nginx/templates/letsencrypt.conf
+++ b/roles/nginx/templates/letsencrypt.conf
@@ -1,4 +1,4 @@
-location /.well-known/acme-challenge {
+location /.well-known/acme-challenge/ {
     root {{ letsencrypt_validation_dir }};
     default_type "text/plain";
     try_files $uri =404;
diff --git a/roles/ping/templates/nginx.d.conf.j2 b/roles/ping/templates/nginx.d.conf.j2
index 5374e87d5825ca0ba8a111f89826af9a75ff12f8..fdef8a14d19bb04da9778b58ff696a0bba94b42d 100644
--- a/roles/ping/templates/nginx.d.conf.j2
+++ b/roles/ping/templates/nginx.d.conf.j2
@@ -23,7 +23,7 @@ server {
     }
 
     # https://man.archlinux.org/man/NetworkManager.conf.5#CONNECTIVITY_SECTION
-    location /nm-check.txt {
+    location = /nm-check.txt {
         access_log off;
         add_header Cache-Control "max-age=0, must-revalidate";
         return 200 'NetworkManager is online\n';
diff --git a/roles/rebuilderd/templates/nginx.d.conf.j2 b/roles/rebuilderd/templates/nginx.d.conf.j2
index e9fd1afa64358dcb6560e46340f3ca8801e9ab4d..78156a96488357532fb5a3bc211cad53351b3978 100644
--- a/roles/rebuilderd/templates/nginx.d.conf.j2
+++ b/roles/rebuilderd/templates/nginx.d.conf.j2
@@ -47,12 +47,12 @@ server {
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
     }
 
-    location /api {
+    location /api/ {
             proxy_set_header    X-Real-IP          $remote_addr;
 	    proxy_pass http://127.0.0.1:8484;
     }
 
-    location /api/v0/build/report {
+    location = /api/v0/build/report {
 	    client_max_body_size 25M;
             proxy_set_header    X-Real-IP          $remote_addr;
 	    proxy_pass http://127.0.0.1:8484;