Skip to content
Snippets Groups Projects
Verified Commit 4f872bae authored by Kristian Klausen's avatar Kristian Klausen :tada:
Browse files

Fix missing HSTS header for some URLs due to nginx "directive inheritance"[1]

F5/nginx has blogged about this[1] and it is also mentioned in nginx's
documentation[2]:
"There could be several add_header directives. These directives are
inherited from the previous configuration level if and only if there are
no add_header directives defined on the current level. "

The problem occurs when add_header is used in a child context like a
server{} or location{} block. It is solved by moving the HSTS header
into a snippet, which is now included before all add_header lines.

For now the HSTS header is the only global header, but in the future we
may need to add more global headers, like the Alt-Svc header[3] for
HTTP/3.

[1] https://www.f5.com/company/blog/nginx/avoiding-top-10-nginx-configuration-mistakes#directive-inheritance
[2] https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
[3] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc

Fix #608
parent a816ca06
No related branches found
No related tags found
1 merge request!859Fix missing HSTS header for some URLs due to nginx "directive inheritance"[1]
Showing
with 29 additions and 8 deletions
......@@ -49,6 +49,7 @@ server {
# Client-cache for Django's static assets
location /static/ {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public";
alias {{ archmanweb_dir }}/repo/collected_static/;
......
......@@ -41,6 +41,7 @@ server {
# Cache django's css, js and png files.
location /static/ {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public";
alias /srv/http/archweb/collected_static/;
......
......@@ -120,6 +120,7 @@ server {
location = /.well-known/matrix/client {
default_type application/json;
include snippets/headers.conf;
add_header Access-Control-Allow-Origin *;
return 200 '{"m.homeserver": {"base_url": "https://{{ matrix_domain }}"}, "m.identity_server": {"base_url": "https://matrix.org"} }';
}
......@@ -167,6 +168,7 @@ server {
# Cache django's css, js and png files.
location /static/ {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public";
alias {{ archweb_dir }}/collected_static/;
......
......@@ -42,6 +42,7 @@ server {
include snippets/letsencrypt.conf;
location /.well-known/ {
include snippets/headers.conf;
add_header Access-Control-Allow-Origin *;
return 301 https://$server_name$request_uri;
}
......@@ -67,6 +68,7 @@ server {
ssl_trusted_certificate /etc/letsencrypt/live/{{ archweb_domain }}/chain.pem;
location /.well-known/ {
include snippets/headers.conf;
add_header Access-Control-Allow-Origin *;
return 301 https://{{ archweb_domain }}{{ domain['redirect']|default('$request_uri') }};
}
......@@ -120,6 +122,7 @@ server {
location = /.well-known/matrix/client {
default_type application/json;
include snippets/headers.conf;
add_header Access-Control-Allow-Origin *;
return 200 '{"m.homeserver": {"base_url": "https://{{ matrix_domain }}"}, "m.identity_server": {"base_url": "https://matrix.org"} }';
}
......@@ -169,6 +172,7 @@ server {
# Cache django's css, js and png files.
location /static/ {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public";
alias {{ archweb_dir }}/collected_static/;
......@@ -189,6 +193,7 @@ server {
uwsgi_cache archwebcache;
uwsgi_cache_revalidate on;
include snippets/headers.conf;
add_header X-Cache-Status $upstream_cache_status;
limit_req zone=rsslimit burst=10 nodelay;
......@@ -202,6 +207,7 @@ server {
uwsgi_cache archwebcache;
uwsgi_cache_revalidate on;
uwsgi_cache_key $cache_key;
include snippets/headers.conf;
add_header X-Cache-Status $upstream_cache_status;
limit_req zone=mirrorstatuslimit burst=10 nodelay;
......@@ -235,11 +241,9 @@ server {
uwsgi_cache archwebcache;
uwsgi_cache_revalidate on;
uwsgi_cache_key $cache_key;
include snippets/headers.conf;
add_header X-Cache-Status $upstream_cache_status;
# re-add HSTS (inheritance from sslsettings.conf broken by above header)
add_header Strict-Transport-Security $hsts_header always;
limit_req zone=archweblimit burst=10 nodelay;
}
}
......@@ -125,6 +125,7 @@ server {
fastcgi_cache_use_stale updating;
fastcgi_cache_lock on;
include snippets/headers.conf;
add_header X-Cache $upstream_cache_status;
{% endblock %}
}
......@@ -143,6 +144,7 @@ server {
# normal PHP FastCGI handler
location ~ ^/[^/]+\.php$ {
if ($challenge) {
include snippets/headers.conf;
add_header Set-Cookie "challenge={{ archwiki_nginx_challenge_value }}; SameSite=Strict";
return 303 $scheme://$server_name/$request_uri;
}
......@@ -165,12 +167,14 @@ server {
# MediaWiki assets
location ~ ^/(?:images|resources/(?:assets|lib|src)|(?:skins|extensions)/.+\.(?:css|js|gif|jpg|jpeg|png|svg|wasm)$) {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location /images/ {
# Add the nosniff header to the images folder (required for mw 1.40+)
include snippets/headers.conf;
add_header X-Content-Type-Options nosniff;
}
......
......@@ -110,6 +110,7 @@ server {
location ~ \.gz$ {
root {{ aurweb_dir }}/archives;
default_type text/plain;
include snippets/headers.conf;
add_header Content-Encoding gzip;
expires 5m;
}
......@@ -118,6 +119,7 @@ server {
rewrite ^/static(/.*)$ $1 break;
expires 7d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
......
......@@ -76,12 +76,14 @@ server {
location ^~ /style/ {
expires 7d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location ^~ /img/ {
expires 7d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
......
......@@ -45,6 +45,7 @@ server {
access_log /var/log/nginx/{{ matrix_domain }}/access.log main;
access_log /var/log/nginx/{{ matrix_domain }}/access.log.json json_main;
{% if location.add_cors | default(false) %}
include snippets/headers.conf;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, HEAD, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization, Date";
......
......@@ -17,6 +17,7 @@ server {
ssl_certificate_key /etc/letsencrypt/live/{{ item.value.mirror_domain }}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/{{ item.value.mirror_domain }}/chain.pem;
include snippets/headers.conf;
add_header X-Served-By "{{ inventory_hostname }}";
autoindex on;
......
......@@ -23,6 +23,7 @@
with_items:
- letsencrypt.conf
- sslsettings.conf
- headers.conf
notify:
- Reload nginx
......
add_header Strict-Transport-Security $hsts_header always;
......@@ -90,6 +90,7 @@ http {
access_log syslog:server=unix:/dev/log,nohostname,tag=nginx_http main;
include snippets/sslsettings.conf;
include snippets/headers.conf;
include nginx.d/*.conf;
}
......@@ -13,10 +13,9 @@ ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# See headers.conf for the HSTS add_header line.
map $scheme $hsts_header {
https "max-age=31536000; includeSubdomains; preload";
}
add_header Strict-Transport-Security $hsts_header always;
resolver 127.0.0.53;
......@@ -26,6 +26,7 @@ server {
# https://man.archlinux.org/man/NetworkManager.conf.5#CONNECTIVITY_SECTION
location = /nm-check.txt {
access_log off;
include snippets/headers.conf;
add_header Cache-Control "max-age=0, must-revalidate";
return 200 'NetworkManager is online\n';
}
......
......@@ -30,6 +30,7 @@ server {
ssl_trusted_certificate /etc/letsencrypt/live/{{ rebuilderd_domain }}/chain.pem;
# Security headers
include snippets/headers.conf;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Xss-Protection "1; mode=block" always;
add_header Referrer-Policy "same-origin";
......@@ -37,13 +38,11 @@ server {
add_header Content-Security-Policy "default-src 'self';";
add_header X-Content-Type-Options "nosniff" always;
# Apply HSTS header again, since adding a header removes previous headers
add_header Strict-Transport-Security $hsts_header;
root {{ rebuilder_website_loc }};
location ~* (css|js|svg)$ {
expires 30d;
include snippets/headers.conf;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
......
......@@ -19,6 +19,7 @@ server {
ssl_trusted_certificate /etc/letsencrypt/live/{{ domain }}/chain.pem;
{% if 'geo_mirrors' in group_names and domain == geo_mirror_domain %}
include snippets/headers.conf;
add_header X-Served-By "{{ inventory_hostname }}";
{% endif %}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment