diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ea649111..66427764c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators.
- Admin API: Reports now ordered by newest
- Deprecated `Pleroma.Uploaders.S3, :public_endpoint`. Now `Pleroma.Upload, :base_url` is the standard configuration key for all uploaders.
+- Improved Apache webserver support: updated sample configuration, MediaProxy cache invalidation verified with the included sample script
### Added
diff --git a/config/config.exs b/config/config.exs
index c4a690799..5eca250bb 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -438,7 +438,9 @@
headers: [],
options: []
-config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil
+config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script,
+ script_path: nil,
+ url_format: nil
# Note: media preview proxy depends on media proxy to be enabled
config :pleroma, :media_preview_proxy,
diff --git a/config/description.exs b/config/description.exs
index 715a0d0c3..d7dc264ee 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -1627,13 +1627,20 @@
group: :pleroma,
key: Pleroma.Web.MediaProxy.Invalidation.Script,
type: :group,
- description: "Script invalidate settings",
+ description: "Invalidation script settings",
children: [
%{
key: :script_path,
type: :string,
- description: "Path to shell script. Which will run purge cache.",
+ description: "Path to executable script which will purge cached items.",
suggestions: ["./installation/nginx-cache-purge.sh.example"]
+ },
+ %{
+ key: :url_format,
+ type: :string,
+ description:
+ "Optional URL format preprocessing. Only required for Apache's htcacheclean.",
+ suggestions: [":htcacheclean"]
}
]
},
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index 5c0fd6487..9d4b07bf4 100644
--- a/docs/configuration/cheatsheet.md
+++ b/docs/configuration/cheatsheet.md
@@ -321,9 +321,10 @@ This section describe PWA manifest instance-specific values. Currently this opti
#### Pleroma.Web.MediaProxy.Invalidation.Script
This strategy allow perform external shell script to purge cache.
-Urls of attachments pass to script as arguments.
+Urls of attachments are passed to the script as arguments.
-* `script_path`: path to external script.
+* `script_path`: Path to the external script.
+* `url_format`: Set to `:htcacheclean` if using Apache's htcacheclean utility.
Example:
diff --git a/installation/apache-cache-purge.sh.example b/installation/apache-cache-purge.sh.example
new file mode 100755
index 000000000..7b4262875
--- /dev/null
+++ b/installation/apache-cache-purge.sh.example
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# A simple shell script to delete a media from Apache's mod_disk_cache.
+# You will likely need to setup a sudo rule like the following:
+#
+# Cmnd_Alias HTCACHECLEAN = /usr/local/sbin/htcacheclean
+# pleroma ALL=HTCACHECLEAN, NOPASSWD: HTCACHECLEAN
+#
+# Please also ensure you have enabled:
+#
+# config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, url_format: :htcacheclean
+#
+# which will correctly format the URLs passed to this script for the htcacheclean utility.
+#
+
+SCRIPTNAME=${0##*/}
+
+# mod_disk_cache directory
+CACHE_DIRECTORY="/tmp/pleroma-media-cache"
+
+## Removes an item via the htcacheclean utility
+## $1 - the filename, can be a pattern .
+## $2 - the cache directory.
+purge_item() {
+ sudo htcacheclean -v -p "${2}" "${1}"
+} # purge_item
+
+purge() {
+ for url in $@
+ do
+ echo "$SCRIPTNAME delete \`$url\` from cache ($CACHE_DIRECTORY)"
+ purge_item "$url" $CACHE_DIRECTORY
+ done
+}
+
+purge $@
diff --git a/installation/pleroma-apache.conf b/installation/pleroma-apache.conf
index 0d627f2d7..139abe9e1 100644
--- a/installation/pleroma-apache.conf
+++ b/installation/pleroma-apache.conf
@@ -1,73 +1,84 @@
-# default Apache site config for Pleroma
-#
-# needed modules: define headers proxy proxy_http proxy_wstunnel rewrite ssl
-# optional modules: cache cache_disk
+# Sample Apache config for Pleroma
#
# Simple installation instructions:
-# 1. Install your TLS certificate, possibly using Let's Encrypt.
-# 2. Replace 'example.tld' with your instance's domain wherever it appears.
-# 3. This assumes a Debian style Apache config. Copy this file to
-# /etc/apache2/sites-available/ and then add a symlink to it in
-# /etc/apache2/sites-enabled/ by running 'a2ensite pleroma-apache.conf', then restart Apache.
+# 1. Install your TLS certificate. We recommend using Let's Encrypt via Certbot
+# 2. Replace 'example.tld' with your instance's domain.
+# 3. This assumes a Debian-style Apache config. Copy this file to
+# /etc/apache2/sites-available/ and then activate the site by running
+# 'a2ensite pleroma-apache.conf', then restart Apache.
#
# Optional: enable disk-based caching for the media proxy
# For details, see https://git.pleroma.social/pleroma/pleroma/wikis/How%20to%20activate%20mediaproxy
#
-# 1. Create the directory listed below as the CacheRoot, and make sure
+# 1. Create a directory as shown below for the CacheRoot and make sure
# the Apache user can write to it.
# 2. Configure Apache's htcacheclean to clean the directory periodically.
-# 3. Run 'a2enmod cache cache_disk' and restart Apache.
+# Your OS may provide a service you can enable to do this automatically.
Define servername example.tld
+
+ LoadModule proxy_module libexec/apache24/mod_proxy.so
+
+
+ LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
+
+
+ LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so
+
+
+ LoadModule rewrite_module libexec/apache24/mod_rewrite.so
+
+
+ LoadModule ssl_module libexec/apache24/mod_ssl.so
+
+
+ LoadModule cache_module libexec/apache24/mod_cache.so
+
+
+ LoadModule cache_disk_module libexec/apache24/mod_cache_disk.so
+
+
ServerName ${servername}
ServerTokens Prod
-ErrorLog ${APACHE_LOG_DIR}/error.log
-CustomLog ${APACHE_LOG_DIR}/access.log combined
+# If you want Pleroma-specific logs
+#ErrorLog /var/log/httpd-pleroma-error.log
+#CustomLog /var/log/httpd-pleroma-access.log combined
- Redirect permanent / https://${servername}
+ RewriteEngine on
+ RewriteCond %{SERVER_NAME} =${servername}
+ RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/${servername}/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/${servername}/privkey.pem
+ # Make sure you have the certbot-apache module installed
+ Include /etc/letsencrypt/options-ssl-apache.conf
- # Mozilla modern configuration, tweak to your needs
- SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
- SSLCipherSuite 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:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
- SSLHonorCipherOrder on
- SSLCompression off
- SSLSessionTickets off
-
- # uncomment the following to enable mediaproxy caching on disk
- #
- # CacheRoot /var/cache/apache2/mod_cache_disk
- # CacheDirLevels 1
- # CacheDirLength 2
- # CacheEnable disk /proxy
- # CacheLock on
- #
+ # Uncomment the following to enable MediaProxy caching on disk
+ #CacheRoot /tmp/pleroma-media-cache/
+ #CacheDirLevels 1
+ #CacheDirLength 2
+ #CacheEnable disk /proxy
+ #CacheLock on
+ #CacheHeader on
+ #CacheDetailHeader on
+ ## 16MB max filesize for caching, configure as desired
+ #CacheMaxFileSize 16000000
+ #CacheDefaultExpire 86400
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
- RewriteRule /(.*) ws://localhost:4000/$1 [P,L]
+ RewriteRule /(.*) ws://127.0.0.1:4000/$1 [P,L]
+ #ProxyRequests must be off or you open your server to abuse as an open proxy
ProxyRequests off
- # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
- # and `localhost.` resolves to [::0] on some systems: see issue #930
ProxyPass / http://127.0.0.1:4000/
ProxyPassReverse / http://127.0.0.1:4000/
-
- RequestHeader set Host ${servername}
ProxyPreserveHost On
-
-# OCSP Stapling, only in httpd 2.3.3 and later
-SSLUseStapling on
-SSLStaplingResponderTimeout 5
-SSLStaplingReturnResponderErrors off
-SSLStaplingCache shmcb:/var/run/ocsp(128000)
diff --git a/lib/pleroma/web/media_proxy/invalidation/script.ex b/lib/pleroma/web/media_proxy/invalidation/script.ex
index 0f66c2fe3..87a21166c 100644
--- a/lib/pleroma/web/media_proxy/invalidation/script.ex
+++ b/lib/pleroma/web/media_proxy/invalidation/script.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.Script do
def purge(urls, opts \\ []) do
args =
urls
+ |> maybe_format_urls(Keyword.get(opts, :url_format))
|> List.wrap()
|> Enum.uniq()
|> Enum.join(" ")
@@ -40,4 +41,22 @@ defp handle_result(error, _) do
Logger.error("Error while cache purge: #{inspect(error)}")
{:error, inspect(error)}
end
+
+ def maybe_format_urls(urls, :htcacheclean) do
+ urls
+ |> Enum.map(fn url ->
+ uri = URI.parse(url)
+
+ query =
+ if !is_nil(uri.query) do
+ "?" <> uri.query
+ else
+ "?"
+ end
+
+ uri.scheme <> "://" <> uri.host <> ":#{inspect(uri.port)}" <> uri.path <> query
+ end)
+ end
+
+ def maybe_format_urls(urls, _), do: urls
end
diff --git a/test/pleroma/web/media_proxy/invalidation/script_test.exs b/test/pleroma/web/media_proxy/invalidation/script_test.exs
index bcb6ab73c..e9629b72b 100644
--- a/test/pleroma/web/media_proxy/invalidation/script_test.exs
+++ b/test/pleroma/web/media_proxy/invalidation/script_test.exs
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do
import ExUnit.CaptureLog
- test "it logger error when script not found" do
+ test "it logs error when script is not found" do
assert capture_log(fn ->
assert Invalidation.Script.purge(
["http://example.com/media/example.jpg"],
@@ -23,4 +23,30 @@ test "it logger error when script not found" do
) == {:error, "\"not found script path\""}
end)
end
+
+ describe "url formatting" do
+ setup do
+ urls = [
+ "https://bikeshed.party/media/foo.png",
+ "http://safe.millennial.space/proxy/wheeeee.gif",
+ "https://lain.com/proxy/mediafile.mp4?foo&bar=true",
+ "http://localhost:4000/media/upload.jpeg"
+ ]
+
+ [urls: urls]
+ end
+
+ test "with invalid formatter", %{urls: urls} do
+ assert urls == Invalidation.Script.maybe_format_urls(urls, nil)
+ end
+
+ test "with :htcacheclean formatter", %{urls: urls} do
+ assert [
+ "https://bikeshed.party:443/media/foo.png?",
+ "http://safe.millennial.space:80/proxy/wheeeee.gif?",
+ "https://lain.com:443/proxy/mediafile.mp4?foo&bar=true",
+ "http://localhost:4000/media/upload.jpeg?"
+ ] == Invalidation.Script.maybe_format_urls(urls, :htcacheclean)
+ end
+ end
end