1
1
mirror of https://gitlab.archlinux.org/archlinux/infrastructure.git synced 2025-01-18 08:06:16 +01:00
infrastructure/roles/archwiki/templates/nginx.d.conf.j2
Kristian Klausen 8dfa7e8c3e
nginx: Add plumbing for enabling HTTP/3 conditionally
We want to roll out HTTP/3 slowly, so this adds the necessary plumbing
and makes it possible to enable it per host.

Instead of adding the conditional logic to each nginx template, the 443
listen config is moved out into a snippet which is managed by the nginx
role.

HTTP/3 uses QUIC which is built on UDP. UDP is connectionless and
therefore reuseport[1][2] must be used to ensure that UDP packets for
the same QUIC connection is directed to the same worker. reuseport can
only be enabled once, so a default_server is added to the
"inventory_hostname vhost" for SSL/QUIC (reuseport is only enabled for
the latter). ssl_reject_handshake[3] is enabled as that allows enabling
SSL/QUIC without specifying a certificate.

[1] https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
[2] https://lwn.net/Articles/542629/
[3] http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_reject_handshake

Ref #606
2024-08-17 21:53:32 +02:00

190 lines
6.3 KiB
Django/Jinja

# Please keep "path" and "levels" in sync with nginx-cache-purge
fastcgi_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=wiki:100m inactive=720m;
# Please keep in sync with "cache_key" in nginx-cache-purge
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# rate limit API endpoint
limit_req_zone $binary_remote_addr zone=api_zone:10m rate=5r/s;
# limit general requests to 10 r/s to block DoS attempts with a burst of 10.
limit_req_zone $binary_remote_addr zone=archwikilimit:10m rate=10r/s;
limit_req_status 429;
upstream archwiki {
server unix://{{ archwiki_socket }};
}
# Challenge the client if the cookie "challenge" is not set to
# the value of "archwiki_nginx_challenge_value".
map $cookie_challenge $challenge_required2 {
default 1;
{{ archwiki_nginx_challenge_value }} 0;
}
# Challenge the client if it is requesting an "action view" and
# $challenge_required2 is true.
map $request_uri $challenge_required {
default 0;
~^/index\.php\? $challenge_required2;
}
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_iso_code country iso_code;
}
# Challenge the client if it is from China and $challenge_required is
# true. This is enough to "throw off" some bots/crawlers from China.
map $geoip2_data_country_iso_code $challenge {
default 0;
CN $challenge_required;
}
server {
listen 80;
listen [::]:80;
server_name {{ archwiki_domain }};
access_log /var/log/nginx/{{ archwiki_domain }}/access.log reduced;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log.json json_reduced;
error_log /var/log/nginx/{{ archwiki_domain }}/error.log;
include snippets/letsencrypt.conf;
location / {
access_log off;
return 301 https://$server_name$request_uri;
}
}
server {
include snippets/listen-443.conf;
server_name {{ archwiki_domain }};
access_log /var/log/nginx/{{ archwiki_domain }}/access.log reduced;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log.json json_reduced;
error_log /var/log/nginx/{{ archwiki_domain }}/error.log;
ssl_certificate /etc/letsencrypt/live/{{ archwiki_domain }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ archwiki_domain }}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/{{ archwiki_domain }}/chain.pem;
root {{ archwiki_dir }}/public;
index index.php;
# Block search bot that apparently never heared the term rate limiting
if ($http_user_agent ~ "Bytespider$" ) {
return 403;
}
location = /robots.txt {
alias {{ archwiki_dir }}/robots.txt;
}
location ^~ /. {
log_not_found off;
deny all;
}
# Redirect old URLs to the new short-url (/title/<page>)
location ~ ^/index.php/(.*)$ {
return 301 /title/$1$is_args$args;
}
# Handling for the article path (pretty URLs)
location ^~ /title/ {
rewrite ^ /index.php;
}
# Handling for MediaWiki REST API, see https://www.mediawiki.org/wiki/API:REST_API
location ^~ /rest.php/ {
rewrite ^ /rest.php;
}
# special case for '/load.php' type URLs to cache css/js in nginx to relieve php-fpm
location = /load.php {
access_log /var/log/nginx/{{ archwiki_domain }}/access.log main;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log.json json_main;
fastcgi_pass archwiki;
fastcgi_index index.php;
include fastcgi.conf;
{% block wiki_cache %}
fastcgi_cache wiki;
# This improves the cache hit ratio[1] and ensures that there is
# only a single cache file. Without this, nginx will use the
# Vary header as an secondary cache key[2], which breaks the
# cache purge service.
# [1] https://www.fastly.com/blog/best-practices-using-vary-header/
# [2] https://github.com/nginx/nginx/commit/1332e76b20a6a1e871904525d42b17dcaed81eec
fastcgi_ignore_headers Vary;
fastcgi_cache_background_update on;
fastcgi_cache_use_stale updating;
fastcgi_cache_lock on;
include snippets/headers.conf;
add_header X-Cache $upstream_cache_status;
{% endblock %}
}
# mediawiki API endpoint
location ~ ^/api\.php {
limit_req zone=api_zone burst=10 delay=5;
try_files $uri =404;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log main;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log.json json_main;
fastcgi_pass archwiki;
fastcgi_index index.php;
include fastcgi.conf;
}
# 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;
}
try_files $uri =404;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log main;
access_log /var/log/nginx/{{ archwiki_domain }}/access.log.json json_main;
fastcgi_pass archwiki;
fastcgi_index index.php;
include fastcgi.conf;
{{ self.wiki_cache() }}
# https://www.mediawiki.org/w/index.php?title=Manual:Varnish_caching&oldid=6230975#Configuring_Varnish
fastcgi_cache_bypass $http_authorization $cookie_archwiki_session $cookie_archwikiToken;
fastcgi_no_cache $http_authorization $cookie_archwiki_session $cookie_archwikiToken;
limit_req zone=archwikilimit burst=10 nodelay;
}
# 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;
}
location /images/deleted {
# Deny access to deleted images folder
deny all;
}
# block all other directories
location ~ ^/[^/]+/ {
log_not_found off;
deny all;
}
}