diff --git a/.gitignore b/.gitignore index 03bd412..2115fd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.env +**/*.env \ No newline at end of file diff --git a/docker-compose.certbot.yml b/docker-compose.certbot.yml index 2c04307..af6bea2 100644 --- a/docker-compose.certbot.yml +++ b/docker-compose.certbot.yml @@ -4,7 +4,7 @@ services: certbot: depends_on: - webserver - image: certbot/certbot:v1.32.0 + image: certbot/certbot:v2.5.0 container_name: certbot profiles: - certbot diff --git a/nginx/conf.d/jellyfin.conf b/nginx/conf.d/jellyfin.conf index 2abc52c..24c386e 100644 --- a/nginx/conf.d/jellyfin.conf +++ b/nginx/conf.d/jellyfin.conf @@ -1,7 +1,4 @@ -proxy_cache_path /var/cache/nginx/jellyfin levels=1:2 keys_zone=jellyfin:100m max_size=3g inactive=30d use_temp_path=off; -proxy_cache_path /var/cache/nginx/jellyfin-videos levels=1:2 keys_zone=jellyfin-videos:100m inactive=90d max_size=3g; -map $request_uri $h264Level { ~(h264-level=)(.+?)& $2; } -map $request_uri $h264Profile { ~(h264-profile=)(.+?)& $2; } +proxy_cache_path /var/cache/nginx/jellyfin levels=1:2 keys_zone=jellyfin:100m max_size=2g inactive=30d use_temp_path=off; upstream jellyfin_server { # ip_hash; @@ -33,9 +30,8 @@ server { listen [::]:443 ssl http2; server_name jellyfin.bensuperpc.org www.jellyfin.bensuperpc.org; - #client_max_body_size 20M; - set $jellyfin jellyfin; - resolver 8.8.8.8 valid=30; + ## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc. + client_max_body_size 20M; # All things related to SSL ssl_certificate /etc/letsencrypt/live/bensuperpc.org/fullchain.pem; @@ -44,19 +40,33 @@ server { include /etc/nginx/conf.d/sub/options-ssl-nginx.conf; - #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - #add_header Strict-Transport-Security "max-age=31536000" always; + # Logging + access_log /var/log/nginx/wordpress.access.log; + error_log /var/log/nginx/wordpress.error.log; + + # Security + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # Security / XSS Mitigation Headers # NOTE: X-Frame-Options may cause issues with the webOS app add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; - #add_header Content-Security-Policy "default-src https: data: blob: http://image.tmdb.org; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.gstatic.com/eureka/clank/95/cast_sender.js https://www.gstatic.com/eureka/clank/96/cast_sender.js https://www.gstatic.com/eureka/clank/97/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'"; + + # Content Security Policy + # See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP + # Enforces https content and restricts JS/CSS to origin + # External Javascript (such as cast_sender.js for Chromecast) must be whitelisted. + # NOTE: The default CSP headers may cause issues with the webOS app + add_header Content-Security-Policy "default-src https: data: blob: http://image.tmdb.org; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.gstatic.com/eureka/clank/95/cast_sender.js https://www.gstatic.com/eureka/clank/96/cast_sender.js https://www.gstatic.com/eureka/clank/97/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'"; location = / { - return 302 http://$host/web/; - #return 302 https://$host/web/; + return 302 https://$host/web/; } location / { @@ -73,6 +83,7 @@ server { proxy_buffering off; } + # location block for /web - This is purely for aesthetics so /web/#!/ works instead of having to go to /web/index.html/#!/ location = /web/ { # Proxy main Jellyfin traffic proxy_pass http://jellyfin_server/web/index.html; @@ -98,10 +109,9 @@ server { proxy_set_header X-Forwarded-Host $http_host; } - # Cache images + # Cache images (inside server block) location ~ /Items/(.*)/Images { - #proxy_pass http://127.0.0.1:8096; - proxy_pass http://jellyfin_server; + proxy_pass http://127.0.0.1:8096; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -114,31 +124,6 @@ server { proxy_cache_lock on; add_header X-Cache-Status $upstream_cache_status; # This is only to check if cache is working } - - # Cache videos - location ~* ^/Videos/(.*)/(?!live) - { - slice 2m; - - proxy_cache jellyfin-videos; - proxy_cache_valid 200 206 301 302 30d; - proxy_ignore_headers Expires Cache-Control Set-Cookie X-Accel-Expires; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - proxy_connect_timeout 15s; - proxy_http_version 1.1; - proxy_set_header Connection ""; - # Transmit slice range to the backend - proxy_set_header Range $slice_range; - - proxy_cache_lock on; - proxy_cache_lock_age 60s; - - #proxy_pass http://$jellyfin:8096; - proxy_pass http://jellyfin_server; - proxy_cache_key "jellyvideo$uri?MediaSourceId=$arg_MediaSourceId&VideoCodec=$arg_VideoCodec&AudioCodec=$arg_AudioCodec&AudioStreamIndex=$arg_AudioStreamIndex&VideoBitrate=$arg_VideoBitrate&AudioBitrate=$arg_AudioBitrate&SubtitleMethod=$arg_SubtitleMethod&TranscodingMaxAudioChannels=$arg_TranscodingMaxAudioChannels&RequireAvc=$arg_RequireAvc&SegmentContainer=$arg_SegmentContainer&MinSegments=$arg_MinSegments&BreakOnNonKeyFrames=$arg_BreakOnNonKeyFrames&h264-profile=$h264Profile&h264-level=$h264Level&slicerange=$slice_range"; - - add_header X-Cache-Status $upstream_cache_status; # This is only for debugging cache - } } -# All configuration options are documented at https://jellyfin.org/docs/general/networking/nginx/ +# All configuration options are documented at https://jellyfin.org/docs/general/networking/nginx/ \ No newline at end of file diff --git a/nginx/conf.d/minecraft.conf b/nginx/conf.d/minecraft.conf deleted file mode 100644 index 4293540..0000000 --- a/nginx/conf.d/minecraft.conf +++ /dev/null @@ -1,12 +0,0 @@ -#upstream minecraft { -# server minecraft:25565; -#} -# -#server { -# listen 25566; -# server_name minecraft.bensuperpc.org www.minecraft.bensuperpc.org; -# location / { -# proxy_pass minecraft; -# } -#} - diff --git a/nginx/conf.d/phpmyadmin.conf b/nginx/conf.d/phpmyadmin.conf index d0aeccf..5b534c5 100644 --- a/nginx/conf.d/phpmyadmin.conf +++ b/nginx/conf.d/phpmyadmin.conf @@ -15,8 +15,6 @@ server { server_name phpmyadmin.bensuperpc.org www.phpmyadmin.bensuperpc.org; - include /etc/nginx/conf.d/sub/gzip.conf; - location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; diff --git a/nginx/conf.d/qbittorrent.conf b/nginx/conf.d/qbittorrent.conf index 3419cd9..e46cfc3 100644 --- a/nginx/conf.d/qbittorrent.conf +++ b/nginx/conf.d/qbittorrent.conf @@ -13,8 +13,6 @@ server { server_name qbittorrent.bensuperpc.org www.qbittorrent.bensuperpc.org; - include /etc/nginx/conf.d/sub/gzip.conf; - location / { proxy_pass http://qbittorrent_server; proxy_redirect off; diff --git a/nginx/conf.d/stream/minecraft.conf b/nginx/conf.d/stream/minecraft.conf new file mode 100644 index 0000000..bf6d39b --- /dev/null +++ b/nginx/conf.d/stream/minecraft.conf @@ -0,0 +1,6 @@ +#server { + # Port number the reverse proxy is listening on +# listen 25565; + # The original Minecraft server address +# proxy_pass server.example.com:25565; +#} \ No newline at end of file diff --git a/nginx/conf.d/wordpress.conf b/nginx/conf.d/wordpress.conf index e6e7362..b1180cb 100644 --- a/nginx/conf.d/wordpress.conf +++ b/nginx/conf.d/wordpress.conf @@ -17,12 +17,6 @@ server { root /var/www/wordpress; index index.php index.html index.htm; - # Keepalive for 70 seconds - keepalive_timeout 70; - - # Number of requests per connection - keepalive_requests 100; - reset_timedout_connection on; # Upload limit @@ -52,9 +46,7 @@ server { server_tokens off; - include /etc/nginx/conf.d/sub/gzip.conf; - - location ~ /.well-known/acme-challenge { + location ~ /.well-knownwell-known/acme-challenge { allow all; root /var/www/wordpress; } @@ -84,6 +76,10 @@ server { # Use the WORDPRESS zone fastcgi_cache WORDPRESS; + + fastcgi_connect_timeout 600; + fastcgi_send_timeout 600; + fastcgi_read_timeout 600; } # Don't write to accesslog for these files @@ -133,12 +129,6 @@ server { root /var/www/wordpress; index index.php index.html index.htm; - # Keepalive for 70 seconds - keepalive_timeout 70; - - # Number of requests per connection - keepalive_requests 100; - reset_timedout_connection on; # Upload limit @@ -167,8 +157,6 @@ server { } server_tokens off; - - include /etc/nginx/conf.d/sub/gzip.conf; # All things related to SSL ssl_certificate /etc/letsencrypt/live/bensuperpc.org/fullchain.pem; diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 2703483..b1a91c0 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -24,9 +24,17 @@ http { sendfile on; #tcp_nopush on; - keepalive_timeout 65; + # Keepalive for 70 seconds + keepalive_timeout 70; - #gzip on; + # Number of requests per connection + keepalive_requests 100; + + include /etc/nginx/conf.d/sub/gzip.conf; include /etc/nginx/conf.d/*.conf; } + +stream { + include /etc/nginx/conf.d/stream/*.conf; +}