hakurei.app/nginx/nginx.conf
2021-11-26 19:41:37 -05:00

427 lines
14 KiB
Nginx Configuration File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# nginx 1.20.x
load_module modules/ngx_http_brotli_static_module.so;
worker_processes auto;
worker_rlimit_nofile 16384;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
charset utf-8;
sendfile on;
sendfile_max_chunk 512k;
tcp_nopush on;
keepalive_timeout 3m;
server_tokens off;
msie_padding off;
client_max_body_size 1k;
client_body_buffer_size 1k;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
http2_recv_buffer_size 128k;
client_body_timeout 30s;
client_header_timeout 30s;
send_timeout 30s;
http2_max_concurrent_streams 32;
limit_conn_status 429;
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 256;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
ssl_conf_command Options PrioritizeChaCha;
ssl_certificate /etc/letsencrypt/live/grapheneos.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/grapheneos.org/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# maintained by nginx-rotate-session-ticket-keys in ramfs
ssl_session_ticket_key session-ticket-keys/4.key;
ssl_session_ticket_key session-ticket-keys/3.key;
ssl_session_ticket_key session-ticket-keys/2.key;
ssl_session_ticket_key session-ticket-keys/1.key;
ssl_buffer_size 4k;
ssl_trusted_certificate /etc/letsencrypt/live/grapheneos.org/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
# maintained by certbot-ocsp-fetcher
ssl_stapling_file ocsp-cache/grapheneos.org.der;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request_method $scheme://$host$request_uri $server_protocol" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main buffer=64k flush=1m;
error_log syslog:server=unix:/dev/log,nohostname;
log_not_found off;
gzip_proxied any;
gzip_vary on;
if_modified_since before;
map $http_cookie $preload_resources {
"~*__Host-preload=1" "";
default "<{{path|/main.css}}>; rel=preload; as=style; integrity={{integrity|/main.css}}, </fonts/roboto-v29-regular-latin.woff2>; rel=preload; as=font; crossorigin, </fonts/roboto-v29-bold-latin.woff2>; rel=preload; as=font; crossorigin, <{{path|/mask-icon.svg}}>; rel=preload; as=image";
}
server {
listen 80 backlog=4096;
listen [::]:80 backlog=4096;
server_name grapheneos.org www.grapheneos.org grapheneos.app www.grapheneos.app grapheneos.ca www.grapheneos.ca grapheneos.com www.grapheneos.com grapheneos.info www.grapheneos.info grapheneos.net www.grapheneos.net grapheneos.ovh www.grapheneos.ovh grapheneos.page www.grapheneos.page vanadium.app www.vanadium.app;
root /var/empty;
# use $host to set up HSTS for redirect domains
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name 0.grapheneos.org;
root /var/empty;
location /.well-known/acme-challenge/ {
root /srv/certbot;
}
location / {
return 301 https://grapheneos.org$request_uri;
}
}
server {
listen 443 ssl http2 backlog=4096;
listen [::]:443 ssl http2 backlog=4096;
server_name www.grapheneos.org grapheneos.app www.grapheneos.app grapheneos.ca www.grapheneos.ca grapheneos.com www.grapheneos.com grapheneos.info www.grapheneos.info grapheneos.net www.grapheneos.net grapheneos.ovh www.grapheneos.ovh grapheneos.page www.grapheneos.page;
root /var/empty;
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
location ^~ /.well-known/acme-challenge/ {
return 301 https://0.grapheneos.org$request_uri;
}
location / {
return 301 https://grapheneos.org$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name vanadium.app www.vanadium.app;
root /var/empty;
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
location ^~ /.well-known/acme-challenge/ {
return 301 https://0.grapheneos.org$request_uri;
}
location / {
return 302 https://github.com/GrapheneOS/Vanadium;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name grapheneos.org;
root /srv/grapheneos.org;
error_page 403 =404 /404;
error_page 404 /404;
open_file_cache max=2048 inactive=1d;
open_file_cache_valid 1d;
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
gzip_static on;
brotli_static on;
if ($request_uri ~ (.*)//(.*)) {
return 301 $1/$2;
}
location = /, {
return 301 /;
}
location = /security.txt {
return 301 /.well-known/security.txt;
}
location = /bitcoin-address.png {
return 301 /bitcoin-donation.png;
}
location = /pdfviewer_privacy_policy {
return 301 /pdfviewer-privacy-policy;
}
# mangled backlinks to /install
location = /installMinimal {
return 301 /install/;
}
# mangled backlink to /faq
location = /fa {
return 301 /faq;
}
location = /FAQ {
return 301 /faq;
}
# mangled backlinks to /usage#updates
location = /updates {
return 301 /usage#updates;
}
# broken link (now fixed) on https://noagendaphone.com/ with UTF-8 object replacement character
location = "/" {
return 301 /;
}
location = /web-install {
return 301 /install/web;
}
location = /install-web {
return 301 /install/web;
}
location = /cli/install {
return 301 /install/cli;
}
location = /web/install {
return 301 /install/web;
}
location = /LICENSE {
return 301 /LICENSE.txt;
}
location = /generate_204 {
return 301 /faq#default-connections;
}
location = /404 {
internal;
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
include snippets/preload.conf;
try_files $uri.html =404;
}
location = /favicon.ico {
if ($http_accept ~ "image/svg\+xml") {
rewrite ^ /favicon.svg last;
}
include snippets/security-headers.conf;
# avoid breaking image hotlinking such as https://github.com/TryGhost/Ghost/issues/12880
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Cache-Control "public, max-age=604800";
}
location = /favicon.svg {
include snippets/security-headers.conf;
# avoid breaking image hotlinking such as https://github.com/TryGhost/Ghost/issues/12880
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Cache-Control "public, max-age=604800";
}
location = /bimi.svg {
include snippets/security-headers.conf;
# allow https://bimigroup.org/bimi-generator/ to hotlink the image
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Cache-Control "public, max-age=604800";
}
location = {{path|/mask-icon.svg}} {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /.well-known/matrix/client {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Access-Control-Allow-Origin "*";
default_type application/json;
}
location = /.well-known/matrix/server {
default_type application/json;
}
location = /install/web {
include snippets/security-headers-base.conf;
add_header Content-Security-Policy "default-src 'none'; child-src 'self'; connect-src 'self' https://releases.grapheneos.org/; font-src 'self'; img-src 'self'; manifest-src 'self'; script-src 'self'; style-src 'self'; form-action 'none'; frame-ancestors 'none'; block-all-mixed-content; base-uri 'none'" always;
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), clipboard-read=(), clipboard-write=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), sync-xhr=(), xr-spatial-tracking=()" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, no-cache";
include snippets/preload.conf;
try_files $uri.html =404;
}
location ^~ /.well-known/acme-challenge/ {
return 301 https://0.grapheneos.org$request_uri;
}
location ^~ /fonts/ {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, max-age=31536000, immutable";
gzip_static off;
brotli_static off;
}
location ~ "/$" {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, no-cache";
include snippets/preload.conf;
try_files ${uri}index.html @noslash;
}
# redirect /path/ to /path if /path.html exists
location @noslash {
rewrite ^(.*)/$ $1;
if (-f $request_filename.html) {
rewrite ^(.*) $1 permanent;
}
return 404;
}
location ~ "\.(?:css|js|map|mjs)$" {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~ "\.webmanifest$" {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, max-age=604800";
}
location ~ "\.png$" {
include snippets/security-headers.conf;
# avoid breaking image hotlinking such as https://github.com/TryGhost/Ghost/issues/12880
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Cache-Control "public, max-age=31536000";
gzip_static off;
brotli_static off;
}
location ~ "\.(?:atom|pdf)$" {
include snippets/security-headers.conf;
# Chromium PDF range requests use wrong origin: https://bugs.chromium.org/p/chromium/issues/detail?id=1074261
# Thunderbird uses wrong origin for feeds: https://bugzilla.mozilla.org/show_bug.cgi?id=1698755
add_header Cross-Origin-Resource-Policy "cross-origin" always;
add_header Cache-Control "public, max-age=1800";
}
location ~ "\.(?:json|txt|xml)$" {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, max-age=1800";
}
# redirect away from the old SVG favicon location
location ~ /mask\-icon.svg {
return 301 /favicon.svg;
}
# https://www.twipu.com/GrapheneOS doesn't handle links with fragments properly
location ~ "^/([^\s]*)<a href=$" {
return 301 /$1;
}
location ~ "/index|\.(?:br|gz|html)$" {
internal;
}
location / {
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cache-Control "public, no-cache";
include snippets/preload.conf;
try_files $uri.html $uri/ =404;
}
}
server {
listen 80;
listen [::]:80;
server_name mta-sts.grapheneos.org mta-sts.mail.grapheneos.org mta-sts.grapheneos.app mta-sts.grapheneos.ca mta-sts.grapheneos.com mta-sts.grapheneos.info mta-sts.grapheneos.net mta-sts.grapheneos.ovh mta-sts.grapheneos.page mta-sts.vanadium.app;
root /var/empty;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mta-sts.grapheneos.org mta-sts.mail.grapheneos.org mta-sts.grapheneos.app mta-sts.grapheneos.ca mta-sts.grapheneos.com mta-sts.grapheneos.info mta-sts.grapheneos.net mta-sts.grapheneos.ovh mta-sts.grapheneos.page mta-sts.vanadium.app;
root /srv/mta-sts;
include snippets/security-headers.conf;
add_header Cross-Origin-Resource-Policy "same-origin" always;
location = / {
return 301 https://grapheneos.org/articles/grapheneos-servers;
}
location = /.well-known/mta-sts.txt {}
location ^~ /.well-known/acme-challenge/ {
return 301 https://0.grapheneos.org$request_uri;
}
location / {
return 404;
}
}
server {
listen 127.0.0.1:81;
listen [::1]:81;
root /var/empty;
location = /nginx_status {
stub_status;
access_log off;
}
location / {
return 404;
}
}
}