From 5922e293692d7e7e904adc80006d671e32a8e3d4 Mon Sep 17 00:00:00 2001 From: Trammell Hudson Date: Tue, 6 Dec 2022 12:56:58 +0000 Subject: [PATCH] Enable nginx caching and optimizations. This patch enabled nginx caching of responses for non-logged in users so that a boost by a popular mastodon user doesn't DDOS the bookwyrm site. It also silences some of the nginx access logs so that static files are not logged. --- nginx/development | 66 ++++++++++++++++++++++++++++++++++++--------- nginx/server_config | 20 ++++++++++++++ 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/nginx/development b/nginx/development index be33cea17..1345051bc 100644 --- a/nginx/development +++ b/nginx/development @@ -5,29 +5,69 @@ upstream web { } server { + access_log /var/log/nginx/access.log cache_log; + listen 80; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + #include /etc/nginx/mime.types; + #default_type application/octet-stream; + + gzip on; + gzip_disable "msie6"; + + proxy_read_timeout 1800s; + chunked_transfer_encoding on; + + # store responses to anonymous users for up to 1 minute + proxy_cache bookwyrm_cache; + proxy_cache_valid any 1m; + add_header X-Cache-Status $upstream_cache_status; + + # ignore the set cookie header when deciding to + # store a response in the cache + proxy_ignore_headers Cache-Control Set-Cookie Expires; + + # PUT requests always bypass the cache + # logged in sessions also do not populate the cache + # to avoid serving personal data to anonymous users + proxy_cache_methods GET HEAD; + proxy_no_cache $cookie_sessionid; + proxy_cache_bypass $cookie_sessionid; + + # tell the web container the address of the outside client + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + + # rate limit the login or password reset pages location ~ ^/(login[^-/]|password-reset|resend-link|2fa-check) { limit_req zone=loginlimit; - proxy_pass http://web; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - proxy_redirect off; } + # do not log periodic polling requests from logged in users + location /api/updates/ { + access_log off; + proxy_pass http://web; + } + + # forward any cache misses or bypass to the web container location / { proxy_pass http://web; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - proxy_redirect off; } - location /images/ { - alias /app/images/; - } - - location /static/ { - alias /app/static/; + # directly serve images and static files from the + # bookwyrm filesystem using sendfile. + # make the logs quieter by not reporting these requests + location ~ ^/(images|static)/ { + root /app; + try_files $uri =404; + add_header X-Cache-Status STATIC; + access_log off; } } diff --git a/nginx/server_config b/nginx/server_config index 385f747ec..8afab66a5 100644 --- a/nginx/server_config +++ b/nginx/server_config @@ -1,2 +1,22 @@ client_max_body_size 10m; limit_req_zone $binary_remote_addr zone=loginlimit:10m rate=1r/s; + +# include the cache status in the log message +log_format cache_log '$upstream_cache_status - ' + '$remote_addr [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '$upstream_response_time $request_time'; + +# Create a cache for responses from the web app +proxy_cache_path + /var/cache/nginx/bookwyrm_cache + keys_zone=bookwyrm_cache:20m + loader_threshold=400 + loader_files=400 + max_size=400m; + +# use the accept header as part of the cache key +# since activitypub endpoints have both HTML and JSON +# on the same URI. +proxy_cache_key $scheme$proxy_host$uri$is_args$args$http_accept;