diff --git a/.github/workflows/ci-backend.yml b/.github/workflows/ci-backend.yml index d7efc62a4..5ab863063 100644 --- a/.github/workflows/ci-backend.yml +++ b/.github/workflows/ci-backend.yml @@ -106,6 +106,7 @@ jobs: enable-cache: true python-version: ${{ steps.setup-python.outputs.python-version }} - name: Install system dependencies + timeout-minutes: 10 run: | sudo apt-get update -qq sudo apt-get install -qq --no-install-recommends \ diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 865609c40..98dbaa024 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -23,7 +23,7 @@ jobs: uses: lewagon/wait-on-check-action@9312864dfbc9fd208e9c0417843430751c042800 # v1.7.0 with: ref: ${{ github.sha }} - check-name: 'Build Docker Image' + check-name: 'Merge and Push Manifest' repo-token: ${{ secrets.GITHUB_TOKEN }} wait-interval: 60 build-release: @@ -177,7 +177,7 @@ jobs: version: ${{ steps.get-version.outputs.version }} prerelease: ${{ steps.get-version.outputs.prerelease }} publish: true - commitish: main + commitish: ${{ steps.get-version.outputs.prerelease == 'true' && 'dev' || 'main' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload release archive diff --git a/Dockerfile b/Dockerfile index ed2eee3fe..0ab31e611 100644 --- a/Dockerfile +++ b/Dockerfile @@ -236,6 +236,8 @@ RUN set -eux \ && mkdir -m700 --verbose /usr/src/paperless/.gnupg \ && echo "Adjusting all permissions" \ && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \ + && echo "Making fontconfig cache writable for arbitrary container UIDs" \ + && chmod 1777 /var/cache/fontconfig \ && echo "Collecting static files" \ && PAPERLESS_SECRET_KEY=build-time-dummy s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \ && PAPERLESS_SECRET_KEY=build-time-dummy s6-setuidgid paperless python3 manage.py compilemessages \ diff --git a/docs/configuration.md b/docs/configuration.md index 6758146f5..390a795b5 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -518,8 +518,25 @@ do CORS calls. Set this to your public domain name. fail2ban with log entries for failed authorization attempts. Value should be IP address(es). + This setting also controls allauth's + [`ALLAUTH_TRUSTED_PROXY_COUNT`](https://docs.allauth.org/en/latest/account/configuration.html), + which is set to the number of proxies listed here. Without this, + allauth cannot determine the client IP address for rate limiting when + running behind a reverse proxy, resulting in a `403 Forbidden` on login. + Defaults to empty string. +#### [`PAPERLESS_ALLAUTH_TRUSTED_CLIENT_IP_HEADER=`](#PAPERLESS_ALLAUTH_TRUSTED_CLIENT_IP_HEADER) {#PAPERLESS_ALLAUTH_TRUSTED_CLIENT_IP_HEADER} + +: Sets allauth's +[`ALLAUTH_TRUSTED_CLIENT_IP_HEADER`](https://docs.allauth.org/en/latest/account/configuration.html). +Use this when your reverse proxy sets a dedicated header for the real +client IP instead of `X-Forwarded-For`, for example `X-Real-IP` (nginx) +or `CF-Connecting-IP` (Cloudflare). When set, this takes precedence over +[`PAPERLESS_TRUSTED_PROXIES`](#PAPERLESS_TRUSTED_PROXIES). + + Defaults to none. + #### [`PAPERLESS_FORCE_SCRIPT_NAME=`](#PAPERLESS_FORCE_SCRIPT_NAME) {#PAPERLESS_FORCE_SCRIPT_NAME} : To host paperless under a subpath url like example.com/paperless you @@ -2014,8 +2031,8 @@ suggestions. This setting is required to be set to true in order to use the AI f #### [`PAPERLESS_AI_LLM_EMBEDDING_BACKEND=`](#PAPERLESS_AI_LLM_EMBEDDING_BACKEND) {#PAPERLESS_AI_LLM_EMBEDDING_BACKEND} -: The embedding backend to use for RAG. This can be either "openai-like" or "huggingface". The -"openai-like" backend uses an OpenAI-compatible embeddings API. +: The embedding backend to use for RAG. This can be "openai-like", "huggingface", or +"ollama". The "openai-like" backend uses an OpenAI-compatible embeddings API. Defaults to None. @@ -2023,11 +2040,34 @@ suggestions. This setting is required to be set to true in order to use the AI f : The model to use for the embedding backend for RAG. This can be set to any of the embedding models supported by the current embedding backend. If not supplied, defaults to -"text-embedding-3-small" for the OpenAI-compatible backend and -"sentence-transformers/all-MiniLM-L6-v2" for Huggingface. +"text-embedding-3-small" for the OpenAI-compatible backend, +"sentence-transformers/all-MiniLM-L6-v2" for Huggingface, and "embeddinggemma" for Ollama. Defaults to None. +#### [`PAPERLESS_AI_LLM_EMBEDDING_ENDPOINT=`](#PAPERLESS_AI_LLM_EMBEDDING_ENDPOINT) {#PAPERLESS_AI_LLM_EMBEDDING_ENDPOINT} + +: The endpoint / url to use for the embedding backend. If not supplied, embeddings use +`PAPERLESS_AI_LLM_ENDPOINT`. + + Defaults to None. + +#### [`PAPERLESS_AI_LLM_EMBEDDING_CHUNK_SIZE=`](#PAPERLESS_AI_LLM_EMBEDDING_CHUNK_SIZE) {#PAPERLESS_AI_LLM_EMBEDDING_CHUNK_SIZE} + +: The chunk size to use when splitting document text for RAG embeddings. Lower this value if your +embedding backend or model rejects larger inputs, or silently truncates inputs in a way that harms +retrieval quality. + + Defaults to 1024. + +#### [`PAPERLESS_AI_LLM_CONTEXT_SIZE=`](#PAPERLESS_AI_LLM_CONTEXT_SIZE) {#PAPERLESS_AI_LLM_CONTEXT_SIZE} + +: The context size to use for AI prompts and RAG retrieval. For Ollama backends, this is also sent +as `num_ctx` so models with very large native context windows are not loaded at their maximum +context by default. + + Defaults to 8192. + #### [`PAPERLESS_AI_LLM_BACKEND=`](#PAPERLESS_AI_LLM_BACKEND) {#PAPERLESS_AI_LLM_BACKEND} : The AI backend to use. This can be either "openai-like" or "ollama". If set to "ollama", the AI diff --git a/docs/migration-v3.md b/docs/migration-v3.md index 1cedfaa28..4fff1f858 100644 --- a/docs/migration-v3.md +++ b/docs/migration-v3.md @@ -1,5 +1,9 @@ # v3 Migration Guide +## Pre-Requisites + +Upgrading to Paperless-ngx v3 can only be performed from version 2.20.15. If you are running an older version, please upgrade to v2.20.15 before proceeding with the v3 upgrade. + ## Secret Key is Now Required The `PAPERLESS_SECRET_KEY` environment variable is now required. This is a critical security setting used for cryptographic signing and should be set to a long, random value. @@ -37,6 +41,10 @@ separating the directory ignore from the file ignore. | `CONSUMER_IGNORE_PATTERNS` | [`CONSUMER_IGNORE_PATTERNS`](configuration.md#PAPERLESS_CONSUMER_IGNORE_PATTERNS) | **Now regex, not fnmatch**; user patterns are added to (not replacing) default ones | | _New_ | [`CONSUMER_IGNORE_DIRS`](configuration.md#PAPERLESS_CONSUMER_IGNORE_DIRS) | Additional directories to ignore; user entries are added to (not replacing) defaults | +## Duplicate Handling Changes + +Paperless-ngx v3 no longer rejects duplicate documents by default. Instead, it now allows duplicates but adds a way to identify them via the UI. To (re-)enable duplicate rejection, set `PAPERLESS_CONSUMER_DELETE_DUPLICATES=true` in your environment. + ## Encryption Support Document and thumbnail encryption is no longer supported. This was previously deprecated in [paperless-ng 0.9.3](https://github.com/paperless-ngx/paperless-ngx/blob/dev/docs/changelog.md#paperless-ng-093) @@ -310,3 +318,11 @@ echo "Document ${DOCUMENT_ID} from ${DOCUMENT_CORRESPONDENT} tagged: ${DOCUMENT_ Update any pre- or post-consumption scripts that read `$1`, `$2`, etc. to use the corresponding environment variables instead. Environment variables have been the preferred option since v1.8.0. + +## Reverse Proxy and Login Rate Limiting + +Allauth changed how it determines the client IP address for login rate limiting. Users running +behind a reverse proxy may need to set +[`PAPERLESS_TRUSTED_PROXIES`](configuration.md#PAPERLESS_TRUSTED_PROXIES), +[`PAPERLESS_ALLAUTH_TRUSTED_CLIENT_IP_HEADER`](configuration.md#PAPERLESS_ALLAUTH_TRUSTED_CLIENT_IP_HEADER), +or both, to avoid `403 Forbidden` errors on login. diff --git a/pyproject.toml b/pyproject.toml index 9343e7529..1b6a11419 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "paperless-ngx" -version = "2.20.15" +version = "3.0.0" description = "A community-supported supercharged document management system: scan, index and archive all your physical documents" readme = "README.md" requires-python = ">=3.11" @@ -25,7 +25,7 @@ dependencies = [ # WARNING: django does not use semver. # Only patch versions are guaranteed to not introduce breaking changes. "django~=5.2.13", - "django-allauth[mfa,socialaccount]~=65.15.0", + "django-allauth[mfa,socialaccount]~=65.16.0", "django-auditlog~=3.4.1", "django-cachalot~=2.9.0", "django-compression-middleware~=0.5.0", @@ -40,7 +40,7 @@ dependencies = [ "djangorestframework~=3.16", "djangorestframework-guardian~=0.4.0", "drf-spectacular~=0.28", - "drf-spectacular-sidecar~=2026.4.14", + "drf-spectacular-sidecar~=2026.5.1", "drf-writable-nested~=0.7.1", "faiss-cpu>=1.10", "filelock~=3.29.0", @@ -53,6 +53,7 @@ dependencies = [ "langdetect~=1.0.9", "llama-index-core>=0.14.21", "llama-index-embeddings-huggingface>=0.6.1", + "llama-index-embeddings-ollama>=0.9", "llama-index-embeddings-openai-like>=0.2.2", "llama-index-llms-ollama>=0.9.1", "llama-index-llms-openai-like>=0.7.1", diff --git a/src-ui/package.json b/src-ui/package.json index 246de3543..a1888c367 100644 --- a/src-ui/package.json +++ b/src-ui/package.json @@ -1,6 +1,6 @@ { "name": "paperless-ngx-ui", - "version": "2.20.15", + "version": "3.0.0", "scripts": { "preinstall": "npx only-allow pnpm", "ng": "ng", diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.html b/src-ui/src/app/components/admin/tasks/tasks.component.html index 1a750e1fc..116d35f89 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.html +++ b/src-ui/src/app/components/admin/tasks/tasks.component.html @@ -23,8 +23,8 @@
Loading...
} -