Merge branch 'develop' into docs/apache-config
authorMark Felder <feld@feld.me>
Mon, 25 Jan 2021 23:00:26 +0000 (17:00 -0600)
committerMark Felder <feld@feld.me>
Mon, 25 Jan 2021 23:00:26 +0000 (17:00 -0600)
CHANGELOG.md
config/config.exs
config/description.exs
docs/configuration/cheatsheet.md
installation/apache-cache-purge.sh.example [new file with mode: 0755]
installation/pleroma-apache.conf
lib/pleroma/web/media_proxy/invalidation/script.ex
test/pleroma/web/media_proxy/invalidation/script_test.exs

index 0ea649111d4be76caf5970ebf8f8815c9f7c9ef5..6522fbdcd1563d70b6ce6bd2f844bcb0a72765cf 100644 (file)
@@ -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 now supported
 
 ### Added
 
index c4a69079925df1a4de625c8e9c43d9926b358e39..5eca250bb0401043286cefdcbef352fa6609586d 100644 (file)
@@ -438,7 +438,9 @@ config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
   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,
index 715a0d0c36e731c6732acdc72607c19fcb44a80d..d7dc264ee2a8179d0553c4591f23c35e28ac3675 100644 (file)
@@ -1627,13 +1627,20 @@ config :pleroma, :config_description, [
     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"]
       }
     ]
   },
index 5c0fd64876c8f8a388965d2a5b806f8769058e09..9d4b07bf4061b9deda13e50501693e0c5bce36d4 100644 (file)
@@ -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 (executable)
index 0000000..be1d368
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# A simple shell script to delete a media from Apache's mod_disk_cache.
+
+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() {
+    htcacheclean -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 "$@"
index 0d627f2d71e98a1a8550cf65481b1cce570728b7..139abe9e1fa05d72d3ce3a6476eb378a76b8e500 100644 (file)
@@ -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
 
+<IfModule !proxy_module>
+    LoadModule proxy_module libexec/apache24/mod_proxy.so
+</IfModule>
+<IfModule !proxy_http_module>
+    LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
+</IfModule>
+<IfModule !proxy_wstunnel_module>
+    LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so
+</IfModule>
+<IfModule !rewrite_module>
+    LoadModule rewrite_module libexec/apache24/mod_rewrite.so
+</IfModule>
+<IfModule !ssl_module>
+    LoadModule ssl_module libexec/apache24/mod_ssl.so
+</IfModule>
+<IfModule !cache_module>
+    LoadModule cache_module libexec/apache24/mod_cache.so
+</IfModule>
+<IfModule !cache_disk_module>
+    LoadModule cache_disk_module libexec/apache24/mod_cache_disk.so
+</IfModule>
+
 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
 
 <VirtualHost *:80>
-    Redirect permanent / https://${servername}
+    RewriteEngine on
+    RewriteCond %{SERVER_NAME} =${servername}
+    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
 </VirtualHost>
 
 <VirtualHost *:443>
     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
-    # <IfModule mod_cache_disk.c>
-    #     CacheRoot /var/cache/apache2/mod_cache_disk
-    #     CacheDirLevels 1
-    #     CacheDirLength 2
-    #     CacheEnable disk /proxy
-    #     CacheLock on
-    # </IfModule>
+    # 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
 </VirtualHost>
-
-# OCSP Stapling, only in httpd 2.3.3 and later
-SSLUseStapling          on
-SSLStaplingResponderTimeout 5
-SSLStaplingReturnResponderErrors off
-SSLStaplingCache        shmcb:/var/run/ocsp(128000)
index 0f66c2fe323a1b351983f2789a26f3476878fa41..87a21166cd9dee8679d4ffb6cdf2c0e24fc4eee6 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.Script 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
index bcb6ab73c71441c14de9ad68e19e6b888565392c..e9629b72bea77ac333e934792a4c96965c1262ad 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest 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