From 8f73514fbbaf347add8be66813d3b13da223811f Mon Sep 17 00:00:00 2001 From: stumpylog <797416+stumpylog@users.noreply.github.com> Date: Wed, 7 Oct 2026 13:46:40 -0700 Subject: [PATCH] Chore: Deprecate PAPERLESS_CONVERT_MEMORY_LIMIT and PAPERLESS_CONVERT_TMPDIR These two options set ImageMagick's memory limit and scratch directory, but their only reader was the PDF thumbnail conversion helper. PDF thumbnails no longer use ImageMagick, so the settings did nothing while still being documented and advertised in the example configuration. Remove the unused settings, add system warnings for anyone who still has either variable set, mark both options as deprecated and without effect in the configuration docs, and drop them from paperless.conf.example. The manual setup guide is also corrected so it no longer claims ImageMagick is needed for PDF conversion, and the ImageMagick policy step now only covers hardening. --- docs/configuration.md | 26 +++----- docs/setup.md | 12 ++-- paperless.conf.example | 2 - src/paperless/checks.py | 31 +++++++++ src/paperless/settings/__init__.py | 2 - src/paperless/tests/test_checks_v3.py | 94 ++++++++++++++++++++++++++- 6 files changed, 138 insertions(+), 29 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 3257a815c..b42397da1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1315,29 +1315,19 @@ valid crontab(5) expression describing when to run. #### [`PAPERLESS_CONVERT_MEMORY_LIMIT=`](#PAPERLESS_CONVERT_MEMORY_LIMIT) {#PAPERLESS_CONVERT_MEMORY_LIMIT} -: On smaller systems, or even in the case of Very Large Documents, the -consumer may explode, complaining about how it's "unable to extend -pixel cache". In such cases, try setting this to a reasonably low -value, like 32. The default is to use whatever is necessary to do -everything without writing to disk, and units are in megabytes. +!!! warning - For more information on how to use this value, you should search the - web for "MAGICK_MEMORY_LIMIT". - - Defaults to 0, which disables the limit. + This option is deprecated and has no effect. It only applied to PDF + thumbnail generation via ImageMagick, which no longer happens. It will be + removed in a future release and can be removed from your configuration now. #### [`PAPERLESS_CONVERT_TMPDIR=`](#PAPERLESS_CONVERT_TMPDIR) {#PAPERLESS_CONVERT_TMPDIR} -: Similar to the memory limit, if you've got a small system and your -OS mounts /tmp as tmpfs, you should set this to a path that's on a -physical disk, like /home/your_user/tmp or something. ImageMagick -will use this as scratch space when crunching through very large -documents. +!!! warning - For more information on how to use this value, you should search the - web for "MAGICK_TMPDIR". - - Default is none, which disables the temporary directory. + This option is deprecated and has no effect. It only applied to PDF + thumbnail generation via ImageMagick, which no longer happens. It will be + removed in a future release and can be removed from your configuration now. #### [`PAPERLESS_APPS=`](#PAPERLESS_APPS) {#PAPERLESS_APPS} diff --git a/docs/setup.md b/docs/setup.md index 206e3107a..ba6e90af3 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -177,7 +177,7 @@ to a positive number to enable polling and disable native filesystem notificatio - `pkg-config` for mysqlclient (python dependency) - `fonts-liberation` for generating thumbnails for plain text files - - `imagemagick` >= 6 for PDF conversion + - `imagemagick` >= 6 for image alpha handling - `gnupg` for decrypting GPG-encrypted email - `libpq-dev` for PostgreSQL - `libmagic-dev` for mime type detection @@ -416,11 +416,11 @@ to a positive number to enable polling and disable native filesystem notificatio You may need to change the path in the files. Example: `ExecStart=/opt/paperless/.local/bin/celery --app paperless worker --loglevel INFO` -12. Configure ImageMagick to allow processing of PDF documents and disable - formats that Paperless-ngx does not use. Most distributions disable PDF - processing by default, since PDF documents can contain malware. - Paperless-ngx no longer passes PDF documents to ImageMagick, so enabling - PDF processing is not required. +12. Harden ImageMagick by disabling formats that Paperless-ngx does not use. + Most distributions disable PDF processing by default, since PDF documents + can contain malware. Paperless-ngx no longer passes PDF documents to + ImageMagick, so enabling PDF processing is not required and should be left + disabled. Configure the active ImageMagick policy file (commonly `/etc/ImageMagick-6/policy.xml` or `/etc/ImageMagick-7/policy.xml`) and diff --git a/paperless.conf.example b/paperless.conf.example index e2cedf63c..740bc9429 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -50,8 +50,6 @@ PAPERLESS_SECRET_KEY=change-me #PAPERLESS_OCR_ROTATE_PAGES=true #PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=12.0 #PAPERLESS_OCR_USER_ARGS={} -#PAPERLESS_CONVERT_MEMORY_LIMIT=0 -#PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless # Software tweaks diff --git a/src/paperless/checks.py b/src/paperless/checks.py index 5d9da91c4..ba94eb266 100644 --- a/src/paperless/checks.py +++ b/src/paperless/checks.py @@ -337,6 +337,37 @@ def check_deprecated_v2_ocr_env_vars( return warnings +DEPRECATED_CONVERT_ENV_VARS: dict[str, str] = { + "PAPERLESS_CONVERT_MEMORY_LIMIT": "paperless.W004", + "PAPERLESS_CONVERT_TMPDIR": "paperless.W005", +} + + +@register() +def check_deprecated_convert_env_vars( + app_configs: object, + **kwargs: object, +) -> list[Warning]: + """Warn when the deprecated ImageMagick convert environment variables are set. + + PDF thumbnails no longer use ImageMagick, so these variables are ignored. + """ + warnings: list[Warning] = [] + + for var, check_id in DEPRECATED_CONVERT_ENV_VARS.items(): + if os.environ.get(var): + warnings.append( + Warning( + f"{var} is deprecated, has no effect and will be removed " + "in a future release.", + hint="It can be removed from your environment or configuration.", + id=check_id, + ), + ) + + return warnings + + def get_tesseract_langs(): proc = subprocess.run( [shutil.which("tesseract"), "--list-langs"], diff --git a/src/paperless/settings/__init__.py b/src/paperless/settings/__init__.py index 7ca3bb66e..7a5ce30b9 100644 --- a/src/paperless/settings/__init__.py +++ b/src/paperless/settings/__init__.py @@ -986,8 +986,6 @@ GNUPG_HOME = os.getenv("HOME", "/tmp") # Convert is part of the ImageMagick package CONVERT_BINARY = os.getenv("PAPERLESS_CONVERT_BINARY", "convert") -CONVERT_TMPDIR = os.getenv("PAPERLESS_CONVERT_TMPDIR") -CONVERT_MEMORY_LIMIT = os.getenv("PAPERLESS_CONVERT_MEMORY_LIMIT") GS_BINARY = os.getenv("PAPERLESS_GS_BINARY", "gs") diff --git a/src/paperless/tests/test_checks_v3.py b/src/paperless/tests/test_checks_v3.py index a87a19727..bafd0075a 100644 --- a/src/paperless/tests/test_checks_v3.py +++ b/src/paperless/tests/test_checks_v3.py @@ -1,4 +1,4 @@ -"""Tests for v3 system checks: deprecated v2 OCR env var warnings.""" +"""Tests for v3 system checks: deprecated environment variable warnings.""" from __future__ import annotations @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING import pytest +from paperless.checks import check_deprecated_convert_env_vars from paperless.checks import check_deprecated_v2_ocr_env_vars if TYPE_CHECKING: @@ -62,3 +63,94 @@ class TestDeprecatedV2OcrEnvVarWarnings: warning = result[0] assert warning.id == expected_id assert expected_fragment in warning.msg + + +class TestDeprecatedConvertEnvVarWarnings: + def test_no_deprecated_vars_returns_empty(self, mocker: MockerFixture) -> None: + """ + GIVEN: + - Neither deprecated convert variable is set + WHEN: + - The deprecated convert check runs + THEN: + - No warnings are returned + """ + mocker.patch.dict(os.environ, {}, clear=True) + assert check_deprecated_convert_env_vars(None) == [] + + def test_empty_value_returns_empty(self, mocker: MockerFixture) -> None: + """ + GIVEN: + - A deprecated convert variable is set to an empty string + WHEN: + - The deprecated convert check runs + THEN: + - No warnings are returned + """ + mocker.patch.dict( + os.environ, + {"PAPERLESS_CONVERT_TMPDIR": ""}, + clear=True, + ) + assert check_deprecated_convert_env_vars(None) == [] + + @pytest.mark.parametrize( + ("env_var", "env_value", "expected_id"), + [ + pytest.param( + "PAPERLESS_CONVERT_MEMORY_LIMIT", + "32", + "paperless.W004", + id="memory-limit-warns", + ), + pytest.param( + "PAPERLESS_CONVERT_TMPDIR", + "/var/tmp/paperless", + "paperless.W005", + id="tmpdir-warns", + ), + ], + ) + def test_deprecated_var_produces_one_warning( + self, + mocker: MockerFixture, + env_var: str, + env_value: str, + expected_id: str, + ) -> None: + """ + GIVEN: + - One deprecated convert variable is set + WHEN: + - The deprecated convert check runs + THEN: + - Exactly one warning naming that variable is returned + """ + mocker.patch.dict(os.environ, {env_var: env_value}, clear=True) + result = check_deprecated_convert_env_vars(None) + + assert len(result) == 1 + assert result[0].id == expected_id + assert env_var in result[0].msg + assert "no effect" in result[0].msg + + def test_both_vars_produce_two_warnings(self, mocker: MockerFixture) -> None: + """ + GIVEN: + - Both deprecated convert variables are set + WHEN: + - The deprecated convert check runs + THEN: + - One warning per variable is returned + """ + mocker.patch.dict( + os.environ, + { + "PAPERLESS_CONVERT_MEMORY_LIMIT": "32", + "PAPERLESS_CONVERT_TMPDIR": "/var/tmp/paperless", + }, + clear=True, + ) + result = check_deprecated_convert_env_vars(None) + + assert {w.id for w in result} == {"paperless.W004", "paperless.W005"}