# Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: let localhost = "127.0.0.1"; jellyfinPort = 8086; nextcloudPort = 80; # unstable_tarball = # builtins.fetchTarball "https://github.com/nixos/nixpkgs/tarball/master"; # unstable = import unstable_tarball { config = config.nixpkgs.config; }; in { services.nginx = { enable = true; recommendedTlsSettings = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; commonHttpConfig = '' ### GLOBAL # Add HSTS header with preloading to HTTPS requests. # Adding this header to HTTP requests is discouraged map $scheme $hsts_header { https "max-age=31536000; includeSubdomains; preload"; } add_header Strict-Transport-Security $hsts_header; # Enable CSP for your services. #add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always; # Minimize information leaked to other domains add_header 'Referrer-Policy' 'origin-when-cross-origin'; # Disable embedding as a frame add_header X-Frame-Options DENY; # Prevent injection of code in other mime types (XSS Attacks) add_header X-Content-Type-Options nosniff; # Enable XSS protection of the browser. # May be unnecessary when CSP is configured properly (see above) add_header X-XSS-Protection "1; mode=block"; # This might create errors proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; ### NEXTCLOUD # upstream php-handler { # server 127.0.0.1:9000; # #server unix:/var/run/php/php7.4-fpm.sock; # } # Set the `immutable` cache control options only for assets with a cache busting `v` argument # map $arg_v $asset_immutable { # "" ""; # default "immutable"; # } ### JELLYFIN proxy_cache_path /var/cache/nginx/jellyfin-videos levels=1:2 keys_zone=jellyfin-videos:100m inactive=90d max_size=35000m; proxy_cache_path /var/cache/nginx/jellyfin levels=1:2 keys_zone=jellyfin:100m max_size=15g inactive=30d use_temp_path=off; map $request_uri $h264Level { ~(h264-level=)(.+?)& $2; } map $request_uri $h264Profile { ~(h264-profile=)(.+?)& $2; } ''; virtualHosts = let base = locations: { inherit locations; forceSSL = true; enableACME = true; http2 = true; }; proxy = port: base { "/".proxyPass = "http://127.0.0.1:" + toString (port) + "/"; }; in { "flix.servidos.lat" = { forceSSL = true; enableACME = true; http2 = true; extraConfig = '' # use a variable to store the upstream proxy # in this example we are using a hostname which is resolved via DNS # (if you aren't using DNS remove the resolver line and change the variable to point to an IP address # e.g `set $jellyfin 127.0.0.1`) set $jellyfin 127.0.0.1; resolver 127.0.0.1 valid=30; location = / { return 302 http://$host/web/; #return 302 https://$host/web/; } location = /web/ { # Proxy main Jellyfin traffic proxy_pass http://$jellyfin:8096/web/index.html; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Forwarded-Host $http_host; } ''; locations = { "/" = { proxyPass = "http://$jellyfin:8096"; proxyWebsockets = true; }; "/socket" = { proxyPass = "http://$jellyfin:8096"; extraConfig = '' proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; ''; }; "~ /Items/(.*)/Images" = { proxyPass = "http://$jellyfin:8096"; extraConfig = '' proxy_cache jellyfin; proxy_cache_revalidate on; proxy_cache_lock on; ''; }; "~* ^/Videos/(.*)/(?!live)" = { proxyPass = "http://$jellyfin:8096"; extraConfig = '' # Set size of a slice (this amount will be always requested from the backend by nginx) # Higher value means more latency, lower more overhead # This size is independent of the size clients/browsers can request # 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 2m; # This saves bandwidth between the proxy and jellyfin, as a file is only downloaded one time instead of multiple times when multiple clients want to at the same time # The first client will trigger the download, the other clients will have to wait until the slice is cached # Esp. practical during SyncPlay proxy_cache_lock on; proxy_cache_lock_age 60s; 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=2m"; # add_header X-Cache-Status $upstream_cache_status; # This is only for debugging cache ''; }; }; }; "library.servidos.lat" = proxy 5000 // { }; ${config.services.nextcloud.hostName} = { forceSSL = true; enableACME = true; http2 = true; # extraConfig = '' # server_tokens off; # # set max upload size and increase upload timeout: # client_body_timeout 300s; # # fastcgi_buffers 64 4K; # # The settings allows you to optimize the HTTP2 bandwitdth. # # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/ # # for tunning hints # client_body_buffer_size 512k; # # HTTP response headers borrowed from Nextcloud `.htaccess` # add_header Referrer-Policy "no-referrer" always; # add_header X-Download-Options "noopen" always; # add_header X-Permitted-Cross-Domain-Policies "none" always; # add_header X-Robots-Tag "noindex, nofollow" always; # # Remove X-Powered-By, which is an information leak # fastcgi_hide_header X-Powered-By; # # Specify how to handle directories -- specifying `/index.php$request_uri` # # here as the fallback means that Nginx always exhibits the desired behaviour # # when a client requests a path that corresponds to a directory that exists # # on the server. In particular, if that directory contains an index.php file, # # that file is correctly served; if it doesn't, then the request is passed to # # the front-end controller. This consistent behaviour means that we don't need # # to specify custom rules for certain paths (e.g. images and other assets, # # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus # # `try_files $uri $uri/ /index.php$request_uri` # # always provides the desired behaviour. # index index.php index.html /index.php$request_uri; # ''; # locations = { # "/".extraConfig = '' # try_files $uri $uri/ /index.php$request_uri; # ''; # "= /".extraConfig = '' # # Rule borrowed from `.htaccess` to handle Microsoft DAV clients # if ( $http_user_agent ~ ^DavClnt ) { # return 302 /remote.php/webdav/$is_args$args; # } # ''; # "^~ /.well-known".extraConfig = '' # # The rules in this block are an adaptation of the rules # # in `.htaccess` that concern `/.well-known`. # location /.well-known/acme-challenge { try_files $uri $uri/ =404; } # location /.well-known/pki-validation { try_files $uri $uri/ =404; } # # Let Nextcloud's API for `/.well-known` URIs handle all other # # requests by passing them to the front-end controller. # return 301 /index.php$request_uri; # ''; # "~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)".extraConfig = # "return 404;"; # "~ ^/(?:.|autotest|occ|issue|indie|db_|console)".extraConfig = # "return 404;"; # "~ .php(?:$|/)".extraConfig = '' # # Required for legacy support # rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; # fastcgi_split_path_info ^(.+?\.php)(/.*)$; # set $path_info $fastcgi_path_info; # try_files $fastcgi_script_name =404; # # include fastcgi_params; # include "${pkgs.nginx}/conf/fastcgi_params"; # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # fastcgi_param PATH_INFO $path_info; # fastcgi_param HTTPS on; # fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice # fastcgi_param front_controller_active true; # Enable pretty urls # fastcgi_intercept_errors on; # fastcgi_request_buffering off; # fastcgi_max_temp_file_size 0; # ''; # "~ .(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$" = { # extraConfig = '' # try_files $uri /index.php$request_uri; # access_log off; # Optional: Don't log access to assets # location ~ \.wasm$ { # default_type application/wasm; # } # ''; # }; # "~ .woff2?$".extraConfig = '' # try_files $uri /index.php$request_uri; # expires 7d; # Cache-Control policy borrowed from `.htaccess` # access_log off; # Optional: Don't log access to assets ''; # "/remote".extraConfig = "return 301 /remote.php$request_uri;"; # }; }; }; }; }