From f53c34c5d6b857f04e744de51ef353a5c678b2e8 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 14:37:48 -0400 Subject: [PATCH 01/11] Move Pleroma cache to /var/tmp /tmp is increasingly becoming tmpfs on a lot of distros and in cloud environments, so putting the cache there by default will be problematic --- installation/pleroma.nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 273cfb390..ca2edf2bd 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -6,7 +6,7 @@ # 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it # in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx. -proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g +proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off; # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only From 537d4d19c581208a70cbbc0ba032c1e9652ea24f Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 14:42:18 -0400 Subject: [PATCH 02/11] Move to the new method to enable http2 instead of on the listen socket statement --- installation/pleroma.nginx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index ca2edf2bd..ad0c3e5bb 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -41,8 +41,10 @@ ssl_session_cache shared:ssl_session_cache:10m; server { server_name example.tld; - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_tickets off; From 16796c292f986e1032f9f28447b7e3dba6857d63 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 14:44:48 -0400 Subject: [PATCH 03/11] Provide HTTP/3 config example --- installation/pleroma.nginx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index ad0c3e5bb..6ce86ec55 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -45,6 +45,17 @@ server { listen [::]:443 ssl; http2 on; + # Optional HTTP/3 support + # Note: requires you open UDP port 443 + # + # listen 443 quic reuseport; + # listen [::]:443 quic reuseport; + # http3 on; + # quic_retry on; + # ssl_early_data on; + # quic_gso on; + # add_header Alt-Svc 'h3=":443"; ma=86400'; + ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_tickets off; From 887a45488bed4c9d9737ebce810bdbe9f190ef3e Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:05:42 -0400 Subject: [PATCH 04/11] Provide example of configuring a dedicated media and proxy subdomain --- installation/pleroma.nginx | 70 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 6ce86ec55..e8caf58c5 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -107,6 +107,8 @@ server { # proxy_pass http://phoenix/notice/$1; # } + # Remove this location if you choose to use a dedicated subdomain + # for media and mediaproxy location ~ ^/(media|proxy) { proxy_cache pleroma_media_cache; slice 1m; @@ -120,3 +122,71 @@ server { proxy_pass http://phoenix; } } + +# It is strongly recommended that you host your media and the mediaproxy on a dedicated subdomain for security reasons. +# The following Pleroma settings will be required to enable this capability: +# +# config :pleroma, :media_proxy, +# base_url: "https://media.example.tld/" +# +# # Assuming default media upload deployment (e.g., not S3 which will require a different domain anyway) -- +# config :pleroma, Pleroma.Upload, +# base_url: "https://media.example.tld/uploads/", +# +# And then uncomment and configure the following server. +# Make sure your certificate was issued to support both domains or use a dedicated certificate: +# +# server { +# server_name media.example.tld; +# +# listen 443 ssl; +# listen [::]:443 ssl; +# http2 on; +# +# # Optional HTTP/3 support +# # Note: requires you open UDP port 443 +# # +# # listen 443 quic reuseport; +# # listen [::]:443 quic reuseport; +# # http3 on; +# # quic_retry on; +# # ssl_early_data on; +# # quic_gso on; +# # add_header Alt-Svc 'h3=":443"; ma=86400'; +# +# ssl_session_timeout 1d; +# ssl_session_cache shared:MozSSL:10m; # about 40000 sessions +# ssl_session_tickets off; +# +# ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem; +# ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; +# +# ssl_protocols TLSv1.2 TLSv1.3; +# ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; +# ssl_prefer_server_ciphers off; +# # In case of an old server with an OpenSSL version of 1.0.2 or below, +# # leave only prime256v1 or comment out the following line. +# ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; +# ssl_stapling on; +# ssl_stapling_verify on; +# +# proxy_http_version 1.1; +# proxy_set_header Upgrade $http_upgrade; +# proxy_set_header Connection "upgrade"; +# proxy_set_header Host $http_host; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# +# location ~ ^/(media|proxy) { +# proxy_cache pleroma_media_cache; +# slice 1m; +# proxy_cache_key $host$uri$is_args$args$slice_range; +# proxy_set_header Range $slice_range; +# proxy_cache_valid 200 206 301 304 1h; +# proxy_cache_lock on; +# proxy_ignore_client_abort on; +# proxy_buffering on; +# chunked_transfer_encoding on; +# proxy_pass http://phoenix; +# } +# } From f06a7b51e286ac80606f3e987d72c3ace796c038 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:09:53 -0400 Subject: [PATCH 05/11] Annotate the Nginx media upload limit --- installation/pleroma.nginx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index e8caf58c5..c9cdca681 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -80,8 +80,14 @@ server { gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml; - # the nginx default is 1m, not enough for large media uploads + # Nginx media upload limitation + # Ensure that this value matches or exceeds your Pleroma upload limit: + # + # config :pleroma, :instance, + # upload_limit: 16_000_000 + # client_max_body_size 16m; + ignore_invalid_headers off; proxy_http_version 1.1; From 6b596ca8e2bf5a29ba0539f00c9adf9e0de3f391 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:11:37 -0400 Subject: [PATCH 06/11] Update the example Nginx config --- changelog.d/nginx-config.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/nginx-config.change diff --git a/changelog.d/nginx-config.change b/changelog.d/nginx-config.change new file mode 100644 index 000000000..3455e3a7b --- /dev/null +++ b/changelog.d/nginx-config.change @@ -0,0 +1 @@ +Updated the example Nginx configuration From 90e0911cdbc59215e7d6910959abf27ff216e13c Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:19:57 -0400 Subject: [PATCH 07/11] Provide full uploads config for a subdomain --- installation/pleroma.nginx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index c9cdca681..093c4de43 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -139,6 +139,8 @@ server { # config :pleroma, Pleroma.Upload, # base_url: "https://media.example.tld/uploads/", # +# config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" +# # And then uncomment and configure the following server. # Make sure your certificate was issued to support both domains or use a dedicated certificate: # @@ -183,6 +185,11 @@ server { # proxy_set_header Host $http_host; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # +# location ~ /uploads { +# root /var/lib/pleroma; +# allow all; +# } +# # location ~ ^/(media|proxy) { # proxy_cache pleroma_media_cache; # slice 1m; From 2870140db2a38960f000db3889fc1d83843aa015 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:27:30 -0400 Subject: [PATCH 08/11] The /media route has not existed for some years now --- installation/pleroma.nginx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 093c4de43..5d547729a 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -114,8 +114,8 @@ server { # } # Remove this location if you choose to use a dedicated subdomain - # for media and mediaproxy - location ~ ^/(media|proxy) { + # for mediaproxy + location /proxy { proxy_cache pleroma_media_cache; slice 1m; proxy_cache_key $host$uri$is_args$args$slice_range; @@ -190,7 +190,7 @@ server { # allow all; # } # -# location ~ ^/(media|proxy) { +# location /proxy { # proxy_cache pleroma_media_cache; # slice 1m; # proxy_cache_key $host$uri$is_args$args$slice_range; From 503e43da5d9f211d812eb3310bcedff4843e1934 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 25 Sep 2024 15:36:20 -0400 Subject: [PATCH 09/11] Document the /uploads location more thoroughly --- installation/pleroma.nginx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 5d547729a..40ab61326 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -127,6 +127,18 @@ server { chunked_transfer_encoding on; proxy_pass http://phoenix; } + + # Nginx can serve the local file uploads directly reducing work for + # the backend. Make sure to change this to a "deny all" if you use + # a dedicated subdomain. It will break access to uploads that have already + # federated if you are converting an existing installation, so weigh the risks + # carefully. + # + # location /uploads { + # root /var/lib/pleroma; <-- make sure this is correct for your deployment + # allow all; + # } + } # It is strongly recommended that you host your media and the mediaproxy on a dedicated subdomain for security reasons. @@ -185,7 +197,7 @@ server { # proxy_set_header Host $http_host; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # -# location ~ /uploads { +# location /uploads { # root /var/lib/pleroma; # allow all; # } From 045dfaf2aff900daaac67942d7f727ff1b46a6e6 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 30 Oct 2024 10:45:06 -0400 Subject: [PATCH 10/11] Fix nginx location for serving media directly --- installation/pleroma.nginx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 40ab61326..5d6d35f0c 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -134,8 +134,8 @@ server { # federated if you are converting an existing installation, so weigh the risks # carefully. # - # location /uploads { - # root /var/lib/pleroma; <-- make sure this is correct for your deployment + # location /media/ { + # alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment # allow all; # } @@ -197,8 +197,8 @@ server { # proxy_set_header Host $http_host; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # -# location /uploads { -# root /var/lib/pleroma; +# location /media/ { # <-- make sure this path matches your Pleroma.Upload :base_url +# alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment # allow all; # } # From 2b8a366f9b849905ad734d176cac889ee99e9ed5 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Mon, 22 Dec 2025 16:10:02 +0400 Subject: [PATCH 11/11] Nginx example: Add headers and use same paths we use in other places --- docs/configuration/howto_mediaproxy.md | 4 +++- installation/pleroma.nginx | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/configuration/howto_mediaproxy.md b/docs/configuration/howto_mediaproxy.md index 16c40c5db..92840c6ba 100644 --- a/docs/configuration/howto_mediaproxy.md +++ b/docs/configuration/howto_mediaproxy.md @@ -16,7 +16,9 @@ location /proxy { ``` Also add the following on top of the configuration, outside of the `server` block: ``` -proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off; +# Note: The cache directory must exist and be writable by nginx. +# If nginx runs in a chroot, create it inside the chroot. +proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off; ``` If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included. diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 5d6d35f0c..8d9e950a8 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -6,6 +6,8 @@ # 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it # in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx. +# Note: The cache directory must exist and be writable by nginx. +# If nginx runs in a chroot, create it inside the chroot. proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off; @@ -137,6 +139,8 @@ server { # location /media/ { # alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment # allow all; + # add_header X-Content-Type-Options "nosniff"; + # add_header Content-Security-Policy "sandbox"; # } } @@ -149,7 +153,7 @@ server { # # # Assuming default media upload deployment (e.g., not S3 which will require a different domain anyway) -- # config :pleroma, Pleroma.Upload, -# base_url: "https://media.example.tld/uploads/", +# base_url: "https://media.example.tld/media/", # # config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" # @@ -200,6 +204,8 @@ server { # location /media/ { # <-- make sure this path matches your Pleroma.Upload :base_url # alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment # allow all; +# add_header X-Content-Type-Options "nosniff"; +# add_header Content-Security-Policy "sandbox"; # } # # location /proxy {