mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			feature-ma
			...
			feature-rt
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 292d7762c4 | 
							
								
								
									
										14
									
								
								.codecov.yml
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.codecov.yml
									
									
									
									
									
								
							| @@ -14,9 +14,6 @@ flag_management: | |||||||
| # codecov will only comment if coverage changes | # codecov will only comment if coverage changes | ||||||
| comment: | comment: | ||||||
|   require_changes: true |   require_changes: true | ||||||
|   # https://docs.codecov.com/docs/javascript-bundle-analysis |  | ||||||
|   require_bundle_changes: true |  | ||||||
|   bundle_change_threshold: "50Kb" |  | ||||||
| coverage: | coverage: | ||||||
|   status: |   status: | ||||||
|     project: |     project: | ||||||
| @@ -25,12 +22,7 @@ coverage: | |||||||
|         threshold: 1% |         threshold: 1% | ||||||
|     patch: |     patch: | ||||||
|       default: |       default: | ||||||
|         # For the changed lines only, target 100% covered, but |         # For the changed lines only, target 75% covered, but | ||||||
|         # allow as low as 75% |         # allow as low as 50% | ||||||
|         target: 100% |         target: 75% | ||||||
|         threshold: 25% |         threshold: 25% | ||||||
| # https://docs.codecov.com/docs/javascript-bundle-analysis |  | ||||||
| bundle_analysis: |  | ||||||
|   # Fail if the bundle size increases by more than 1MB |  | ||||||
|   warning_threshold: "1MB" |  | ||||||
|   status: true |  | ||||||
|   | |||||||
| @@ -1,3 +1,3 @@ | |||||||
| [codespell] | [codespell] | ||||||
| write-changes = True | write-changes = True | ||||||
| ignore-words-list = criterias,afterall,valeu,ureue,equest,ure,assertIn | ignore-words-list = criterias,afterall,valeu,ureue,equest,ure | ||||||
|   | |||||||
| @@ -1,180 +0,0 @@ | |||||||
| # syntax=docker/dockerfile:1 |  | ||||||
|  |  | ||||||
| FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim as main-app |  | ||||||
|  |  | ||||||
| ARG DEBIAN_FRONTEND=noninteractive |  | ||||||
|  |  | ||||||
| # Buildx provided, must be defined to use though |  | ||||||
| ARG TARGETARCH |  | ||||||
|  |  | ||||||
| # Can be workflow provided, defaults set for manual building |  | ||||||
| ARG JBIG2ENC_VERSION=0.29 |  | ||||||
| ARG QPDF_VERSION=11.9.0 |  | ||||||
| ARG GS_VERSION=10.03.1 |  | ||||||
|  |  | ||||||
| # Set Python environment variables |  | ||||||
| ENV PYTHONDONTWRITEBYTECODE=1 \ |  | ||||||
|     PYTHONUNBUFFERED=1 \ |  | ||||||
|     # Ignore warning from Whitenoise |  | ||||||
|     PYTHONWARNINGS="ignore:::django.http.response:517" \ |  | ||||||
|     PNGX_CONTAINERIZED=1 |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Begin installation and configuration |  | ||||||
| # Order the steps below from least often changed to most |  | ||||||
| # |  | ||||||
|  |  | ||||||
| # Packages need for running |  | ||||||
| ARG RUNTIME_PACKAGES="\ |  | ||||||
|   # General utils |  | ||||||
|   curl \ |  | ||||||
|   # Docker specific |  | ||||||
|   gosu \ |  | ||||||
|   # Timezones support |  | ||||||
|   tzdata \ |  | ||||||
|   # fonts for text file thumbnail generation |  | ||||||
|   fonts-liberation \ |  | ||||||
|   gettext \ |  | ||||||
|   ghostscript \ |  | ||||||
|   gnupg \ |  | ||||||
|   icc-profiles-free \ |  | ||||||
|   imagemagick \ |  | ||||||
|   # PostgreSQL |  | ||||||
|   postgresql-client \ |  | ||||||
|   # MySQL / MariaDB |  | ||||||
|   mariadb-client \ |  | ||||||
|   # OCRmyPDF dependencies |  | ||||||
|   tesseract-ocr \ |  | ||||||
|   tesseract-ocr-eng \ |  | ||||||
|   tesseract-ocr-deu \ |  | ||||||
|   tesseract-ocr-fra \ |  | ||||||
|   tesseract-ocr-ita \ |  | ||||||
|   tesseract-ocr-spa \ |  | ||||||
|   unpaper \ |  | ||||||
|   pngquant \ |  | ||||||
|   jbig2dec \ |  | ||||||
|   # lxml |  | ||||||
|   libxml2 \ |  | ||||||
|   libxslt1.1 \ |  | ||||||
|   # itself |  | ||||||
|   qpdf \ |  | ||||||
|   # Mime type detection |  | ||||||
|   file \ |  | ||||||
|   libmagic1 \ |  | ||||||
|   media-types \ |  | ||||||
|   zlib1g \ |  | ||||||
|   # Barcode splitter |  | ||||||
|   libzbar0 \ |  | ||||||
|   poppler-utils \ |  | ||||||
|   htop \ |  | ||||||
|   sudo" |  | ||||||
|  |  | ||||||
| # Install basic runtime packages. |  | ||||||
| # These change very infrequently |  | ||||||
| RUN set -eux \ |  | ||||||
|   echo "Installing system packages" \ |  | ||||||
|     && apt-get update \ |  | ||||||
|     && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} |  | ||||||
|  |  | ||||||
| ARG PYTHON_PACKAGES="\ |  | ||||||
|   python3 \ |  | ||||||
|   python3-pip \ |  | ||||||
|   python3-wheel \ |  | ||||||
|   pipenv \ |  | ||||||
|   ca-certificates" |  | ||||||
|  |  | ||||||
| RUN set -eux \ |  | ||||||
|   echo "Installing python packages" \ |  | ||||||
|     && apt-get update \ |  | ||||||
|     && apt-get install --yes --quiet ${PYTHON_PACKAGES} |  | ||||||
|  |  | ||||||
| RUN set -eux \ |  | ||||||
|   && echo "Installing pre-built updates" \ |  | ||||||
|     && echo "Installing qpdf ${QPDF_VERSION}" \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|         --output libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|         --output qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|       && dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|       && dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|     && echo "Installing Ghostscript ${GS_VERSION}" \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|           --output libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|           --output ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|           --output libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ |  | ||||||
|           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ |  | ||||||
|         && dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ |  | ||||||
|         && dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|         && dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|     && echo "Installing jbig2enc" \ |  | ||||||
|       && curl --fail --silent --show-error --location \ |  | ||||||
|         --output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|       && dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb |  | ||||||
|  |  | ||||||
| # setup docker-specific things |  | ||||||
| # These change sometimes, but rarely |  | ||||||
| WORKDIR /usr/src/paperless/src/docker/ |  | ||||||
|  |  | ||||||
| COPY [ \ |  | ||||||
|   "docker/rootfs/etc/ImageMagick-6/paperless-policy.xml", \ |  | ||||||
|   "./" \ |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| RUN set -eux \ |  | ||||||
|   && echo "Configuring ImageMagick" \ |  | ||||||
|     && mv paperless-policy.xml /etc/ImageMagick-6/policy.xml |  | ||||||
|  |  | ||||||
| # Packages needed only for building a few quick Python |  | ||||||
| # dependencies |  | ||||||
| ARG BUILD_PACKAGES="\ |  | ||||||
|   build-essential \ |  | ||||||
|   git \ |  | ||||||
|   # https://www.psycopg.org/docs/install.html#prerequisites |  | ||||||
|   libpq-dev \ |  | ||||||
|   # https://github.com/PyMySQL/mysqlclient#linux |  | ||||||
|   default-libmysqlclient-dev \ |  | ||||||
|   pkg-config \ |  | ||||||
|   pre-commit" |  | ||||||
|  |  | ||||||
| # hadolint ignore=DL3042 |  | ||||||
| RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \ |  | ||||||
|   set -eux \ |  | ||||||
|   && echo "Installing build system packages" \ |  | ||||||
|     && apt-get update \ |  | ||||||
|     && apt-get install --yes --quiet ${BUILD_PACKAGES} |  | ||||||
|  |  | ||||||
| RUN set -eux \ |  | ||||||
|   && npm update npm -g |  | ||||||
|  |  | ||||||
| # add users, setup scripts |  | ||||||
| # Mount the compiled frontend to expected location |  | ||||||
| RUN set -eux \ |  | ||||||
|   && echo "Setting up user/group" \ |  | ||||||
|     && groupmod --new-name paperless node \ |  | ||||||
|     && usermod --login paperless --home /usr/src/paperless node \ |  | ||||||
|     && usermod -s /bin/bash paperless \ |  | ||||||
|     && echo "paperless ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \ |  | ||||||
|   && echo "Creating volume directories" \ |  | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/paperless-ngx/data \ |  | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/paperless-ngx/media \ |  | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/paperless-ngx/consume \ |  | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/paperless-ngx/export \ |  | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/paperless-ngx/.venv \ |  | ||||||
|   && echo "Adjusting all permissions" \ |  | ||||||
|     && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless |  | ||||||
| #  && echo "Collecting static files" \ |  | ||||||
| #    && gosu paperless python3 manage.py collectstatic --clear --no-input --link \ |  | ||||||
| #    && gosu paperless python3 manage.py compilemessages |  | ||||||
|  |  | ||||||
| VOLUME ["/usr/src/paperless/paperless-ngx/data", \ |  | ||||||
|         "/usr/src/paperless/paperless-ngx/media", \ |  | ||||||
|         "/usr/src/paperless/paperless-ngx/consume", \ |  | ||||||
|         "/usr/src/paperless/paperless-ngx/export", \ |  | ||||||
|         "/usr/src/paperless/paperless-ngx/.venv"] |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| { |  | ||||||
|     "name": "Paperless Development", |  | ||||||
|     "dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml", |  | ||||||
|     "service": "paperless-development", |  | ||||||
|     "workspaceFolder": "/usr/src/paperless/paperless-ngx", |  | ||||||
|     "postCreateCommand": "pipenv install --dev && pipenv run pre-commit install", |  | ||||||
|     "customizations": { |  | ||||||
|         "vscode": { |  | ||||||
|           "extensions": [ |  | ||||||
|             "mhutchie.git-graph", |  | ||||||
|             "ms-python.python", |  | ||||||
|             "ms-vscode.js-debug-nightly", |  | ||||||
|             "eamodio.gitlens", |  | ||||||
|             "yzhang.markdown-all-in-one" |  | ||||||
|           ], |  | ||||||
|           "settings": { |  | ||||||
|             "python.defaultInterpreterPath": "/usr/src/paperless/paperless-ngx/.venv/bin/python", |  | ||||||
|             "python.pythonPath": "/usr/src/paperless/paperless-ngx/.venv/bin/python", |  | ||||||
|             "python.terminal.activateEnvInCurrentTerminal": true, |  | ||||||
|             "editor.formatOnPaste": false, |  | ||||||
|             "editor.formatOnSave": true, |  | ||||||
|             "editor.formatOnType": true, |  | ||||||
|             "files.trimTrailingWhitespace": true |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       }, |  | ||||||
|       "remoteUser": "paperless" |  | ||||||
|     } |  | ||||||
| @@ -1,83 +0,0 @@ | |||||||
| # Docker Compose file for developing Paperless NGX in VSCode DevContainers. |  | ||||||
| # This file contains everything Paperless NGX needs to run. |  | ||||||
| # Paperless supports amd64, arm, and arm64 hardware. |  | ||||||
| # All compose files of Paperless configure it in the following way: |  | ||||||
| # |  | ||||||
| # - Paperless is (re)started on system boot if it was running before shutdown. |  | ||||||
| # - Docker volumes for storing data are managed by Docker. |  | ||||||
| # - Folders for importing and exporting files are created in the same directory |  | ||||||
| #   as this file and mounted to the correct folders inside the container. |  | ||||||
| # - Paperless listens on port 8000. |  | ||||||
| # |  | ||||||
| # SQLite is used as the database. The SQLite file is stored in the data volume. |  | ||||||
| # |  | ||||||
| # In addition, this Docker Compose file adds the following optional |  | ||||||
| # configurations: |  | ||||||
| # |  | ||||||
| # - Apache Tika and Gotenberg servers are started with Paperless NGX and Paperless |  | ||||||
| #   is configured to use these services. These provide support for consuming |  | ||||||
| #   Office documents (Word, Excel, PowerPoint, and their LibreOffice counterparts). |  | ||||||
| # |  | ||||||
| # This file is intended only to be used through VSCOde devcontainers. See README.md |  | ||||||
| # in the folder .devcontainer. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| services: |  | ||||||
|   broker: |  | ||||||
|     image: docker.io/library/redis:7 |  | ||||||
|     restart: unless-stopped |  | ||||||
|     volumes: |  | ||||||
|       - ./redisdata:/data |  | ||||||
|  |  | ||||||
|   # No ports need to be exposed; the VSCode DevContainer plugin manages them. |  | ||||||
|   paperless-development: |  | ||||||
|     image: paperless-ngx |  | ||||||
|     build: |  | ||||||
|       context: ../    # Dockerfile cannot access files from parent directories if context is not set. |  | ||||||
|       dockerfile: ./.devcontainer/Dockerfile |  | ||||||
|     restart: unless-stopped |  | ||||||
|     depends_on: |  | ||||||
|       - broker |  | ||||||
|       - gotenberg |  | ||||||
|       - tika |  | ||||||
|     volumes: |  | ||||||
|       - ..:/usr/src/paperless/paperless-ngx:delegated |  | ||||||
|       - ../.devcontainer/vscode:/usr/src/paperless/paperless-ngx/.vscode:delegated # VSCode config files |  | ||||||
|       - pipenv:/usr/src/paperless/paperless-ngx/.venv |  | ||||||
|       - /usr/src/paperless/paperless-ngx/src/documents/static/frontend # Static frontend files exist only in container |  | ||||||
|       - /usr/src/paperless/paperless-ngx/src/.pytest_cache |  | ||||||
|       - /usr/src/paperless/paperless-ngx/.ruff_cache |  | ||||||
|       - /usr/src/paperless/paperless-ngx/htmlcov |  | ||||||
|       - /usr/src/paperless/paperless-ngx/.coverage |  | ||||||
|       - ./data:/usr/src/paperless/paperless-ngx/data |  | ||||||
|       - ./media:/usr/src/paperless/paperless-ngx/media |  | ||||||
|       - ./consume:/usr/src/paperless/paperless-ngx/consume |  | ||||||
|       - ~/.gitconfig:/usr/src/paperless/.gitconfig:ro |  | ||||||
|     environment: |  | ||||||
|       PAPERLESS_REDIS: redis://broker:6379 |  | ||||||
|       PAPERLESS_TIKA_ENABLED: 1 |  | ||||||
|       PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 |  | ||||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 |  | ||||||
|       PAPERLESS_STATICDIR: ./src/documents/static |  | ||||||
|       PAPERLESS_DEBUG: true |  | ||||||
|  |  | ||||||
|     # Overrides default command so things don't shut down after the process ends. |  | ||||||
|     command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done" |  | ||||||
|  |  | ||||||
|   gotenberg: |  | ||||||
|     image: docker.io/gotenberg/gotenberg:8.17 |  | ||||||
|     restart: unless-stopped |  | ||||||
|  |  | ||||||
|     # The Gotenberg Chromium route is used to convert .eml files. We do not |  | ||||||
|     # want to allow external content like tracking pixels or even JavaScript. |  | ||||||
|     command: |  | ||||||
|       - "gotenberg" |  | ||||||
|       - "--chromium-disable-javascript=true" |  | ||||||
|       - "--chromium-allow-list=file:///tmp/.*" |  | ||||||
|  |  | ||||||
|   tika: |  | ||||||
|     image: docker.io/apache/tika:latest |  | ||||||
|     restart: unless-stopped |  | ||||||
|  |  | ||||||
| volumes: |  | ||||||
|   pipenv: |  | ||||||
| @@ -1,58 +0,0 @@ | |||||||
| { |  | ||||||
|     "version": "0.2.0", |  | ||||||
|     "configurations": [ |  | ||||||
|         { |  | ||||||
|             "name": "Chrome: Debug Angular Frontend", |  | ||||||
| 						"description": "Debug the Angular Dev Frontend in Chrome", |  | ||||||
|             "type": "chrome", |  | ||||||
|             "request": "launch", |  | ||||||
|             "url": "http://localhost:4200", |  | ||||||
|             "webRoot": "${workspaceFolder}/src-ui", |  | ||||||
|             "preLaunchTask": "Start: Frontend Angular" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "name": "Debug: Backend Server (manage.py runserver)", |  | ||||||
| 						"description": "Debug the Django Backend Server", |  | ||||||
|             "type": "python", |  | ||||||
|             "request": "launch", |  | ||||||
|             "program": "${workspaceFolder}/src/manage.py", |  | ||||||
|             "args": [ |  | ||||||
|                 "runserver" |  | ||||||
|             ], |  | ||||||
|             "django": true, |  | ||||||
|             "console": "integratedTerminal", |  | ||||||
|             "env": { |  | ||||||
|                 "PYTHONPATH": "${workspaceFolder}/src" |  | ||||||
|             }, |  | ||||||
|             "python": "${workspaceFolder}/.venv/bin/python" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "name": "Debug: Consumer Service (manage.py document_consumer)", |  | ||||||
| 						"description": "Debug the Consumer Service which processes files from a directory", |  | ||||||
|             "type": "python", |  | ||||||
|             "request": "launch", |  | ||||||
|             "program": "${workspaceFolder}/src/manage.py", |  | ||||||
|             "args": [ |  | ||||||
|                 "document_consumer" |  | ||||||
|             ], |  | ||||||
|             "django": true, |  | ||||||
|             "console": "integratedTerminal", |  | ||||||
|             "env": { |  | ||||||
|                 "PYTHONPATH": "${workspaceFolder}/src" |  | ||||||
|             }, |  | ||||||
|             "python": "${workspaceFolder}/.venv/bin/python" |  | ||||||
|         } |  | ||||||
|     ], |  | ||||||
|     "compounds": [ |  | ||||||
|         { |  | ||||||
|             "name": "Debug: FullStack", |  | ||||||
| 						"description": "Debug run the Angular dev frontend, Django backend, and consumer service", |  | ||||||
|             "configurations": [ |  | ||||||
|                 "Chrome: Debug Angular Frontend", |  | ||||||
|                 "Debug: Backend Server (manage.py runserver)", |  | ||||||
|                 "Debug: Consumer Service (manage.py document_consumer)" |  | ||||||
|             ], |  | ||||||
|             "preLaunchTask": "Start: Celery Worker" |  | ||||||
|         } |  | ||||||
|     ] |  | ||||||
| } |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| { |  | ||||||
|     "python.testing.pytestArgs": [ |  | ||||||
|         "src" |  | ||||||
|     ], |  | ||||||
|     "python.testing.unittestEnabled": false, |  | ||||||
|     "python.testing.pytestEnabled": true, |  | ||||||
|     "files.watcherExclude": { |  | ||||||
|         "**/.venv/**": true, |  | ||||||
|         "**/pytest_cache/**": true |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,223 +0,0 @@ | |||||||
| { |  | ||||||
| 	"version": "2.0.0", |  | ||||||
| 	"tasks": [ |  | ||||||
| 		{ |  | ||||||
| 			"label": "Start: Celery Worker", |  | ||||||
| 			"description": "Start the Celery Worker which processes background and consume tasks", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run celery --app paperless worker -l DEBUG", |  | ||||||
| 			"isBackground": true, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src" |  | ||||||
| 			}, |  | ||||||
| 			"problemMatcher": [ |  | ||||||
| 				{ |  | ||||||
| 					"owner": "custom", |  | ||||||
| 					"pattern": [ |  | ||||||
| 						{ |  | ||||||
| 							"regexp": ".", |  | ||||||
| 							"file": 1, |  | ||||||
| 							"location": 2, |  | ||||||
| 							"message": 3 |  | ||||||
| 						} |  | ||||||
| 					], |  | ||||||
| 					"background": { |  | ||||||
| 						"activeOnStart": true, |  | ||||||
| 						"beginsPattern": "celery.*", |  | ||||||
| 						"endsPattern": "ready" |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			] |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Start: Frontend Angular", |  | ||||||
| 			"description": "Start the Frontend Angular Dev Server", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "npm start", |  | ||||||
| 			"isBackground": true, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src-ui" |  | ||||||
| 			}, |  | ||||||
| 			"problemMatcher": [ |  | ||||||
| 				{ |  | ||||||
| 					"owner": "custom", |  | ||||||
| 					"pattern": [ |  | ||||||
| 						{ |  | ||||||
| 							"regexp": ".", |  | ||||||
| 							"file": 1, |  | ||||||
| 							"location": 2, |  | ||||||
| 							"message": 3 |  | ||||||
| 						} |  | ||||||
| 					], |  | ||||||
| 					"background": { |  | ||||||
| 						"activeOnStart": true, |  | ||||||
| 						"beginsPattern": ".*", |  | ||||||
| 						"endsPattern": "Compiled successfully" |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			] |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Start: Consumer Service (manage.py document_consumer)", |  | ||||||
| 			"description": "Start the Consumer Service which processes files from a directory", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run python manage.py document_consumer", |  | ||||||
| 			"group": "build", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": false, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Start: Backend Server (manage.py runserver)", |  | ||||||
| 			"description": "Start the Backend Server which serves the Django API and the compiled Angular frontend", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run python manage.py runserver", |  | ||||||
| 			"group": "build", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": false, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Maintenance: manage.py migrate", |  | ||||||
| 			"description": "Apply database migrations", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run python manage.py migrate", |  | ||||||
| 			"group": "none", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": true, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Maintenance: Build Documentation", |  | ||||||
| 			"description": "Build the documentation with MkDocs", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run mkdocs build --config-file mkdocs.yml && pipenv run mkdocs serve", |  | ||||||
| 			"group": "none", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": true, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Maintenance: manage.py createsuperuser", |  | ||||||
| 			"description": "Create a superuser", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "pipenv run python manage.py createsuperuser", |  | ||||||
| 			"group": "none", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": true, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Maintenance: recreate .venv", |  | ||||||
| 			"description": "Recreate the python virtual environment and install python dependencies", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "rm -R -v .venv/* || pipenv install --dev", |  | ||||||
| 			"group": "none", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": true, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Maintenance: Install Frontend Dependencies", |  | ||||||
| 			"description": "Install frontend (npm) dependencies", |  | ||||||
| 			"type": "npm", |  | ||||||
| 			"script": "install", |  | ||||||
| 			"path": "src-ui", |  | ||||||
| 			"group": "clean", |  | ||||||
| 			"problemMatcher": [], |  | ||||||
| 			"detail": "install dependencies from package" |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"description": "Clean install frontend dependencies and build the frontend for production", |  | ||||||
| 			"label": "Maintenance: Compile frontend for production", |  | ||||||
| 			"type": "shell", |  | ||||||
| 			"command": "npm ci && ./node_modules/.bin/ng build --configuration production", |  | ||||||
| 			"group": "none", |  | ||||||
| 			"presentation": { |  | ||||||
| 				"echo": true, |  | ||||||
| 				"reveal": "always", |  | ||||||
| 				"focus": true, |  | ||||||
| 				"panel": "shared", |  | ||||||
| 				"showReuseMessage": false, |  | ||||||
| 				"clear": true, |  | ||||||
| 				"revealProblems": "onProblem" |  | ||||||
| 			}, |  | ||||||
| 			"options": { |  | ||||||
| 				"cwd": "${workspaceFolder}/src-ui" |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Project Setup: Run all Init Tasks", |  | ||||||
| 			"description": "Runs all init tasks to setup the project including migrate the database, create a superuser and compile the frontend for production", |  | ||||||
| 			"dependsOrder": "sequence", |  | ||||||
| 			"dependsOn": [ |  | ||||||
| 				"Maintenance: manage.py migrate", |  | ||||||
| 				"Maintenance: manage.py createsuperuser", |  | ||||||
| 				"Maintenance: Compile frontend for production" |  | ||||||
| 			] |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"label": "Project Start: Run all Services", |  | ||||||
| 			"description": "Runs all services required to start the project including the Celery Worker, the Consumer Service and the Backend Server", |  | ||||||
| 			"dependsOn": [ |  | ||||||
| 				"Start: Celery Worker", |  | ||||||
| 				"Start: Consumer Service (manage.py document_consumer)", |  | ||||||
| 				"Start: Backend Server (manage.py runserver)" |  | ||||||
| 			] |  | ||||||
| 		} |  | ||||||
| 	] |  | ||||||
| } |  | ||||||
| @@ -26,5 +26,3 @@ | |||||||
| ./dist | ./dist | ||||||
| ./scripts | ./scripts | ||||||
| ./resources | ./resources | ||||||
| # Other stuff |  | ||||||
| **/*.drawio.png |  | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								.github/ISSUE_TEMPLATE/bug-report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/ISSUE_TEMPLATE/bug-report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -9,7 +9,7 @@ body: | |||||||
|         ### ⚠️ Please remember: issues are for *bugs* |         ### ⚠️ Please remember: issues are for *bugs* | ||||||
|         That is, something you believe affects every single user of Paperless-ngx, not just you. If you're not sure, start with one of the other options below. |         That is, something you believe affects every single user of Paperless-ngx, not just you. If you're not sure, start with one of the other options below. | ||||||
|  |  | ||||||
|         Also, note that **Paperless-ngx does not perform OCR or archive file creation itself**, those are handled by other tools. Problems with OCR or archive versions of specific files should likely be raised 'upstream', see https://github.com/ocrmypdf/OCRmyPDF/issues or https://github.com/tesseract-ocr/tesseract/issues |         Also, note that **Paperless-ngx does not perform OCR itself**, that is handled by other tools. Problems with OCR of specific files should likely be raised 'upstream', see https://github.com/ocrmypdf/OCRmyPDF/issues or https://github.com/tesseract-ocr/tesseract/issues | ||||||
|   - type: markdown |   - type: markdown | ||||||
|     attributes: |     attributes: | ||||||
|       value: | |       value: | | ||||||
| @@ -86,23 +86,22 @@ body: | |||||||
|       description: Note there are significant differences from the official image and linuxserver.io, please check if your issue is specific to the third-party image. |       description: Note there are significant differences from the official image and linuxserver.io, please check if your issue is specific to the third-party image. | ||||||
|     validations: |     validations: | ||||||
|       required: true |       required: true | ||||||
|   - type: textarea |  | ||||||
|     id: system-status |  | ||||||
|     attributes: |  | ||||||
|       label: System status |  | ||||||
|       description: If available, copy & paste the system status output from Settings > System Status > Copy |  | ||||||
|       render: json |  | ||||||
|   - type: input |   - type: input | ||||||
|     id: browser |     id: browser | ||||||
|     attributes: |     attributes: | ||||||
|       label: Browser |       label: Browser | ||||||
|       description: Which browser you are using, if relevant. |       description: Which browser you are using, if relevant. | ||||||
|       placeholder: e.g. Chrome, Safari |       placeholder: e.g. Chrome, Safari | ||||||
|   - type: textarea |   - type: input | ||||||
|     id: config-changes |     id: config-changes | ||||||
|     attributes: |     attributes: | ||||||
|       label: Configuration changes |       label: Configuration changes | ||||||
|       description: Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`. |       description: Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`. | ||||||
|  |   - type: input | ||||||
|  |     id: other | ||||||
|  |     attributes: | ||||||
|  |       label: Other | ||||||
|  |       description: Any other relevant details. | ||||||
|   - type: checkboxes |   - type: checkboxes | ||||||
|     id: required-checks |     id: required-checks | ||||||
|     attributes: |     attributes: | ||||||
| @@ -110,8 +109,6 @@ body: | |||||||
|       options: |       options: | ||||||
|         - label: I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation. |         - label: I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation. | ||||||
|           required: true |           required: true | ||||||
|         - label: This issue is not about the OCR or archive creation of a specific file(s). Otherwise, please see above regarding OCR tools. |  | ||||||
|           required: true |  | ||||||
|         - label: I have already searched for relevant existing issues and discussions before opening this report. |         - label: I have already searched for relevant existing issues and discussions before opening this report. | ||||||
|           required: true |           required: true | ||||||
|         - label: I have updated the title field above with a concise description. |         - label: I have updated the title field above with a concise description. | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,10 +2,10 @@ blank_issues_enabled: false | |||||||
| contact_links: | contact_links: | ||||||
|   - name: 🤔 Questions and Help |   - name: 🤔 Questions and Help | ||||||
|     url: https://github.com/paperless-ngx/paperless-ngx/discussions |     url: https://github.com/paperless-ngx/paperless-ngx/discussions | ||||||
|     about: General questions or support for using Paperless-ngx. |     about: This issue tracker is not for support questions. Please refer to our Discussions. | ||||||
|   - name: 💬 Chat |   - name: 💬 Chat | ||||||
|     url: https://matrix.to/#/#paperlessngx:matrix.org |     url: https://matrix.to/#/#paperlessngx:matrix.org | ||||||
|     about: Want to discuss Paperless-ngx with others? Check out our chat. |     about: Want to discuss Paperless-ngx with others? Check out our chat. | ||||||
|   - name: 🚀 Feature Request |   - name: 🚀 Feature Request | ||||||
|     url: https://github.com/paperless-ngx/paperless-ngx/discussions/new?category=feature-requests |     url: https://github.com/paperless-ngx/paperless-ngx/discussions/new?category=feature-requests | ||||||
|     about: Remember to search for existing feature requests and "up-vote" those that you like. |     about: Remember to search for existing feature requests and "up-vote" any you like | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							| @@ -53,6 +53,7 @@ updates: | |||||||
|       development: |       development: | ||||||
|         patterns: |         patterns: | ||||||
|           - "*pytest*" |           - "*pytest*" | ||||||
|  |           - "black" | ||||||
|           - "ruff" |           - "ruff" | ||||||
|           - "mkdocs-material" |           - "mkdocs-material" | ||||||
|       django: |       django: | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,9 +16,9 @@ on: | |||||||
| env: | env: | ||||||
|   # This is the version of pipenv all the steps will use |   # This is the version of pipenv all the steps will use | ||||||
|   # If changing this, change Dockerfile |   # If changing this, change Dockerfile | ||||||
|   DEFAULT_PIP_ENV_VERSION: "2024.4.1" |   DEFAULT_PIP_ENV_VERSION: "2023.12.1" | ||||||
|   # This is the default version of Python to use in most steps which aren't specific |   # This is the default version of Python to use in most steps which aren't specific | ||||||
|   DEFAULT_PYTHON_VERSION: "3.11" |   DEFAULT_PYTHON_VERSION: "3.10" | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   pre-commit: |   pre-commit: | ||||||
| @@ -30,7 +30,7 @@ jobs: | |||||||
|       github.repository |       github.repository | ||||||
|  |  | ||||||
|     name: Linting Checks |     name: Linting Checks | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout repository |         name: Checkout repository | ||||||
| @@ -46,7 +46,7 @@ jobs: | |||||||
|  |  | ||||||
|   documentation: |   documentation: | ||||||
|     name: "Build & Deploy Documentation" |     name: "Build & Deploy Documentation" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - pre-commit |       - pre-commit | ||||||
|     steps: |     steps: | ||||||
| @@ -95,12 +95,12 @@ jobs: | |||||||
|  |  | ||||||
|   tests-backend: |   tests-backend: | ||||||
|     name: "Backend Tests (Python ${{ matrix.python-version }})" |     name: "Backend Tests (Python ${{ matrix.python-version }})" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - pre-commit |       - pre-commit | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|         python-version: ['3.10', '3.11', '3.12'] |         python-version: ['3.9', '3.10', '3.11'] | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
| @@ -131,7 +131,7 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Configure ImageMagick |         name: Configure ImageMagick | ||||||
|         run: | |         run: | | ||||||
|           sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml |           sudo cp docker/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml | ||||||
|       - |       - | ||||||
|         name: Install Python dependencies |         name: Install Python dependencies | ||||||
|         run: | |         run: | | ||||||
| @@ -170,7 +170,7 @@ jobs: | |||||||
|  |  | ||||||
|   install-frontend-depedendencies: |   install-frontend-depedendencies: | ||||||
|     name: "Install Frontend Dependencies" |     name: "Install Frontend Dependencies" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - pre-commit |       - pre-commit | ||||||
|     steps: |     steps: | ||||||
| @@ -201,7 +201,7 @@ jobs: | |||||||
|  |  | ||||||
|   tests-frontend: |   tests-frontend: | ||||||
|     name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})" |     name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - install-frontend-depedendencies |       - install-frontend-depedendencies | ||||||
|     strategy: |     strategy: | ||||||
| @@ -260,8 +260,8 @@ jobs: | |||||||
|           retention-days: 7 |           retention-days: 7 | ||||||
|  |  | ||||||
|   tests-coverage-upload: |   tests-coverage-upload: | ||||||
|     name: "Upload to Codecov" |     name: "Upload Coverage" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - tests-backend |       - tests-backend | ||||||
|       - tests-frontend |       - tests-frontend | ||||||
| @@ -283,7 +283,7 @@ jobs: | |||||||
|           merge-multiple: true |           merge-multiple: true | ||||||
|       - |       - | ||||||
|         name: Upload frontend coverage to Codecov |         name: Upload frontend coverage to Codecov | ||||||
|         uses: codecov/codecov-action@v5 |         uses: codecov/codecov-action@v4 | ||||||
|         with: |         with: | ||||||
|           # not required for public repos, but intermittently fails otherwise |           # not required for public repos, but intermittently fails otherwise | ||||||
|           token: ${{ secrets.CODECOV_TOKEN }} |           token: ${{ secrets.CODECOV_TOKEN }} | ||||||
| @@ -299,41 +299,17 @@ jobs: | |||||||
|           path: src/ |           path: src/ | ||||||
|       - |       - | ||||||
|         name: Upload coverage to Codecov |         name: Upload coverage to Codecov | ||||||
|         uses: codecov/codecov-action@v5 |         uses: codecov/codecov-action@v4 | ||||||
|         with: |         with: | ||||||
|           # not required for public repos, but intermittently fails otherwise |           # not required for public repos, but intermittently fails otherwise | ||||||
|           token: ${{ secrets.CODECOV_TOKEN }} |           token: ${{ secrets.CODECOV_TOKEN }} | ||||||
|           # future expansion |           # future expansion | ||||||
|           flags: backend |           flags: backend | ||||||
|           directory: src/ |           directory: src/ | ||||||
|       - |  | ||||||
|         name: Use Node.js 20 |  | ||||||
|         uses: actions/setup-node@v4 |  | ||||||
|         with: |  | ||||||
|           node-version: 20.x |  | ||||||
|           cache: 'npm' |  | ||||||
|           cache-dependency-path: 'src-ui/package-lock.json' |  | ||||||
|       - |  | ||||||
|         name: Cache frontend dependencies |  | ||||||
|         id: cache-frontend-deps |  | ||||||
|         uses: actions/cache@v4 |  | ||||||
|         with: |  | ||||||
|           path: | |  | ||||||
|             ~/.npm |  | ||||||
|             ~/.cache |  | ||||||
|           key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }} |  | ||||||
|       - |  | ||||||
|         name: Re-link Angular cli |  | ||||||
|         run: cd src-ui && npm link @angular/cli |  | ||||||
|       - |  | ||||||
|         name: Build frontend and upload analysis |  | ||||||
|         env: |  | ||||||
|           CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} |  | ||||||
|         run: cd src-ui && ng build --configuration=production |  | ||||||
|  |  | ||||||
|   build-docker-image: |   build-docker-image: | ||||||
|     name: Build Docker image for ${{ github.ref_name }} |     name: Build Docker image for ${{ github.ref_name }} | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v')) |     if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v')) | ||||||
|     concurrency: |     concurrency: | ||||||
|       group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }} |       group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }} | ||||||
| @@ -406,7 +382,7 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Login to Docker Hub |         name: Login to Docker Hub | ||||||
|         uses: docker/login-action@v3 |         uses: docker/login-action@v3 | ||||||
|         # Don't attempt to login if not pushing to Docker Hub |         # Don't attempt to login is not pushing to Docker Hub | ||||||
|         if: steps.push-other-places.outputs.enable == 'true' |         if: steps.push-other-places.outputs.enable == 'true' | ||||||
|         with: |         with: | ||||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} |           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||||
| @@ -414,7 +390,7 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Login to Quay.io |         name: Login to Quay.io | ||||||
|         uses: docker/login-action@v3 |         uses: docker/login-action@v3 | ||||||
|         # Don't attempt to login if not pushing to Quay.io |         # Don't attempt to login is not pushing to Quay.io | ||||||
|         if: steps.push-other-places.outputs.enable == 'true' |         if: steps.push-other-places.outputs.enable == 'true' | ||||||
|         with: |         with: | ||||||
|           registry: quay.io |           registry: quay.io | ||||||
| @@ -422,7 +398,7 @@ jobs: | |||||||
|           password: ${{ secrets.QUAY_ROBOT_TOKEN }} |           password: ${{ secrets.QUAY_ROBOT_TOKEN }} | ||||||
|       - |       - | ||||||
|         name: Build and push |         name: Build and push | ||||||
|         uses: docker/build-push-action@v6 |         uses: docker/build-push-action@v5 | ||||||
|         with: |         with: | ||||||
|           context: . |           context: . | ||||||
|           file: ./Dockerfile |           file: ./Dockerfile | ||||||
| @@ -430,8 +406,6 @@ jobs: | |||||||
|           push: ${{ github.event_name != 'pull_request' }} |           push: ${{ github.event_name != 'pull_request' }} | ||||||
|           tags: ${{ steps.docker-meta.outputs.tags }} |           tags: ${{ steps.docker-meta.outputs.tags }} | ||||||
|           labels: ${{ steps.docker-meta.outputs.labels }} |           labels: ${{ steps.docker-meta.outputs.labels }} | ||||||
|           build-args: | |  | ||||||
|             PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }} |  | ||||||
|           # Get cache layers from this branch, then dev |           # Get cache layers from this branch, then dev | ||||||
|           # This allows new branches to get at least some cache benefits, generally from dev |           # This allows new branches to get at least some cache benefits, generally from dev | ||||||
|           cache-from: | |           cache-from: | | ||||||
| @@ -461,7 +435,7 @@ jobs: | |||||||
|     needs: |     needs: | ||||||
|       - build-docker-image |       - build-docker-image | ||||||
|       - documentation |       - documentation | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
| @@ -482,6 +456,12 @@ jobs: | |||||||
|         name: Install Python dependencies |         name: Install Python dependencies | ||||||
|         run: | |         run: | | ||||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev |           pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev | ||||||
|  |       - | ||||||
|  |         name: Patch whitenoise | ||||||
|  |         run: | | ||||||
|  |           curl --fail --silent --show-error --location --output 484.patch https://github.com/evansd/whitenoise/pull/484.patch | ||||||
|  |           patch -d $(pipenv --venv)/lib/python3.10/site-packages --verbose -p2 < 484.patch | ||||||
|  |           rm 484.patch | ||||||
|       - |       - | ||||||
|         name: Install system dependencies |         name: Install system dependencies | ||||||
|         run: | |         run: | | ||||||
| @@ -569,7 +549,7 @@ jobs: | |||||||
|  |  | ||||||
|   publish-release: |   publish-release: | ||||||
|     name: "Publish Release" |     name: "Publish Release" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     outputs: |     outputs: | ||||||
|       prerelease: ${{ steps.get_version.outputs.prerelease }} |       prerelease: ${{ steps.get_version.outputs.prerelease }} | ||||||
|       changelog: ${{ steps.create-release.outputs.body }} |       changelog: ${{ steps.create-release.outputs.body }} | ||||||
| @@ -619,7 +599,7 @@ jobs: | |||||||
|  |  | ||||||
|   append-changelog: |   append-changelog: | ||||||
|     name: "Append Changelog" |     name: "Append Changelog" | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - publish-release |       - publish-release | ||||||
|     if: needs.publish-release.outputs.prerelease == 'false' |     if: needs.publish-release.outputs.prerelease == 'false' | ||||||
| @@ -649,9 +629,7 @@ jobs: | |||||||
|           git checkout ${{ needs.publish-release.outputs.version }}-changelog |           git checkout ${{ needs.publish-release.outputs.version }}-changelog | ||||||
|           echo -e "# Changelog\n\n${{ needs.publish-release.outputs.changelog }}\n" > changelog-new.md |           echo -e "# Changelog\n\n${{ needs.publish-release.outputs.changelog }}\n" > changelog-new.md | ||||||
|           echo "Manually linking usernames" |           echo "Manually linking usernames" | ||||||
|           sed -i -r 's|@([a-zA-Z0-9_]+) \(\[#|[@\1](https://github.com/\1) ([#|g' changelog-new.md |           sed -i -r 's|@(.+?) \(\[#|[@\1](https://github.com/\1) ([#|ig' changelog-new.md | ||||||
|           echo "Removing unneeded comment tags" |  | ||||||
|           sed -i -r 's|@<!---->|@|g' changelog-new.md |  | ||||||
|           CURRENT_CHANGELOG=`tail --lines +2 changelog.md` |           CURRENT_CHANGELOG=`tail --lines +2 changelog.md` | ||||||
|           echo -e "$CURRENT_CHANGELOG" >> changelog-new.md |           echo -e "$CURRENT_CHANGELOG" >> changelog-new.md | ||||||
|           mv changelog-new.md changelog.md |           mv changelog-new.md changelog.md | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | |||||||
|   cleanup-images: |   cleanup-images: | ||||||
|     name: Cleanup Image Tags for ${{ matrix.primary-name }} |     name: Cleanup Image Tags for ${{ matrix.primary-name }} | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     if: github.repository_owner == 'paperless-ngx' | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
| @@ -33,7 +33,7 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Clean temporary images |         name: Clean temporary images | ||||||
|         if: "${{ env.TOKEN != '' }}" |         if: "${{ env.TOKEN != '' }}" | ||||||
|         uses: stumpylog/image-cleaner-action/ephemeral@v0.9.0 |         uses: stumpylog/image-cleaner-action/ephemeral@v0.5.0 | ||||||
|         with: |         with: | ||||||
|           token: "${{ env.TOKEN }}" |           token: "${{ env.TOKEN }}" | ||||||
|           owner: "${{ github.repository_owner }}" |           owner: "${{ github.repository_owner }}" | ||||||
| @@ -47,7 +47,7 @@ jobs: | |||||||
|   cleanup-untagged-images: |   cleanup-untagged-images: | ||||||
|     name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }} |     name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }} | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     if: github.repository_owner == 'paperless-ngx' | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     needs: |     needs: | ||||||
|       - cleanup-images |       - cleanup-images | ||||||
|     strategy: |     strategy: | ||||||
| @@ -61,7 +61,7 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Clean untagged images |         name: Clean untagged images | ||||||
|         if: "${{ env.TOKEN != '' }}" |         if: "${{ env.TOKEN != '' }}" | ||||||
|         uses: stumpylog/image-cleaner-action/untagged@v0.9.0 |         uses: stumpylog/image-cleaner-action/untagged@v0.5.0 | ||||||
|         with: |         with: | ||||||
|           token: "${{ env.TOKEN }}" |           token: "${{ env.TOKEN }}" | ||||||
|           owner: "${{ github.repository_owner }}" |           owner: "${{ github.repository_owner }}" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ on: | |||||||
| jobs: | jobs: | ||||||
|   analyze: |   analyze: | ||||||
|     name: Analyze |     name: Analyze | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     permissions: |     permissions: | ||||||
|       actions: read |       actions: read | ||||||
|       contents: read |       contents: read | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								.github/workflows/crowdin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/crowdin.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,14 +15,13 @@ on: | |||||||
| jobs: | jobs: | ||||||
|   synchronize-with-crowdin: |   synchronize-with-crowdin: | ||||||
|     name: Crowdin Sync |     name: Crowdin Sync | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|     - name: Checkout |     - name: Checkout | ||||||
|       uses: actions/checkout@v4 |       uses: actions/checkout@v4 | ||||||
|     - name: crowdin action |     - name: crowdin action | ||||||
|       uses: crowdin/github-action@v2 |       uses: crowdin/github-action@v1 | ||||||
|       with: |       with: | ||||||
|         upload_translations: false |         upload_translations: false | ||||||
|         download_translations: true |         download_translations: true | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/project-actions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/project-actions.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,7 +15,7 @@ permissions: | |||||||
| jobs: | jobs: | ||||||
|   pr_opened_or_reopened: |   pr_opened_or_reopened: | ||||||
|     name: pr_opened_or_reopened |     name: pr_opened_or_reopened | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-22.04 | ||||||
|     permissions: |     permissions: | ||||||
|       # write permission is required for autolabeler |       # write permission is required for autolabeler | ||||||
|       pull-requests: write |       pull-requests: write | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								.github/workflows/repo-maintenance.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/repo-maintenance.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,14 +16,13 @@ concurrency: | |||||||
| jobs: | jobs: | ||||||
|   stale: |   stale: | ||||||
|     name: 'Stale' |     name: 'Stale' | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/stale@v9 |       - uses: actions/stale@v9 | ||||||
|         with: |         with: | ||||||
|           days-before-stale: 7 |           days-before-stale: 7 | ||||||
|           days-before-close: 14 |           days-before-close: 14 | ||||||
|           any-of-labels: 'stale,cant-reproduce,not a bug' |           any-of-labels: 'cant-reproduce,not a bug' | ||||||
|           stale-issue-label: stale |           stale-issue-label: stale | ||||||
|           stale-pr-label: stale |           stale-pr-label: stale | ||||||
|           stale-issue-message: > |           stale-issue-message: > | ||||||
| @@ -32,8 +31,7 @@ jobs: | |||||||
|             for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details. |             for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details. | ||||||
|   lock-threads: |   lock-threads: | ||||||
|     name: 'Lock Old Threads' |     name: 'Lock Old Threads' | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: dessant/lock-threads@v5 |       - uses: dessant/lock-threads@v5 | ||||||
|         with: |         with: | ||||||
| @@ -58,8 +56,7 @@ jobs: | |||||||
|             See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details. |             See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details. | ||||||
|   close-answered-discussions: |   close-answered-discussions: | ||||||
|     name: 'Close Answered Discussions' |     name: 'Close Answered Discussions' | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/github-script@v7 |       - uses: actions/github-script@v7 | ||||||
|         with: |         with: | ||||||
| @@ -115,8 +112,7 @@ jobs: | |||||||
|             } |             } | ||||||
|   close-outdated-discussions: |   close-outdated-discussions: | ||||||
|     name: 'Close Outdated Discussions' |     name: 'Close Outdated Discussions' | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/github-script@v7 |       - uses: actions/github-script@v7 | ||||||
|         with: |         with: | ||||||
| @@ -207,8 +203,7 @@ jobs: | |||||||
|             } |             } | ||||||
|   close-unsupported-feature-requests: |   close-unsupported-feature-requests: | ||||||
|     name: 'Close Unsupported Feature Requests' |     name: 'Close Unsupported Feature Requests' | ||||||
|     if: github.repository_owner == 'paperless-ngx' |     runs-on: ubuntu-latest | ||||||
|     runs-on: ubuntu-24.04 |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/github-script@v7 |       - uses: actions/github-script@v7 | ||||||
|         with: |         with: | ||||||
| @@ -217,20 +212,15 @@ jobs: | |||||||
|               return new Promise(resolve => setTimeout(resolve, ms)); |               return new Promise(resolve => setTimeout(resolve, ms)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             const CUTOFF_MAX_COUNT = 80; |  | ||||||
|             const CUTOFF_1_DAYS = 180; |             const CUTOFF_1_DAYS = 180; | ||||||
|             const CUTOFF_1_COUNT = 5; |             const CUTOFF_1_COUNT = 5; | ||||||
|             const CUTOFF_2_DAYS = 365; |             const CUTOFF_2_DAYS = 365; | ||||||
|             const CUTOFF_2_COUNT = 20; |             const CUTOFF_2_COUNT = 10; | ||||||
|             const CUTOFF_3_DAYS = 730; |  | ||||||
|             const CUTOFF_3_COUNT = 40; |  | ||||||
|  |  | ||||||
|             const cutoff1Date = new Date(); |             const cutoff1Date = new Date(); | ||||||
|             cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS); |             cutoff1Date.setDate(cutoff1Date.getDate() - CUTOFF_1_DAYS); | ||||||
|             const cutoff2Date = new Date(); |             const cutoff2Date = new Date(); | ||||||
|             cutoff2Date.setDate(cutoff2Date.getDate() - CUTOFF_2_DAYS); |             cutoff2Date.setDate(cutoff2Date.getDate() - CUTOFF_2_DAYS); | ||||||
|             const cutoff3Date = new Date(); |  | ||||||
|             cutoff3Date.setDate(cutoff3Date.getDate() - CUTOFF_3_DAYS); |  | ||||||
|  |  | ||||||
|             const query = `query( |             const query = `query( | ||||||
|                 $owner:String!, |                 $owner:String!, | ||||||
| @@ -260,12 +250,9 @@ jobs: | |||||||
|             const result = await github.graphql(query, variables); |             const result = await github.graphql(query, variables); | ||||||
|  |  | ||||||
|             for (const discussion of result.repository.discussions.nodes) { |             for (const discussion of result.repository.discussions.nodes) { | ||||||
|               const discussionUpdatedDate = new Date(discussion.updatedAt); |               const discussionDate = new Date(discussion.updatedAt); | ||||||
|               const discussionCreatedDate = new Date(discussion.createdAt); |               if ((discussionDate < cutoff1Date && discussion.upvoteCount < CUTOFF_1_COUNT) || | ||||||
|               if ((discussionUpdatedDate < cutoff1Date && discussion.upvoteCount < CUTOFF_MAX_COUNT) || |                   (discussionDate < cutoff2Date && discussion.upvoteCount < CUTOFF_2_COUNT)) { | ||||||
|                   (discussionCreatedDate < cutoff1Date && discussion.upvoteCount < CUTOFF_1_COUNT) || |  | ||||||
|                   (discussionCreatedDate < cutoff2Date && discussion.upvoteCount < CUTOFF_2_COUNT) || |  | ||||||
|                   (discussionCreatedDate < cutoff3Date && discussion.upvoteCount < CUTOFF_3_COUNT)) { |  | ||||||
|                 console.log(`Closing discussion #${discussion.number} (${discussion.id}), last updated at ${discussion.updatedAt} with votes ${discussion.upvoteCount}`); |                 console.log(`Closing discussion #${discussion.number} (${discussion.id}), last updated at ${discussion.updatedAt} with votes ${discussion.upvoteCount}`); | ||||||
|                 const addCommentMutation = `mutation($discussion:ID!, $body:String!) { |                 const addCommentMutation = `mutation($discussion:ID!, $body:String!) { | ||||||
|                   addDiscussionComment(input:{discussionId:$discussion, body:$body}) { |                   addDiscussionComment(input:{discussionId:$discussion, body:$body}) { | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -22,7 +22,6 @@ var/ | |||||||
| *.egg-info/ | *.egg-info/ | ||||||
| .installed.cfg | .installed.cfg | ||||||
| *.egg | *.egg | ||||||
| /src/paperless_mail/templates/node_modules |  | ||||||
|  |  | ||||||
| # PyInstaller | # PyInstaller | ||||||
| #  Usually these files are written by a python script from a template | #  Usually these files are written by a python script from a template | ||||||
| @@ -66,8 +65,6 @@ target/ | |||||||
| .vscode | .vscode | ||||||
| /src-ui/.vscode | /src-ui/.vscode | ||||||
| /docs/.vscode | /docs/.vscode | ||||||
| .vscode-server |  | ||||||
| *CommandMarker |  | ||||||
|  |  | ||||||
| # Other stuff that doesn't belong | # Other stuff that doesn't belong | ||||||
| .virtualenv | .virtualenv | ||||||
| @@ -100,9 +97,3 @@ scripts/nuke | |||||||
|  |  | ||||||
| # celery schedule file | # celery schedule file | ||||||
| celerybeat-schedule* | celerybeat-schedule* | ||||||
|  |  | ||||||
| # ignore .devcontainer sub folders |  | ||||||
| /.devcontainer/consume/ |  | ||||||
| /.devcontainer/data/ |  | ||||||
| /.devcontainer/media/ |  | ||||||
| /.devcontainer/redisdata/ |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| repos: | repos: | ||||||
|   # General hooks |   # General hooks | ||||||
|   - repo: https://github.com/pre-commit/pre-commit-hooks |   - repo: https://github.com/pre-commit/pre-commit-hooks | ||||||
|     rev: v5.0.0 |     rev: v4.6.0 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: check-docstring-first |       - id: check-docstring-first | ||||||
|       - id: check-json |       - id: check-json | ||||||
| @@ -29,16 +29,15 @@ repos: | |||||||
|       - id: check-case-conflict |       - id: check-case-conflict | ||||||
|       - id: detect-private-key |       - id: detect-private-key | ||||||
|   - repo: https://github.com/codespell-project/codespell |   - repo: https://github.com/codespell-project/codespell | ||||||
|     rev: v2.4.0 |     rev: v2.2.6 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: codespell |       - id: codespell | ||||||
|         exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)" |         exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)" | ||||||
|         exclude_types: |         exclude_types: | ||||||
|           - pofile |           - pofile | ||||||
|           - json |           - json | ||||||
|   # See https://github.com/prettier/prettier/issues/15742 for the fork reason |   - repo: https://github.com/pre-commit/mirrors-prettier | ||||||
|   - repo: https://github.com/rbubley/mirrors-prettier |     rev: 'v3.1.0' | ||||||
|     rev: 'v3.3.3' |  | ||||||
|     hooks: |     hooks: | ||||||
|       - id: prettier |       - id: prettier | ||||||
|         types_or: |         types_or: | ||||||
| @@ -46,15 +45,15 @@ repos: | |||||||
|           - ts |           - ts | ||||||
|           - markdown |           - markdown | ||||||
|         exclude: "(^Pipfile\\.lock$)" |         exclude: "(^Pipfile\\.lock$)" | ||||||
|         additional_dependencies: |  | ||||||
|           - prettier@3.3.3 |  | ||||||
|           - 'prettier-plugin-organize-imports@4.1.0' |  | ||||||
|   # Python hooks |   # Python hooks | ||||||
|   - repo: https://github.com/astral-sh/ruff-pre-commit |   - repo: https://github.com/astral-sh/ruff-pre-commit | ||||||
|     rev: v0.9.6 |     rev: 'v0.4.1' | ||||||
|     hooks: |     hooks: | ||||||
|       - id: ruff |       - id: ruff | ||||||
|       - id: ruff-format |   - repo: https://github.com/psf/black-pre-commit-mirror | ||||||
|  |     rev: 24.4.0 | ||||||
|  |     hooks: | ||||||
|  |       - id: black | ||||||
|   # Dockerfile hooks |   # Dockerfile hooks | ||||||
|   - repo: https://github.com/AleksaC/hadolint-py |   - repo: https://github.com/AleksaC/hadolint-py | ||||||
|     rev: v2.12.0.3 |     rev: v2.12.0.3 | ||||||
| @@ -65,8 +64,6 @@ repos: | |||||||
|     rev: v6.2.1 |     rev: v6.2.1 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: beautysh |       - id: beautysh | ||||||
|         additional_dependencies: |  | ||||||
|           - setuptools |  | ||||||
|         args: |         args: | ||||||
|           - "--tab" |           - "--tab" | ||||||
|   - repo: https://github.com/shellcheck-py/shellcheck-py |   - repo: https://github.com/shellcheck-py/shellcheck-py | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | { | ||||||
|  |     # https://prettier.io/docs/en/options.html#semicolons | ||||||
|  |     "semi": false, | ||||||
|  |     # https://prettier.io/docs/en/options.html#quotes | ||||||
|  |     "singleQuote": true, | ||||||
|  |     # https://prettier.io/docs/en/options.html#trailing-commas | ||||||
|  |     "trailingComma": "es5", | ||||||
|  |     "overrides": [ | ||||||
|  |         { | ||||||
|  |             "files": ["index.md", "administration.md"], | ||||||
|  |             "options": { | ||||||
|  |                 "tabWidth": 4 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| const config = { |  | ||||||
| 	// https://prettier.io/docs/en/options.html#semicolons |  | ||||||
| 	semi: false, |  | ||||||
| 	// https://prettier.io/docs/en/options.html#quotes |  | ||||||
| 	singleQuote: true, |  | ||||||
| 	// https://prettier.io/docs/en/options.html#trailing-commas |  | ||||||
| 	trailingComma: 'es5', |  | ||||||
| 	overrides: [ |  | ||||||
| 		{ |  | ||||||
| 			files: ['docs/*.md'], |  | ||||||
| 			options: { |  | ||||||
| 				tabWidth: 4, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 	], |  | ||||||
| 	plugins: [require('prettier-plugin-organize-imports')], |  | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = config |  | ||||||
| @@ -1 +1 @@ | |||||||
| 3.10.15 | 3.9.18 | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								.ruff.toml
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								.ruff.toml
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ fix = true | |||||||
| line-length = 88 | line-length = 88 | ||||||
| respect-gitignore = true | respect-gitignore = true | ||||||
| src = ["src"] | src = ["src"] | ||||||
| target-version = "py310" | target-version = "py39" | ||||||
| output-format = "grouped" | output-format = "grouped" | ||||||
| show-fixes = true | show-fixes = true | ||||||
|  |  | ||||||
| @@ -31,57 +31,17 @@ extend-select = [ | |||||||
|   "PLE",   # https://docs.astral.sh/ruff/rules/#pylint-pl |   "PLE",   # https://docs.astral.sh/ruff/rules/#pylint-pl | ||||||
|   "RUF",   # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf |   "RUF",   # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf | ||||||
|   "FLY",   # https://docs.astral.sh/ruff/rules/#flynt-fly |   "FLY",   # https://docs.astral.sh/ruff/rules/#flynt-fly | ||||||
|   "PTH",   # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth |  | ||||||
|   "FBT",   # https://docs.astral.sh/ruff/rules/#flake8-boolean-trap-fbt |  | ||||||
| ] | ] | ||||||
|  | # TODO PTH https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth | ||||||
| ignore = ["DJ001", "SIM105", "RUF012"] | ignore = ["DJ001", "SIM105", "RUF012"] | ||||||
|  |  | ||||||
| [lint.per-file-ignores] | [lint.per-file-ignores] | ||||||
| ".github/scripts/*.py" = ["E501", "INP001", "SIM117"] | ".github/scripts/*.py" = ["E501", "INP001", "SIM117"] | ||||||
| "docker/wait-for-redis.py" = ["INP001", "T201"] | "docker/wait-for-redis.py" = ["INP001", "T201"] | ||||||
| "src/documents/file_handling.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/management/commands/document_consumer.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/management/commands/document_exporter.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/migrations/0012_auto_20160305_0040.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/migrations/0014_document_checksum.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/migrations/1003_mime_types.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/migrations/1012_fix_archive_files.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/models.py" = ["SIM115", "PTH"]  # TODO PTH Enable & remove |  | ||||||
| "src/documents/parsers.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/signals/handlers.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tasks.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_api_app_config.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_classifier.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_consumer.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_file_handling.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_management.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_management_consumer.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_management_exporter.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_management_thumbnails.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_migration_archive_files.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_migration_document_pages_count.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_migration_mime_type.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_sanity_check.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_tasks.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/tests/test_views.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/documents/views.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless/checks.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless/settings.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless/tests/test_checks.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless/urls.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless/views.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless_mail/mail.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless_mail/preprocessor.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless_tesseract/parsers.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless_tesseract/tests/test_parser.py" = ["RUF001", "PTH"]  # TODO PTH Enable & remove |  | ||||||
| "src/paperless_tika/tests/test_live_tika.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| "src/paperless_tika/tests/test_tika_parser.py" = ["PTH"]  # TODO Enable & remove |  | ||||||
| # Testing |  | ||||||
| "*/tests/*.py" = ["E501", "SIM117"] | "*/tests/*.py" = ["E501", "SIM117"] | ||||||
| # Migrations |  | ||||||
| "*/migrations/*.py" = ["E501", "SIM", "T201"] | "*/migrations/*.py" = ["E501", "SIM", "T201"] | ||||||
| # Docker specific | "src/paperless_tesseract/tests/test_parser.py" = ["RUF001"] | ||||||
| "docker/rootfs/usr/local/bin/wait-for-redis.py" = ["INP001", "T201"] | "src/documents/models.py" = ["SIM115"] | ||||||
|  |  | ||||||
| [lint.isort] | [lint.isort] | ||||||
| force-single-line = true | force-single-line = true | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| We as members, contributors, and leaders pledge to make participation in our | We as members, contributors, and leaders pledge to make participation in our | ||||||
| community a harassment-free experience for everyone, regardless of age, body | community a harassment-free experience for everyone, regardless of age, body | ||||||
| size, visible or invisible disability, ethnicity, sex characteristics, gender | size, visible or invisible disability, ethnicity, sex characteristics, gender | ||||||
| identity and expression, level of experience, education, socioeconomic status, | identity and expression, level of experience, education, socio-economic status, | ||||||
| nationality, personal appearance, race, religion, or sexual identity | nationality, personal appearance, race, religion, or sexual identity | ||||||
| and orientation. | and orientation. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ If you want to implement something big: | |||||||
|  |  | ||||||
| ## Python | ## Python | ||||||
|  |  | ||||||
| Paperless supports python 3.10 - 3.12 at this time. We format Python code with [ruff](https://docs.astral.sh/ruff/formatter/). | Paperless supports python 3.9 - 3.11. We format Python code with [Black](https://github.com/psf/black). | ||||||
|  |  | ||||||
| ## Branches | ## Branches | ||||||
|  |  | ||||||
| @@ -147,7 +147,7 @@ community members. That said, in an effort to keep the repository organized and | |||||||
| - Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity. | - Issues, pull requests and discussions that are closed will be locked after 30 days of inactivity. | ||||||
| - Discussions with a marked answer will be automatically closed. | - Discussions with a marked answer will be automatically closed. | ||||||
| - Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity. | - Discussions in the 'General' or 'Support' categories will be closed after 180 days of inactivity. | ||||||
| - Feature requests that do not meet the following thresholds will be closed: 180 days of inactivity, < 5 "up-votes" after 180 days, < 20 "up-votes" after 1 year or < 80 "up-votes" at 2 years. | - Feature requests that do not meet the following thresholds will be closed: 5 "up-votes" after 180 days of inactivity or 10 "up-votes" after 365 days. | ||||||
|  |  | ||||||
| In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns. | In all cases, threads can be re-opened by project maintainers and, of course, users can always create a new discussion for related concerns. | ||||||
| Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features. | Finally, remember that all information remains searchable and 'closed' feature requests can still serve as inspiration for new features. | ||||||
|   | |||||||
							
								
								
									
										187
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -13,16 +13,6 @@ WORKDIR /src/src-ui | |||||||
| RUN set -eux \ | RUN set -eux \ | ||||||
|   && npm update npm -g \ |   && npm update npm -g \ | ||||||
|   && npm ci |   && npm ci | ||||||
|  |  | ||||||
| ARG PNGX_TAG_VERSION= |  | ||||||
| # Add the tag to the environment file if its a tagged dev build |  | ||||||
| RUN set -eux && \ |  | ||||||
| case "${PNGX_TAG_VERSION}" in \ |  | ||||||
|   dev|beta|fix*|feature*) \ |  | ||||||
|     sed -i -E "s/version: '([0-9\.]+)'/version: '\1 #${PNGX_TAG_VERSION}'/g" /src/src-ui/src/environments/environment.prod.ts \ |  | ||||||
|     ;; \ |  | ||||||
| esac |  | ||||||
|  |  | ||||||
| RUN set -eux \ | RUN set -eux \ | ||||||
|   && ./node_modules/.bin/ng build --configuration production |   && ./node_modules/.bin/ng build --configuration production | ||||||
|  |  | ||||||
| @@ -31,7 +21,7 @@ RUN set -eux \ | |||||||
| # Comments: | # Comments: | ||||||
| #  - pipenv dependencies are not left in the final image | #  - pipenv dependencies are not left in the final image | ||||||
| #  - pipenv can't touch the final image somehow | #  - pipenv can't touch the final image somehow | ||||||
| FROM --platform=$BUILDPLATFORM docker.io/python:3.12-alpine AS pipenv-base | FROM --platform=$BUILDPLATFORM docker.io/python:3.11-alpine as pipenv-base | ||||||
|  |  | ||||||
| WORKDIR /usr/src/pipenv | WORKDIR /usr/src/pipenv | ||||||
|  |  | ||||||
| @@ -39,70 +29,15 @@ COPY Pipfile* ./ | |||||||
|  |  | ||||||
| RUN set -eux \ | RUN set -eux \ | ||||||
|   && echo "Installing pipenv" \ |   && echo "Installing pipenv" \ | ||||||
|     && python3 -m pip install --no-cache-dir --upgrade pipenv==2024.4.1 \ |     && python3 -m pip install --no-cache-dir --upgrade pipenv==2023.12.1 \ | ||||||
|   && echo "Generating requirement.txt" \ |   && echo "Generating requirement.txt" \ | ||||||
|     && pipenv requirements > requirements.txt |     && pipenv requirements > requirements.txt | ||||||
|  |  | ||||||
| # Stage: s6-overlay-base |  | ||||||
| # Purpose: Installs s6-overlay and rootfs |  | ||||||
| # Comments: |  | ||||||
| #  - Don't leave anything extra in here either |  | ||||||
| FROM docker.io/python:3.12-slim-bookworm AS s6-overlay-base |  | ||||||
|  |  | ||||||
| WORKDIR /usr/src/s6 |  | ||||||
|  |  | ||||||
| # https://github.com/just-containers/s6-overlay#customizing-s6-overlay-behaviour |  | ||||||
| ENV \ |  | ||||||
|     S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \ |  | ||||||
|     S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \ |  | ||||||
|     S6_VERBOSITY=1 \ |  | ||||||
|     PATH=/command:$PATH |  | ||||||
|  |  | ||||||
| # Buildx provided, must be defined to use though |  | ||||||
| ARG TARGETARCH |  | ||||||
| ARG TARGETVARIANT |  | ||||||
| # Lock this version |  | ||||||
| ARG S6_OVERLAY_VERSION=3.2.0.2 |  | ||||||
|  |  | ||||||
| ARG S6_BUILD_TIME_PKGS="curl \ |  | ||||||
|                         xz-utils" |  | ||||||
|  |  | ||||||
| RUN set -eux \ |  | ||||||
|     && echo "Installing build time packages" \ |  | ||||||
|       && apt-get update \ |  | ||||||
|       && apt-get install --yes --quiet --no-install-recommends ${S6_BUILD_TIME_PKGS} \ |  | ||||||
|     && echo "Determining arch" \ |  | ||||||
|       && S6_ARCH="" \ |  | ||||||
|       && if [ "${TARGETARCH}${TARGETVARIANT}" = "amd64" ]; then S6_ARCH="x86_64"; \ |  | ||||||
|       elif [ "${TARGETARCH}${TARGETVARIANT}" = "arm64" ]; then S6_ARCH="aarch64"; fi\ |  | ||||||
|       && if [ -z "${S6_ARCH}" ]; then { echo "Error: Not able to determine arch"; exit 1; }; fi \ |  | ||||||
|     && echo "Installing s6-overlay for ${S6_ARCH}" \ |  | ||||||
|       && curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \ |  | ||||||
|         "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz" \ |  | ||||||
|         "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz.sha256" \ |  | ||||||
|         "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz" \ |  | ||||||
|         "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz.sha256" \ |  | ||||||
|       && echo "Validating s6-archive checksums" \ |  | ||||||
|         && sha256sum --check ./*.sha256 \ |  | ||||||
|       && echo "Unpacking archives" \ |  | ||||||
|         && tar --directory / -Jxpf s6-overlay-noarch.tar.xz \ |  | ||||||
|         && tar --directory / -Jxpf s6-overlay-${S6_ARCH}.tar.xz \ |  | ||||||
|       && echo "Removing downloaded archives" \ |  | ||||||
|         && rm ./*.tar.xz \ |  | ||||||
|         && rm ./*.sha256 \ |  | ||||||
|     && echo "Cleaning up image" \ |  | ||||||
|       && apt-get --yes purge ${S6_BUILD_TIME_PKGS} \ |  | ||||||
|       && apt-get --yes autoremove --purge \ |  | ||||||
|       && rm -rf /var/lib/apt/lists/* |  | ||||||
|  |  | ||||||
| # Copy our service defs and filesystem |  | ||||||
| COPY ./docker/rootfs / |  | ||||||
|  |  | ||||||
| # Stage: main-app | # Stage: main-app | ||||||
| # Purpose: The final image | # Purpose: The final image | ||||||
| # Comments: | # Comments: | ||||||
| #  - Don't leave anything extra in here | #  - Don't leave anything extra in here | ||||||
| FROM s6-overlay-base AS main-app | FROM docker.io/python:3.11-slim-bookworm as main-app | ||||||
|  |  | ||||||
| LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>" | LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>" | ||||||
| LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/" | LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/" | ||||||
| @@ -116,9 +51,9 @@ ARG DEBIAN_FRONTEND=noninteractive | |||||||
| ARG TARGETARCH | ARG TARGETARCH | ||||||
|  |  | ||||||
| # Can be workflow provided, defaults set for manual building | # Can be workflow provided, defaults set for manual building | ||||||
| ARG JBIG2ENC_VERSION=0.30 | ARG JBIG2ENC_VERSION=0.29 | ||||||
| ARG QPDF_VERSION=11.9.0 | ARG QPDF_VERSION=11.9.0 | ||||||
| ARG GS_VERSION=10.03.1 | ARG GS_VERSION=10.02.1 | ||||||
|  |  | ||||||
| # Set Python environment variables | # Set Python environment variables | ||||||
| ENV PYTHONDONTWRITEBYTECODE=1 \ | ENV PYTHONDONTWRITEBYTECODE=1 \ | ||||||
| @@ -148,6 +83,7 @@ ARG RUNTIME_PACKAGES="\ | |||||||
|   icc-profiles-free \ |   icc-profiles-free \ | ||||||
|   imagemagick \ |   imagemagick \ | ||||||
|   # PostgreSQL |   # PostgreSQL | ||||||
|  |   libpq5 \ | ||||||
|   postgresql-client \ |   postgresql-client \ | ||||||
|   # MySQL / MariaDB |   # MySQL / MariaDB | ||||||
|   mariadb-client \ |   mariadb-client \ | ||||||
| @@ -182,39 +118,91 @@ RUN set -eux \ | |||||||
|     && apt-get update \ |     && apt-get update \ | ||||||
|     && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \ |     && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \ | ||||||
|     && echo "Installing pre-built updates" \ |     && echo "Installing pre-built updates" \ | ||||||
|       && curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ |  | ||||||
|         https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ |  | ||||||
|       && echo "Installing qpdf ${QPDF_VERSION}" \ |       && echo "Installing qpdf ${QPDF_VERSION}" \ | ||||||
|  |         && curl --fail --silent --show-error --location \ | ||||||
|  |           --output libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|  |           https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|  |         && curl --fail --silent --show-error --location \ | ||||||
|  |           --output qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|  |           https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|         && dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |         && dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|         && dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ |         && dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|       && echo "Installing Ghostscript ${GS_VERSION}" \ |       && echo "Installing Ghostscript ${GS_VERSION}" \ | ||||||
|         && dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ |         && curl --fail --silent --show-error --location \ | ||||||
|         && dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |           --output libgs10_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \ | ||||||
|         && dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ |           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ | ||||||
|  |         && curl --fail --silent --show-error --location \ | ||||||
|  |           --output ghostscript_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \ | ||||||
|  |           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \ | ||||||
|  |         && curl --fail --silent --show-error --location \ | ||||||
|  |           --output libgs10-common_${GS_VERSION}.dfsg-2_all.deb \ | ||||||
|  |           https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \ | ||||||
|  |         && dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-2_all.deb \ | ||||||
|  |         && dpkg --install ./libgs10_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \ | ||||||
|  |         && dpkg --install ./ghostscript_${GS_VERSION}.dfsg-2_${TARGETARCH}.deb \ | ||||||
|       && echo "Installing jbig2enc" \ |       && echo "Installing jbig2enc" \ | ||||||
|  |         && curl --fail --silent --show-error --location \ | ||||||
|  |           --output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|  |           https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|         && dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ |         && dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \ | ||||||
|       && echo "Configuring imagemagick" \ |  | ||||||
|         && cp /etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml \ |  | ||||||
|       && echo "Cleaning up image layer" \ |       && echo "Cleaning up image layer" \ | ||||||
|         && rm --force --verbose *.deb \ |         && rm --force --verbose *.deb \ | ||||||
|     && rm --recursive --force --verbose /var/lib/apt/lists/* |     && rm --recursive --force --verbose /var/lib/apt/lists/* \ | ||||||
|  |   && echo "Installing supervisor" \ | ||||||
|  |     && python3 -m pip install --default-timeout=1000 --upgrade --no-cache-dir supervisor==4.2.5 | ||||||
|  |  | ||||||
| # Copy gunicorn config | # Copy gunicorn config | ||||||
| # Changes very infrequently | # Changes very infrequently | ||||||
| WORKDIR /usr/src/paperless/ | WORKDIR /usr/src/paperless/ | ||||||
|  |  | ||||||
| COPY --chown=1000:1000 gunicorn.conf.py /usr/src/paperless/gunicorn.conf.py | COPY gunicorn.conf.py . | ||||||
|  |  | ||||||
|  | # setup docker-specific things | ||||||
|  | # These change sometimes, but rarely | ||||||
|  | WORKDIR /usr/src/paperless/src/docker/ | ||||||
|  |  | ||||||
|  | COPY [ \ | ||||||
|  |   "docker/imagemagick-policy.xml", \ | ||||||
|  |   "docker/supervisord.conf", \ | ||||||
|  |   "docker/docker-entrypoint.sh", \ | ||||||
|  |   "docker/docker-prepare.sh", \ | ||||||
|  |   "docker/paperless_cmd.sh", \ | ||||||
|  |   "docker/wait-for-redis.py", \ | ||||||
|  |   "docker/env-from-file.sh", \ | ||||||
|  |   "docker/management_script.sh", \ | ||||||
|  |   "docker/flower-conditional.sh", \ | ||||||
|  |   "docker/install_management_commands.sh", \ | ||||||
|  |   "/usr/src/paperless/src/docker/" \ | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | RUN set -eux \ | ||||||
|  |   && echo "Configuring ImageMagick" \ | ||||||
|  |     && mv imagemagick-policy.xml /etc/ImageMagick-6/policy.xml \ | ||||||
|  |   && echo "Configuring supervisord" \ | ||||||
|  |     && mkdir /var/log/supervisord /var/run/supervisord \ | ||||||
|  |     && mv supervisord.conf /etc/supervisord.conf \ | ||||||
|  |   && echo "Setting up Docker scripts" \ | ||||||
|  |     && mv docker-entrypoint.sh /sbin/docker-entrypoint.sh \ | ||||||
|  |     && chmod 755 /sbin/docker-entrypoint.sh \ | ||||||
|  |     && mv docker-prepare.sh /sbin/docker-prepare.sh \ | ||||||
|  |     && chmod 755 /sbin/docker-prepare.sh \ | ||||||
|  |     && mv wait-for-redis.py /sbin/wait-for-redis.py \ | ||||||
|  |     && chmod 755 /sbin/wait-for-redis.py \ | ||||||
|  |     && mv env-from-file.sh /sbin/env-from-file.sh \ | ||||||
|  |     && chmod 755 /sbin/env-from-file.sh \ | ||||||
|  |     && mv paperless_cmd.sh /usr/local/bin/paperless_cmd.sh \ | ||||||
|  |     && chmod 755 /usr/local/bin/paperless_cmd.sh \ | ||||||
|  |     && mv flower-conditional.sh /usr/local/bin/flower-conditional.sh \ | ||||||
|  |     && chmod 755 /usr/local/bin/flower-conditional.sh \ | ||||||
|  |   && echo "Installing management commands" \ | ||||||
|  |     && chmod +x install_management_commands.sh \ | ||||||
|  |     && ./install_management_commands.sh | ||||||
|  |  | ||||||
| WORKDIR /usr/src/paperless/src/ | WORKDIR /usr/src/paperless/src/ | ||||||
|  |  | ||||||
| # Python dependencies | # Python dependencies | ||||||
| # Change pretty frequently | # Change pretty frequently | ||||||
| COPY --chown=1000:1000 --from=pipenv-base /usr/src/pipenv/requirements.txt ./ | COPY --from=pipenv-base /usr/src/pipenv/requirements.txt ./ | ||||||
|  |  | ||||||
| # Packages needed only for building a few quick Python | # Packages needed only for building a few quick Python | ||||||
| # dependencies | # dependencies | ||||||
| @@ -227,32 +215,27 @@ ARG BUILD_PACKAGES="\ | |||||||
|   default-libmysqlclient-dev \ |   default-libmysqlclient-dev \ | ||||||
|   pkg-config" |   pkg-config" | ||||||
|  |  | ||||||
| ARG ZXING_VERSION=2.3.0 |  | ||||||
| ARG PSYCOPG_VERSION=3.2.4 |  | ||||||
|  |  | ||||||
| # hadolint ignore=DL3042 | # hadolint ignore=DL3042 | ||||||
| RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \ | RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \ | ||||||
|   set -eux \ |   set -eux \ | ||||||
|   && echo "Installing build system packages" \ |   && echo "Installing build system packages" \ | ||||||
|     && apt-get update \ |     && apt-get update \ | ||||||
|     && apt-get install --yes --quiet --no-install-recommends ${BUILD_PACKAGES} \ |     && apt-get install --yes --quiet --no-install-recommends ${BUILD_PACKAGES} \ | ||||||
|     && python3 -m pip install --upgrade wheel \ |     && python3 -m pip install --no-cache-dir --upgrade wheel \ | ||||||
|   && echo "Installing Python requirements" \ |   && echo "Installing Python requirements" \ | ||||||
|     && curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \ |     && python3 -m pip install --default-timeout=1000 --requirement requirements.txt \ | ||||||
|       https://github.com/paperless-ngx/builder/releases/download/psycopg-${PSYCOPG_VERSION}/psycopg_c-${PSYCOPG_VERSION}-cp312-cp312-linux_x86_64.whl \ |   && echo "Patching whitenoise for compression speedup" \ | ||||||
|       https://github.com/paperless-ngx/builder/releases/download/psycopg-${PSYCOPG_VERSION}/psycopg_c-${PSYCOPG_VERSION}-cp312-cp312-linux_aarch64.whl \ |     && curl --fail --silent --show-error --location --output 484.patch https://github.com/evansd/whitenoise/pull/484.patch \ | ||||||
|       https://github.com/paperless-ngx/builder/releases/download/zxing-${ZXING_VERSION}/zxing_cpp-${ZXING_VERSION}-cp312-cp312-linux_aarch64.whl \ |     && patch -d /usr/local/lib/python3.11/site-packages --verbose -p2 < 484.patch \ | ||||||
|       https://github.com/paperless-ngx/builder/releases/download/zxing-${ZXING_VERSION}/zxing_cpp-${ZXING_VERSION}-cp312-cp312-linux_x86_64.whl \ |     && rm 484.patch \ | ||||||
|     && python3 -m pip install --default-timeout=1000 --find-links . --requirement requirements.txt \ |  | ||||||
|   && echo "Installing NLTK data" \ |   && echo "Installing NLTK data" \ | ||||||
|     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \ |     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \ | ||||||
|     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \ |     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \ | ||||||
|     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" punkt_tab \ |     && python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" punkt \ | ||||||
|   && echo "Cleaning up image" \ |   && echo "Cleaning up image" \ | ||||||
|     && apt-get --yes purge ${BUILD_PACKAGES} \ |     && apt-get --yes purge ${BUILD_PACKAGES} \ | ||||||
|     && apt-get --yes autoremove --purge \ |     && apt-get --yes autoremove --purge \ | ||||||
|     && apt-get clean --yes \ |     && apt-get clean --yes \ | ||||||
|     && rm --recursive --force --verbose *.whl \ |  | ||||||
|     && rm --recursive --force --verbose /var/lib/apt/lists/* \ |     && rm --recursive --force --verbose /var/lib/apt/lists/* \ | ||||||
|     && rm --recursive --force --verbose /tmp/* \ |     && rm --recursive --force --verbose /tmp/* \ | ||||||
|     && rm --recursive --force --verbose /var/tmp/* \ |     && rm --recursive --force --verbose /var/tmp/* \ | ||||||
| @@ -276,21 +259,21 @@ RUN set -eux \ | |||||||
|     && mkdir --parents --verbose /usr/src/paperless/media \ |     && mkdir --parents --verbose /usr/src/paperless/media \ | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/consume \ |     && mkdir --parents --verbose /usr/src/paperless/consume \ | ||||||
|     && mkdir --parents --verbose /usr/src/paperless/export \ |     && mkdir --parents --verbose /usr/src/paperless/export \ | ||||||
|   && echo "Creating gnupg directory" \ |  | ||||||
|     && mkdir -m700 --verbose /usr/src/paperless/.gnupg \ |  | ||||||
|   && echo "Adjusting all permissions" \ |   && echo "Adjusting all permissions" \ | ||||||
|     && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \ |     && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \ | ||||||
|   && echo "Collecting static files" \ |   && echo "Collecting static files" \ | ||||||
|     && s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \ |     && gosu paperless python3 manage.py collectstatic --clear --no-input --link \ | ||||||
|     && s6-setuidgid paperless python3 manage.py compilemessages |     && gosu paperless python3 manage.py compilemessages | ||||||
|  |  | ||||||
| VOLUME ["/usr/src/paperless/data", \ | VOLUME ["/usr/src/paperless/data", \ | ||||||
|         "/usr/src/paperless/media", \ |         "/usr/src/paperless/media", \ | ||||||
|         "/usr/src/paperless/consume", \ |         "/usr/src/paperless/consume", \ | ||||||
|         "/usr/src/paperless/export"] |         "/usr/src/paperless/export"] | ||||||
|  |  | ||||||
| ENTRYPOINT ["/init"] | ENTRYPOINT ["/sbin/docker-entrypoint.sh"] | ||||||
|  |  | ||||||
| EXPOSE 8000 | EXPOSE 8000 | ||||||
|  |  | ||||||
|  | CMD ["/usr/local/bin/paperless_cmd.sh"] | ||||||
|  |  | ||||||
| HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000" ] | HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000" ] | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								Pipfile
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								Pipfile
									
									
									
									
									
								
							| @@ -7,42 +7,37 @@ name = "pypi" | |||||||
| dateparser = "~=1.2" | dateparser = "~=1.2" | ||||||
| # WARNING: django does not use semver. | # WARNING: django does not use semver. | ||||||
| #          Only patch versions are guaranteed to not introduce breaking changes. | #          Only patch versions are guaranteed to not introduce breaking changes. | ||||||
| django = "~=5.1.5" | django = "~=4.2.11" | ||||||
| django-allauth = {extras = ["mfa", "socialaccount"], version = "*"} | django-allauth = "*" | ||||||
| django-auditlog = "*" | django-auditlog = "*" | ||||||
| django-celery-results = "*" | django-celery-results = "*" | ||||||
| django-compression-middleware = "*" | django-compression-middleware = "*" | ||||||
| django-cors-headers = "*" | django-cors-headers = "*" | ||||||
| django-extensions = "*" | django-extensions = "*" | ||||||
| django-filter = "~=25.1" | django-filter = "~=24.2" | ||||||
| django-guardian = "*" | django-guardian = "*" | ||||||
| django-multiselectfield = "*" | django-multiselectfield = "*" | ||||||
| django-soft-delete = "*" | djangorestframework = "==3.14.0" | ||||||
| djangorestframework = "~=3.15.2" |  | ||||||
| djangorestframework-guardian = "*" | djangorestframework-guardian = "*" | ||||||
| drf-spectacular = "*" |  | ||||||
| drf-spectacular-sidecar = "*" |  | ||||||
| drf-writable-nested = "*" | drf-writable-nested = "*" | ||||||
| bleach = "*" | bleach = "*" | ||||||
| celery = {extras = ["redis"], version = "*"} | celery = {extras = ["redis"], version = "*"} | ||||||
| channels = "~=4.2" | channels = "~=4.1" | ||||||
| channels-redis = "*" | channels-redis = "*" | ||||||
| concurrent-log-handler = "*" | concurrent-log-handler = "*" | ||||||
| filelock = "*" | filelock = "*" | ||||||
| flower = "*" | flower = "*" | ||||||
| gotenberg-client = "*" | gotenberg-client = "*" | ||||||
| gunicorn = "*" | gunicorn = "*" | ||||||
| httpx-oauth = "*" |  | ||||||
| imap-tools = "*" | imap-tools = "*" | ||||||
| inotifyrecursive = "~=0.3" | inotifyrecursive = "~=0.3" | ||||||
| jinja2 = "~=3.1" |  | ||||||
| langdetect = "*" | langdetect = "*" | ||||||
| mysqlclient = "*" | mysqlclient = "*" | ||||||
| nltk = "*" | nltk = "*" | ||||||
| ocrmypdf = "~=16.9" | ocrmypdf = "~=15.4" | ||||||
| pathvalidate = "*" | pathvalidate = "*" | ||||||
| pdf2image = "*" | pdf2image = "*" | ||||||
| psycopg = {version = "*", extras = ["c"]} | psycopg2 = "*" | ||||||
| python-dateutil = "*" | python-dateutil = "*" | ||||||
| python-dotenv = "*" | python-dotenv = "*" | ||||||
| python-gnupg = "*" | python-gnupg = "*" | ||||||
| @@ -51,24 +46,23 @@ python-magic = "*" | |||||||
| pyzbar = "*" | pyzbar = "*" | ||||||
| rapidfuzz = "*" | rapidfuzz = "*" | ||||||
| redis = {extras = ["hiredis"], version = "*"} | redis = {extras = ["hiredis"], version = "*"} | ||||||
| scikit-learn = "~=1.6" | scikit-learn = "~=1.4" | ||||||
| setproctitle = "*" | setproctitle = "*" | ||||||
| tika-client = "*" | tika-client = "*" | ||||||
| tqdm = "*" | tqdm = "*" | ||||||
| # See https://github.com/paperless-ngx/paperless-ngx/issues/5494 |  | ||||||
| uvicorn = {extras = ["standard"], version = "==0.25.0"} | uvicorn = {extras = ["standard"], version = "==0.25.0"} | ||||||
| watchdog = "~=6.0" | watchdog = "~=4.0" | ||||||
| whitenoise = "~=6.9" | whitenoise = "~=6.6" | ||||||
| whoosh = "~=2.7" | whoosh="~=2.7" | ||||||
| zxing-cpp = "*" | zxing-cpp = {version = "*", platform_machine = "== 'x86_64'"} | ||||||
|  |  | ||||||
|  |  | ||||||
| [dev-packages] | [dev-packages] | ||||||
| # Linting | # Linting | ||||||
|  | black = "*" | ||||||
| pre-commit = "*" | pre-commit = "*" | ||||||
| ruff = "*" | ruff = "*" | ||||||
| factory-boy = "*" |  | ||||||
| # Testing | # Testing | ||||||
|  | factory-boy = "*" | ||||||
| pytest = "*" | pytest = "*" | ||||||
| pytest-cov = "*" | pytest-cov = "*" | ||||||
| pytest-django = "*" | pytest-django = "*" | ||||||
| @@ -76,7 +70,6 @@ pytest-httpx = "*" | |||||||
| pytest-env = "*" | pytest-env = "*" | ||||||
| pytest-sugar = "*" | pytest-sugar = "*" | ||||||
| pytest-xdist = "*" | pytest-xdist = "*" | ||||||
| pytest-mock = "*" |  | ||||||
| pytest-rerunfailures = "*" | pytest-rerunfailures = "*" | ||||||
| imagehash = "*" | imagehash = "*" | ||||||
| daphne = "*" | daphne = "*" | ||||||
| @@ -99,4 +92,5 @@ types-tqdm = "*" | |||||||
| types-Markdown = "*" | types-Markdown = "*" | ||||||
| types-Pygments = "*" | types-Pygments = "*" | ||||||
| types-colorama = "*" | types-colorama = "*" | ||||||
|  | types-psycopg2 = "*" | ||||||
| types-setuptools = "*" | types-setuptools = "*" | ||||||
|   | |||||||
							
								
								
									
										6423
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6423
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @@ -30,14 +30,14 @@ Thanks to the generous folks at [DigitalOcean](https://m.do.co/c/8d70b916d462), | |||||||
|   - [Translation](#translation) |   - [Translation](#translation) | ||||||
|   - [Feature Requests](#feature-requests) |   - [Feature Requests](#feature-requests) | ||||||
|   - [Bugs](#bugs) |   - [Bugs](#bugs) | ||||||
| - [Related Projects](#related-projects) | - [Affiliated Projects](#affiliated-projects) | ||||||
| - [Important Note](#important-note) | - [Important Note](#important-note) | ||||||
|  |  | ||||||
| <p align="right">This project is supported by:<br/> | <p align="right">This project is supported by:<br/> | ||||||
|   <a href="https://m.do.co/c/8d70b916d462" style="padding-top: 4px; display: block;"> |   <a href="https://m.do.co/c/8d70b916d462" style="padding-top: 4px; display: block;"> | ||||||
|     <picture> |     <picture> | ||||||
|       <source media="(prefers-color-scheme: dark)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_white.svg" width="140px"> |       <source media="(prefers-color-scheme: dark)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_white.svg" width="140px"> | ||||||
|       <source media="(prefers-color-scheme: light)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="140px"> |       <source media="(prefers-color-scheme: light)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px"> | ||||||
|       <img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px"> |       <img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px"> | ||||||
|     </picture> |     </picture> | ||||||
|   </a> |   </a> | ||||||
| @@ -55,7 +55,7 @@ A full list of [features](https://docs.paperless-ngx.com/#features) and [screens | |||||||
|  |  | ||||||
| # Getting started | # Getting started | ||||||
|  |  | ||||||
| The easiest way to deploy paperless is `docker compose`. The files in the [`/docker/compose` directory](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose) are configured to pull the image from the GitHub container registry. | The easiest way to deploy paperless is `docker compose`. The files in the [`/docker/compose` directory](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose) are configured to pull the image from GitHub Packages. | ||||||
|  |  | ||||||
| If you'd like to jump right in, you can configure a `docker compose` environment with our install script: | If you'd like to jump right in, you can configure a `docker compose` environment with our install script: | ||||||
|  |  | ||||||
| @@ -63,7 +63,7 @@ If you'd like to jump right in, you can configure a `docker compose` environment | |||||||
| bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)" | bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)" | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| More details and step-by-step guides for alternative installation methods can be found in [the documentation](https://docs.paperless-ngx.com/setup/#installation). | Alternatively, you can install the dependencies and setup apache and a database server yourself. The [documentation](https://docs.paperless-ngx.com/setup/#installation) has a step by step guide on how to do it. | ||||||
|  |  | ||||||
| Migrating from Paperless-ng is easy, just drop in the new docker image! See the [documentation on migrating](https://docs.paperless-ngx.com/setup/#migrating-to-paperless-ngx) for more details. | Migrating from Paperless-ng is easy, just drop in the new docker image! See the [documentation on migrating](https://docs.paperless-ngx.com/setup/#migrating-to-paperless-ngx) for more details. | ||||||
|  |  | ||||||
| @@ -93,9 +93,9 @@ Feature requests can be submitted via [GitHub Discussions](https://github.com/pa | |||||||
|  |  | ||||||
| For bugs please [open an issue](https://github.com/paperless-ngx/paperless-ngx/issues) or [start a discussion](https://github.com/paperless-ngx/paperless-ngx/discussions) if you have questions. | For bugs please [open an issue](https://github.com/paperless-ngx/paperless-ngx/issues) or [start a discussion](https://github.com/paperless-ngx/paperless-ngx/discussions) if you have questions. | ||||||
|  |  | ||||||
| # Related Projects | # Affiliated Projects | ||||||
|  |  | ||||||
| Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Related-Projects) for a user-maintained list of related projects and software that is compatible with Paperless-ngx. | Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Affiliated-Projects) for a user-maintained list of affiliated projects and software that is compatible with Paperless-ngx. | ||||||
|  |  | ||||||
| # Important Note | # Important Note | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,9 +3,10 @@ | |||||||
| # Can be used locally or by the CI to start the necessary containers with the | # Can be used locally or by the CI to start the necessary containers with the | ||||||
| # correct networking for the tests | # correct networking for the tests | ||||||
|  |  | ||||||
|  | version: "3.7" | ||||||
| services: | services: | ||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:8.17 |     image: docker.io/gotenberg/gotenberg:7.10 | ||||||
|     hostname: gotenberg |     hostname: gotenberg | ||||||
|     container_name: gotenberg |     container_name: gotenberg | ||||||
|     network_mode: host |     network_mode: host | ||||||
| @@ -19,7 +20,7 @@ services: | |||||||
|       - "--log-level=warn" |       - "--log-level=warn" | ||||||
|       - "--log-format=text" |       - "--log-format=text" | ||||||
|   tika: |   tika: | ||||||
|     image: docker.io/apache/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|     hostname: tika |     hostname: tika | ||||||
|     container_name: tika |     container_name: tika | ||||||
|     network_mode: host |     network_mode: host | ||||||
|   | |||||||
| @@ -1,17 +1,26 @@ | |||||||
| ############################################################################### |  | ||||||
| # Paperless-ngx settings                                                      # |  | ||||||
| ############################################################################### |  | ||||||
|  |  | ||||||
| # See http://docs.paperless-ngx.com/configuration/ for all available options. |  | ||||||
|  |  | ||||||
| # The UID and GID of the user used to run paperless in the container. Set this | # The UID and GID of the user used to run paperless in the container. Set this | ||||||
| # to your UID and GID on the host so that you have write access to the | # to your UID and GID on the host so that you have write access to the | ||||||
| # consumption directory. | # consumption directory. | ||||||
| #USERMAP_UID=1000 | #USERMAP_UID=1000 | ||||||
| #USERMAP_GID=1000 | #USERMAP_GID=1000 | ||||||
|  |  | ||||||
| # See the documentation linked above for all options. A few commonly adjusted settings | # Additional languages to install for text recognition, separated by a | ||||||
| # are provided below. | # whitespace. Note that this is | ||||||
|  | # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the | ||||||
|  | # language used for OCR. | ||||||
|  | # The container installs English, German, Italian, Spanish and French by | ||||||
|  | # default. | ||||||
|  | # See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster | ||||||
|  | # for available languages. | ||||||
|  | #PAPERLESS_OCR_LANGUAGES=tur ces | ||||||
|  |  | ||||||
|  | ############################################################################### | ||||||
|  | # Paperless-specific settings                                                 # | ||||||
|  | ############################################################################### | ||||||
|  |  | ||||||
|  | # All settings defined in the paperless.conf.example can be used here. The | ||||||
|  | # Docker setup does not use the configuration file. | ||||||
|  | # A few commonly adjusted settings are provided below. | ||||||
|  |  | ||||||
| # This is required if you will be exposing Paperless-ngx on a public domain | # This is required if you will be exposing Paperless-ngx on a public domain | ||||||
| # (if doing so please consider security measures such as reverse proxy) | # (if doing so please consider security measures such as reverse proxy) | ||||||
| @@ -21,17 +30,13 @@ | |||||||
| # be a very long sequence of random characters. You don't need to remember it. | # be a very long sequence of random characters. You don't need to remember it. | ||||||
| #PAPERLESS_SECRET_KEY=change-me | #PAPERLESS_SECRET_KEY=change-me | ||||||
|  |  | ||||||
| # Use this variable to set a timezone for the Paperless Docker containers. Defaults to UTC. | # Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC. | ||||||
| #PAPERLESS_TIME_ZONE=America/Los_Angeles | #PAPERLESS_TIME_ZONE=America/Los_Angeles | ||||||
|  |  | ||||||
| # The default language to use for OCR. Set this to the language most of your | # The default language to use for OCR. Set this to the language most of your | ||||||
| # documents are written in. | # documents are written in. | ||||||
| #PAPERLESS_OCR_LANGUAGE=eng | #PAPERLESS_OCR_LANGUAGE=eng | ||||||
|  |  | ||||||
| # Additional languages to install for text recognition, separated by a whitespace. | # Set if accessing paperless via a domain subpath e.g. https://domain.com/PATHPREFIX and using a reverse-proxy like traefik or nginx | ||||||
| # Note that this is different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines | #PAPERLESS_FORCE_SCRIPT_NAME=/PATHPREFIX | ||||||
| # the language used for OCR. | #PAPERLESS_STATIC_URL=/PATHPREFIX/static/ # trailing slash required | ||||||
| # The container installs English, German, Italian, Spanish and French by default. |  | ||||||
| # See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster |  | ||||||
| # for available languages. |  | ||||||
| #PAPERLESS_OCR_LANGUAGES=tur ces |  | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -38,7 +39,7 @@ services: | |||||||
|       - redisdata:/data |       - redisdata:/data | ||||||
|  |  | ||||||
|   db: |   db: | ||||||
|     image: docker.io/library/mariadb:11 |     image: docker.io/library/mariadb:10 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     volumes: |     volumes: | ||||||
|       - dbdata:/var/lib/mysql |       - dbdata:/var/lib/mysql | ||||||
| @@ -77,7 +78,7 @@ services: | |||||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 |       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||||
|  |  | ||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:8.17 |     image: docker.io/gotenberg/gotenberg:7.10 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     # The gotenberg chromium route is used to convert .eml files. We do not |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|     # want to allow external content like tracking pixels or even javascript. |     # want to allow external content like tracking pixels or even javascript. | ||||||
| @@ -87,7 +88,7 @@ services: | |||||||
|       - "--chromium-allow-list=file:///tmp/.*" |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
|  |  | ||||||
|   tika: |   tika: | ||||||
|     image: docker.io/apache/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |  | ||||||
| volumes: | volumes: | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -34,7 +35,7 @@ services: | |||||||
|       - redisdata:/data |       - redisdata:/data | ||||||
|  |  | ||||||
|   db: |   db: | ||||||
|     image: docker.io/library/mariadb:11 |     image: docker.io/library/mariadb:10 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     volumes: |     volumes: | ||||||
|       - dbdata:/var/lib/mysql |       - dbdata:/var/lib/mysql | ||||||
|   | |||||||
| @@ -19,8 +19,6 @@ | |||||||
| # | # | ||||||
| # - Open portainer Stacks list and click 'Add stack' | # - Open portainer Stacks list and click 'Add stack' | ||||||
| # - Paste the contents of this file and assign a name, e.g. 'paperless' | # - Paste the contents of this file and assign a name, e.g. 'paperless' | ||||||
| # - Upload 'docker-compose.env' by clicking on 'Load variables from .env file' |  | ||||||
| # - Modify the environment variables as needed |  | ||||||
| # - Click 'Deploy the stack' and wait for it to be deployed | # - Click 'Deploy the stack' and wait for it to be deployed | ||||||
| # - Open the list of containers, select paperless_webserver_1 | # - Open the list of containers, select paperless_webserver_1 | ||||||
| # - Click 'Console' and then 'Connect' to open the command line inside the container | # - Click 'Console' and then 'Connect' to open the command line inside the container | ||||||
| @@ -30,6 +28,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -38,7 +37,7 @@ services: | |||||||
|       - redisdata:/data |       - redisdata:/data | ||||||
|  |  | ||||||
|   db: |   db: | ||||||
|     image: docker.io/library/postgres:16 |     image: docker.io/library/postgres:15 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     volumes: |     volumes: | ||||||
|       - pgdata:/var/lib/postgresql/data |       - pgdata:/var/lib/postgresql/data | ||||||
| @@ -63,8 +62,28 @@ services: | |||||||
|     environment: |     environment: | ||||||
|       PAPERLESS_REDIS: redis://broker:6379 |       PAPERLESS_REDIS: redis://broker:6379 | ||||||
|       PAPERLESS_DBHOST: db |       PAPERLESS_DBHOST: db | ||||||
|     env_file: | # The UID and GID of the user used to run paperless in the container. Set this | ||||||
|       - stack.env | # to your UID and GID on the host so that you have write access to the | ||||||
|  | # consumption directory. | ||||||
|  |       USERMAP_UID: 1000 | ||||||
|  |       USERMAP_GID: 100 | ||||||
|  | # Additional languages to install for text recognition, separated by a | ||||||
|  | # whitespace. Note that this is | ||||||
|  | # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the | ||||||
|  | # language used for OCR. | ||||||
|  | # The container installs English, German, Italian, Spanish and French by | ||||||
|  | # default. | ||||||
|  | # See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster | ||||||
|  | # for available languages. | ||||||
|  |       #PAPERLESS_OCR_LANGUAGES: tur ces | ||||||
|  | # Adjust this key if you plan to make paperless available publicly. It should | ||||||
|  | # be a very long sequence of random characters. You don't need to remember it. | ||||||
|  |       #PAPERLESS_SECRET_KEY: change-me | ||||||
|  | # Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC. | ||||||
|  |       #PAPERLESS_TIME_ZONE: America/Los_Angeles | ||||||
|  | # The default language to use for OCR. Set this to the language most of your | ||||||
|  | # documents are written in. | ||||||
|  |       #PAPERLESS_OCR_LANGUAGE: eng | ||||||
|  |  | ||||||
| volumes: | volumes: | ||||||
|   data: |   data: | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -38,7 +39,7 @@ services: | |||||||
|       - redisdata:/data |       - redisdata:/data | ||||||
|  |  | ||||||
|   db: |   db: | ||||||
|     image: docker.io/library/postgres:16 |     image: docker.io/library/postgres:15 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     volumes: |     volumes: | ||||||
|       - pgdata:/var/lib/postgresql/data |       - pgdata:/var/lib/postgresql/data | ||||||
| @@ -71,7 +72,7 @@ services: | |||||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 |       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||||
|  |  | ||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:8.17 |     image: docker.io/gotenberg/gotenberg:7.10 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |  | ||||||
|     # The gotenberg chromium route is used to convert .eml files. We do not |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
| @@ -82,7 +83,7 @@ services: | |||||||
|       - "--chromium-allow-list=file:///tmp/.*" |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
|  |  | ||||||
|   tika: |   tika: | ||||||
|     image: docker.io/apache/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |  | ||||||
| volumes: | volumes: | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -34,7 +35,7 @@ services: | |||||||
|       - redisdata:/data |       - redisdata:/data | ||||||
|  |  | ||||||
|   db: |   db: | ||||||
|     image: docker.io/library/postgres:16 |     image: docker.io/library/postgres:15 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     volumes: |     volumes: | ||||||
|       - pgdata:/var/lib/postgresql/data |       - pgdata:/var/lib/postgresql/data | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
| @@ -59,7 +60,7 @@ services: | |||||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 |       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||||
|  |  | ||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:8.17 |     image: docker.io/gotenberg/gotenberg:7.10 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |  | ||||||
|     # The gotenberg chromium route is used to convert .eml files. We do not |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
| @@ -70,7 +71,7 @@ services: | |||||||
|       - "--chromium-allow-list=file:///tmp/.*" |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
|  |  | ||||||
|   tika: |   tika: | ||||||
|     image: docker.io/apache/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |  | ||||||
| volumes: | volumes: | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ | |||||||
| # For more extensive installation and update instructions, refer to the | # For more extensive installation and update instructions, refer to the | ||||||
| # documentation. | # documentation. | ||||||
|  |  | ||||||
|  | version: "3.4" | ||||||
| services: | services: | ||||||
|   broker: |   broker: | ||||||
|     image: docker.io/library/redis:7 |     image: docker.io/library/redis:7 | ||||||
|   | |||||||
| @@ -10,8 +10,8 @@ map_uidgid() { | |||||||
| 	local -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}} | 	local -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}} | ||||||
| 	if [[ ${usermap_new_uid} != "${usermap_original_uid}" || ${usermap_new_gid} != "${usermap_original_gid}" ]]; then | 	if [[ ${usermap_new_uid} != "${usermap_original_uid}" || ${usermap_new_gid} != "${usermap_original_gid}" ]]; then | ||||||
| 		echo "Mapping UID and GID for paperless:paperless to $usermap_new_uid:$usermap_new_gid" | 		echo "Mapping UID and GID for paperless:paperless to $usermap_new_uid:$usermap_new_gid" | ||||||
| 		usermod --non-unique --uid "${usermap_new_uid}" paperless | 		usermod -o -u "${usermap_new_uid}" paperless | ||||||
| 		groupmod --non-unique --gid "${usermap_new_gid}" paperless | 		groupmod -o -g "${usermap_new_gid}" paperless | ||||||
| 	fi | 	fi | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -42,7 +42,7 @@ custom_container_init() { | |||||||
| 		fi | 		fi | ||||||
|  |  | ||||||
| 		# Make sure custom init directory has files in it | 		# Make sure custom init directory has files in it | ||||||
| 		if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then | 		if [ -n "$(/bin/ls -A "${custom_script_dir}" 2>/dev/null)" ]; then | ||||||
| 			echo "[custom-init] files found in ${custom_script_dir} executing" | 			echo "[custom-init] files found in ${custom_script_dir} executing" | ||||||
| 			# Loop over files in the directory | 			# Loop over files in the directory | ||||||
| 			for SCRIPT in "${custom_script_dir}"/*; do | 			for SCRIPT in "${custom_script_dir}"/*; do | ||||||
| @@ -86,13 +86,13 @@ initialize() { | |||||||
| 		"${CONSUME_DIR}"; do | 		"${CONSUME_DIR}"; do | ||||||
| 		if [[ ! -d "${dir}" ]]; then | 		if [[ ! -d "${dir}" ]]; then | ||||||
| 			echo "Creating directory ${dir}" | 			echo "Creating directory ${dir}" | ||||||
| 			mkdir --parents --verbose "${dir}" | 			mkdir --parents "${dir}" | ||||||
| 		fi | 		fi | ||||||
| 	done | 	done | ||||||
|  |  | ||||||
| 	local -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}" | 	local -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}" | ||||||
| 	echo "Creating directory scratch directory ${tmp_dir}" | 	echo "Creating directory scratch directory ${tmp_dir}" | ||||||
| 	mkdir --parents --verbose "${tmp_dir}" | 	mkdir --parents "${tmp_dir}" | ||||||
|  |  | ||||||
| 	set +e | 	set +e | ||||||
| 	echo "Adjusting permissions of paperless files. This may take a while." | 	echo "Adjusting permissions of paperless files. This may take a while." | ||||||
| @@ -102,7 +102,7 @@ initialize() { | |||||||
| 		"${DATA_DIR}" \ | 		"${DATA_DIR}" \ | ||||||
| 		"${MEDIA_ROOT_DIR}" \ | 		"${MEDIA_ROOT_DIR}" \ | ||||||
| 		"${CONSUME_DIR}"; do | 		"${CONSUME_DIR}"; do | ||||||
| 		find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} + | 		find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown paperless:paperless {} + | ||||||
| 	done | 	done | ||||||
| 	set -e | 	set -e | ||||||
|  |  | ||||||
| @@ -122,44 +122,33 @@ install_languages() { | |||||||
| 	if [ ${#langs[@]} -eq 0 ]; then | 	if [ ${#langs[@]} -eq 0 ]; then | ||||||
| 		return | 		return | ||||||
| 	fi | 	fi | ||||||
|  | 	apt-get update | ||||||
|  |  | ||||||
| 	# Build list of packages to install |  | ||||||
| 	to_install=() |  | ||||||
| 	for lang in "${langs[@]}"; do | 	for lang in "${langs[@]}"; do | ||||||
| 		pkg="tesseract-ocr-$lang" | 		pkg="tesseract-ocr-$lang" | ||||||
|  |  | ||||||
| 		if dpkg --status "$pkg" &>/dev/null; then | 		if dpkg -s "$pkg" &>/dev/null; then | ||||||
| 			echo "Package $pkg already installed!" | 			echo "Package $pkg already installed!" | ||||||
| 			continue | 			continue | ||||||
| 		else |  | ||||||
| 			to_install+=("$pkg") |  | ||||||
| 		fi | 		fi | ||||||
| 	done |  | ||||||
|  |  | ||||||
| 	# Use apt only when we install packages |  | ||||||
| 	if [ ${#to_install[@]} -gt 0 ]; then |  | ||||||
| 		apt-get update |  | ||||||
|  |  | ||||||
| 		for pkg in "${to_install[@]}"; do |  | ||||||
|  |  | ||||||
| 		if ! apt-cache show "$pkg" &>/dev/null; then | 		if ! apt-cache show "$pkg" &>/dev/null; then | ||||||
| 				echo "Skipped $pkg: Package not found! :(" | 			echo "Package $pkg not found! :(" | ||||||
| 			continue | 			continue | ||||||
| 		fi | 		fi | ||||||
|  |  | ||||||
| 		echo "Installing package $pkg..." | 		echo "Installing package $pkg..." | ||||||
| 			if ! apt-get --assume-yes install "$pkg" &>/dev/null; then | 		if ! apt-get -y install "$pkg" &>/dev/null; then | ||||||
| 			echo "Could not install $pkg" | 			echo "Could not install $pkg" | ||||||
| 			exit 1 | 			exit 1 | ||||||
| 		fi | 		fi | ||||||
| 	done | 	done | ||||||
| 	fi |  | ||||||
| } | } | ||||||
|  |  | ||||||
| echo "Paperless-ngx docker container starting..." | echo "Paperless-ngx docker container starting..." | ||||||
|  |  | ||||||
| gosu_cmd=(gosu paperless) | gosu_cmd=(gosu paperless) | ||||||
| if [ "$(id --user)" == "$(id --user paperless)" ]; then | if [ "$(id -u)" == "$(id -u paperless)" ]; then | ||||||
| 	gosu_cmd=() | 	gosu_cmd=() | ||||||
| fi | fi | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								docker/docker-prepare.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										118
									
								
								docker/docker-prepare.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | wait_for_postgres() { | ||||||
|  | 	local attempt_num=1 | ||||||
|  | 	local -r max_attempts=5 | ||||||
|  |  | ||||||
|  | 	echo "Waiting for PostgreSQL to start..." | ||||||
|  |  | ||||||
|  | 	local -r host="${PAPERLESS_DBHOST:-localhost}" | ||||||
|  | 	local -r port="${PAPERLESS_DBPORT:-5432}" | ||||||
|  |  | ||||||
|  | 	# Disable warning, host and port can't have spaces | ||||||
|  | 	# shellcheck disable=SC2086 | ||||||
|  | 	while [ ! "$(pg_isready -h ${host} -p ${port})" ]; do | ||||||
|  |  | ||||||
|  | 		if [ $attempt_num -eq $max_attempts ]; then | ||||||
|  | 			echo "Unable to connect to database." | ||||||
|  | 			exit 1 | ||||||
|  | 		else | ||||||
|  | 			echo "Attempt $attempt_num failed! Trying again in 5 seconds..." | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  | 		attempt_num=$(("$attempt_num" + 1)) | ||||||
|  | 		sleep 5 | ||||||
|  | 	done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | wait_for_mariadb() { | ||||||
|  | 	echo "Waiting for MariaDB to start..." | ||||||
|  |  | ||||||
|  | 	local -r host="${PAPERLESS_DBHOST:=localhost}" | ||||||
|  | 	local -r port="${PAPERLESS_DBPORT:=3306}" | ||||||
|  |  | ||||||
|  | 	local attempt_num=1 | ||||||
|  | 	local -r max_attempts=5 | ||||||
|  |  | ||||||
|  | 	# Disable warning, host and port can't have spaces | ||||||
|  | 	# shellcheck disable=SC2086 | ||||||
|  | 	while ! true > /dev/tcp/$host/$port; do | ||||||
|  |  | ||||||
|  | 		if [ $attempt_num -eq $max_attempts ]; then | ||||||
|  | 			echo "Unable to connect to database." | ||||||
|  | 			exit 1 | ||||||
|  | 		else | ||||||
|  | 			echo "Attempt $attempt_num failed! Trying again in 5 seconds..." | ||||||
|  |  | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  | 		attempt_num=$(("$attempt_num" + 1)) | ||||||
|  | 		sleep 5 | ||||||
|  | 	done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | wait_for_redis() { | ||||||
|  | 	# We use a Python script to send the Redis ping | ||||||
|  | 	# instead of installing redis-tools just for 1 thing | ||||||
|  | 	if ! python3 /sbin/wait-for-redis.py; then | ||||||
|  | 		exit 1 | ||||||
|  | 	fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | migrations() { | ||||||
|  | 	( | ||||||
|  | 		# flock is in place to prevent multiple containers from doing migrations | ||||||
|  | 		# simultaneously. This also ensures that the db is ready when the command | ||||||
|  | 		# of the current container starts. | ||||||
|  | 		flock 200 | ||||||
|  | 		echo "Apply database migrations..." | ||||||
|  | 		python3 manage.py migrate --skip-checks --no-input | ||||||
|  | 	) 200>"${DATA_DIR}/migration_lock" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | django_checks() { | ||||||
|  | 	# Explicitly run the Django system checks | ||||||
|  | 	echo "Running Django checks" | ||||||
|  | 	python3 manage.py check | ||||||
|  | } | ||||||
|  |  | ||||||
|  | search_index() { | ||||||
|  |  | ||||||
|  | 	local -r index_version=9 | ||||||
|  | 	local -r index_version_file=${DATA_DIR}/.index_version | ||||||
|  |  | ||||||
|  | 	if [[ (! -f "${index_version_file}") || $(<"${index_version_file}") != "$index_version" ]]; then | ||||||
|  | 		echo "Search index out of date. Updating..." | ||||||
|  | 		python3 manage.py document_index reindex --no-progress-bar | ||||||
|  | 		echo ${index_version} | tee "${index_version_file}" >/dev/null | ||||||
|  | 	fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | superuser() { | ||||||
|  | 	if [[ -n "${PAPERLESS_ADMIN_USER}" ]]; then | ||||||
|  | 		python3 manage.py manage_superuser | ||||||
|  | 	fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | do_work() { | ||||||
|  | 	if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then | ||||||
|  | 		wait_for_mariadb | ||||||
|  | 	elif [[ -n "${PAPERLESS_DBHOST}" ]]; then | ||||||
|  | 		wait_for_postgres | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | 	wait_for_redis | ||||||
|  |  | ||||||
|  | 	migrations | ||||||
|  |  | ||||||
|  | 	django_checks | ||||||
|  |  | ||||||
|  | 	search_index | ||||||
|  |  | ||||||
|  | 	superuser | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | do_work | ||||||
							
								
								
									
										42
									
								
								docker/env-from-file.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								docker/env-from-file.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | # Scans the environment variables for those with the suffix _FILE | ||||||
|  | # When located, checks the file exists, and exports the contents | ||||||
|  | # of the file as the same name, minus the suffix | ||||||
|  | # This allows the use of Docker secrets or mounted files | ||||||
|  | # to fill in any of the settings configurable via environment | ||||||
|  | # variables | ||||||
|  |  | ||||||
|  | set -eu | ||||||
|  |  | ||||||
|  | for line in $(printenv) | ||||||
|  | do | ||||||
|  | 	# Extract the name of the environment variable | ||||||
|  | 	env_name=${line%%=*} | ||||||
|  | 	# Check if it starts with "PAPERLESS_" and ends in "_FILE" | ||||||
|  | 	if [[ ${env_name} == PAPERLESS_*_FILE ]]; then | ||||||
|  | 		# This should have been named different.. | ||||||
|  | 		if [[ ${env_name} == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" ]]; then | ||||||
|  | 			continue | ||||||
|  | 		fi | ||||||
|  | 		# Extract the value of the environment | ||||||
|  | 		env_value=${line#*=} | ||||||
|  |  | ||||||
|  | 		# Check the file exists | ||||||
|  | 		if [[ -f ${env_value} ]]; then | ||||||
|  |  | ||||||
|  | 			# Trim off the _FILE suffix | ||||||
|  | 			non_file_env_name=${env_name%"_FILE"} | ||||||
|  | 			echo "Setting ${non_file_env_name} from file" | ||||||
|  |  | ||||||
|  | 			# Reads the value from th file | ||||||
|  | 			val="$(< "${!env_name}")" | ||||||
|  |  | ||||||
|  | 			# Sets the normal name to the read file contents | ||||||
|  | 			export "${non_file_env_name}"="${val}" | ||||||
|  |  | ||||||
|  | 		else | ||||||
|  | 			echo "File ${env_value} referenced by ${env_name} doesn't exist" | ||||||
|  | 		fi | ||||||
|  | 	fi | ||||||
|  | done | ||||||
							
								
								
									
										12
									
								
								docker/flower-conditional.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								docker/flower-conditional.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | echo "Checking if we should start flower..." | ||||||
|  |  | ||||||
|  | if [[ -n  "${PAPERLESS_ENABLE_FLOWER}" ]]; then | ||||||
|  | 	# Small delay to allow celery to be up first | ||||||
|  | 	echo "Starting flower in 5s" | ||||||
|  | 	sleep 5 | ||||||
|  | 	celery --app paperless flower --conf=/usr/src/paperless/src/paperless/flowerconfig.py | ||||||
|  | else | ||||||
|  | 	echo "Not starting flower" | ||||||
|  | fi | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 30 KiB | 
| @@ -1,7 +1,5 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
|  |  | ||||||
| # Run this script to generate the management commands again (for example if a new command is create or the template is updated) |  | ||||||
|  |  | ||||||
| set -eu | set -eu | ||||||
|  |  | ||||||
| for command in decrypt_documents \ | for command in decrypt_documents \ | ||||||
| @@ -16,11 +14,9 @@ for command in decrypt_documents \ | |||||||
| 	document_thumbnails \ | 	document_thumbnails \ | ||||||
| 	document_sanity_checker \ | 	document_sanity_checker \ | ||||||
| 	document_fuzzy_match \ | 	document_fuzzy_match \ | ||||||
| 	manage_superuser \ | 	manage_superuser; | ||||||
| 	convert_mariadb_uuid \ |  | ||||||
| 	prune_audit_logs; |  | ||||||
| do | do | ||||||
| 	echo "installing $command..." | 	echo "installing $command..." | ||||||
| 	sed "s/management_command/$command/g" management_script.sh >"$PWD/rootfs/usr/local/bin/$command" | 	sed "s/management_command/$command/g" management_script.sh > /usr/local/bin/$command | ||||||
| 	chmod +x "$PWD/rootfs/usr/local/bin/$command" | 	chmod +x /usr/local/bin/$command | ||||||
| done | done | ||||||
|   | |||||||
| @@ -1,13 +1,17 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash | #!/usr/bin/env bash | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| set -e | set -e | ||||||
|  |  | ||||||
| cd "${PAPERLESS_SRC_DIR}" | cd /usr/src/paperless/src/ | ||||||
|  | # This ensures environment is setup | ||||||
|  | # shellcheck disable=SC1091 | ||||||
|  | source /sbin/env-from-file.sh | ||||||
|  |  | ||||||
| if [[ $(id -u) == 0 ]]; then | if [[ $(id -u) == 0 ]] ; | ||||||
| 	s6-setuidgid paperless python3 manage.py management_command "$@" | then | ||||||
| elif [[ $(id -un) == "paperless" ]]; then | 	gosu paperless python3 manage.py management_command "$@" | ||||||
|  | elif [[ $(id -un) == "paperless" ]] ; | ||||||
|  | then | ||||||
| 	python3 manage.py management_command "$@" | 	python3 manage.py management_command "$@" | ||||||
| else | else | ||||||
| 	echo "Unknown user." | 	echo "Unknown user." | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								docker/paperless_cmd.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								docker/paperless_cmd.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | SUPERVISORD_WORKING_DIR="${PAPERLESS_SUPERVISORD_WORKING_DIR:-$PWD}" | ||||||
|  | rootless_args=() | ||||||
|  | if [ "$(id -u)" == "$(id -u paperless)" ]; then | ||||||
|  | 	rootless_args=( | ||||||
|  | 		--user | ||||||
|  | 		paperless | ||||||
|  | 		--logfile | ||||||
|  | 		"${SUPERVISORD_WORKING_DIR}/supervisord.log" | ||||||
|  | 		--pidfile | ||||||
|  | 		"${SUPERVISORD_WORKING_DIR}/supervisord.pid" | ||||||
|  | 	) | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | exec /usr/local/bin/supervisord -c /etc/supervisord.conf "${rootless_args[@]}" | ||||||
| @@ -1,8 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
| declare -r log_prefix="[init-complete]" |  | ||||||
| declare -r end_time=$(date +%s) |  | ||||||
| declare -r start_time=${PAPERLESS_START_TIME_S} |  | ||||||
|  |  | ||||||
| echo "${log_prefix} paperless-ngx docker container init completed in $(($end_time-$start_time)) seconds" |  | ||||||
| echo "${log_prefix} Starting services" |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-complete/run |  | ||||||
| @@ -1,44 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[custom-init]" |  | ||||||
|  |  | ||||||
| # Mostly borrowed from the LinuxServer.io base image |  | ||||||
| # https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d |  | ||||||
| declare -r custom_script_dir="/custom-cont-init.d" |  | ||||||
|  |  | ||||||
| # Tamper checking. |  | ||||||
| # Don't run files which are owned by anyone except root |  | ||||||
| # Don't run files which are writeable by others |  | ||||||
| if [ -d "${custom_script_dir}" ]; then |  | ||||||
| 	if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then |  | ||||||
| 		echo "${log_prefix} **** Potential tampering with custom scripts detected ****" |  | ||||||
| 		echo "${log_prefix} **** The folder '${custom_script_dir}' must be owned by root ****" |  | ||||||
| 		exit 0 |  | ||||||
| 	fi |  | ||||||
| 	if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then |  | ||||||
| 		echo "${log_prefix} **** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****" |  | ||||||
| 		echo "${log_prefix} **** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****" |  | ||||||
| 		exit 0 |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	# Make sure custom init directory has files in it |  | ||||||
| 	if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then |  | ||||||
| 		echo "${log_prefix} files found in ${custom_script_dir} executing" |  | ||||||
| 		# Loop over files in the directory |  | ||||||
| 		for SCRIPT in "${custom_script_dir}"/*; do |  | ||||||
| 			NAME="$(basename "${SCRIPT}")" |  | ||||||
| 			if [ -f "${SCRIPT}" ]; then |  | ||||||
| 				echo "${log_prefix} ${NAME}: executing..." |  | ||||||
| 				/command/with-contenv /bin/bash "${SCRIPT}" |  | ||||||
| 				echo "${log_prefix} ${NAME}: exited $?" |  | ||||||
| 			elif [ ! -f "${SCRIPT}" ]; then |  | ||||||
| 				echo "${log_prefix} ${NAME}: is not a file" |  | ||||||
| 			fi |  | ||||||
| 		done |  | ||||||
| 	else |  | ||||||
| 		echo "${log_prefix} no custom files found exiting..." |  | ||||||
| 	fi |  | ||||||
| else |  | ||||||
| 	echo "${log_prefix} ${custom_script_dir} doesn't exist, nothing to do" |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-custom-init/run |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[env-init]" |  | ||||||
|  |  | ||||||
| echo "${log_prefix} Checking for environment from files" |  | ||||||
|  |  | ||||||
| if find /run/s6/container_environment/*"_FILE" -maxdepth 1 > /dev/null 2>&1; then |  | ||||||
| 	for FILENAME in /run/s6/container_environment/*; do |  | ||||||
| 		if [[ "${FILENAME##*/}" == PAPERLESS_*_FILE ]]; then |  | ||||||
| 			# This should have been named different.. |  | ||||||
| 			if [[ ${FILENAME} == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" || ${FILENAME} == "PAPERLESS_MODEL_FILE" ]]; then |  | ||||||
| 				continue |  | ||||||
| 			fi |  | ||||||
| 			SECRETFILE=$(cat "${FILENAME}") |  | ||||||
| 			# Check the file exists |  | ||||||
| 			if [[ -f ${SECRETFILE} ]]; then |  | ||||||
| 				# Trim off trailing _FILE |  | ||||||
| 				FILESTRIP=${FILENAME//_FILE/} |  | ||||||
| 				# Set environment variable |  | ||||||
| 				cat "${SECRETFILE}" > "${FILESTRIP}" |  | ||||||
| 				echo "${log_prefix} ${FILESTRIP##*/} set from ${FILENAME##*/}" |  | ||||||
| 			else |  | ||||||
| 				echo "${log_prefix} cannot find secret in ${FILENAME##*/}" |  | ||||||
| 			fi |  | ||||||
| 		fi |  | ||||||
| 	done |  | ||||||
| else |  | ||||||
| 		echo "${log_prefix} No *_FILE environment found" |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-env-file/run |  | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[init-folders]" |  | ||||||
|  |  | ||||||
| declare -r export_dir="/usr/src/paperless/export" |  | ||||||
| declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}" |  | ||||||
| declare -r media_root_dir="${PAPERLESS_MEDIA_ROOT:-/usr/src/paperless/media}" |  | ||||||
| declare -r consume_dir="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}" |  | ||||||
| declare -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}" |  | ||||||
|  |  | ||||||
| echo "${log_prefix} Checking for folder existence" |  | ||||||
|  |  | ||||||
| for dir in \ |  | ||||||
| 	"${export_dir}" \ |  | ||||||
| 	"${data_dir}" "${data_dir}/index" \ |  | ||||||
| 	"${media_root_dir}" "${media_root_dir}/documents" "${media_root_dir}/documents/originals" "${media_root_dir}/documents/thumbnails" \ |  | ||||||
| 	"${consume_dir}" \ |  | ||||||
| 	"${tmp_dir}"; do |  | ||||||
| 	if [[ ! -d "${dir}" ]]; then |  | ||||||
| 		mkdir --parents --verbose "${dir}" |  | ||||||
| 	fi |  | ||||||
| done |  | ||||||
|  |  | ||||||
| echo "${log_prefix} Adjusting file and folder permissions" |  | ||||||
| for dir in \ |  | ||||||
| 	"${export_dir}" \ |  | ||||||
| 	"${data_dir}" \ |  | ||||||
| 	"${media_root_dir}" \ |  | ||||||
| 	"${consume_dir}" \ |  | ||||||
| 	"${tmp_dir}"; do |  | ||||||
| 	find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} + |  | ||||||
| done |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-folders/run |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
| declare -r log_prefix="[init-migrations]" |  | ||||||
| declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}" |  | ||||||
|  |  | ||||||
| ( |  | ||||||
| 	# flock is in place to prevent multiple containers from doing migrations |  | ||||||
| 	# simultaneously. This also ensures that the db is ready when the command |  | ||||||
| 	# of the current container starts. |  | ||||||
| 	flock 200 |  | ||||||
| 	echo "${log_prefix} Apply database migrations..." |  | ||||||
| 	cd "${PAPERLESS_SRC_DIR}" |  | ||||||
|  |  | ||||||
| 	if [[ -n "${USER_IS_NON_ROOT}" ]]; then |  | ||||||
| 		exec python3 manage.py migrate --skip-checks --no-input |  | ||||||
| 	else |  | ||||||
| 		exec s6-setuidgid paperless python3 manage.py migrate --skip-checks --no-input |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| ) 200>"${data_dir}/migration_lock" |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-migrations/run |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
| declare -r log_prefix="[init-user]" |  | ||||||
|  |  | ||||||
| declare -r usermap_original_uid=$(id -u paperless) |  | ||||||
| declare -r usermap_original_gid=$(id -g paperless) |  | ||||||
| declare -r usermap_new_uid=${USERMAP_UID:-$usermap_original_uid} |  | ||||||
| declare -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}} |  | ||||||
|  |  | ||||||
| if [[ ${usermap_new_uid} != "${usermap_original_uid}" ]]; then |  | ||||||
| 	echo "${log_prefix} Mapping UID for paperless to $usermap_new_uid" |  | ||||||
| 	usermod --non-unique --uid "${usermap_new_uid}" paperless |  | ||||||
| else |  | ||||||
| 	echo "${log_prefix} No UID changes for paperless" |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [[ ${usermap_new_gid} != "${usermap_original_gid}" ]]; then |  | ||||||
| 	echo "${log_prefix} Mapping GID for paperless to $usermap_new_gid" |  | ||||||
| 	groupmod --non-unique --gid "${usermap_new_gid}" paperless |  | ||||||
| else |  | ||||||
| 	echo "${log_prefix} No GID changes for paperless" |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-modify-user/run |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[init-index]" |  | ||||||
|  |  | ||||||
| declare -r index_version=9 |  | ||||||
| declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}" |  | ||||||
| declare -r index_version_file="${data_dir}/.index_version" |  | ||||||
|  |  | ||||||
| update_index () { |  | ||||||
| 	echo "${log_prefix} Search index out of date. Updating..." |  | ||||||
| 	cd "${PAPERLESS_SRC_DIR}" |  | ||||||
| 	if [[ -n "${USER_IS_NON_ROOT}" ]]; then |  | ||||||
| 		python3 manage.py document_index reindex --no-progress-bar |  | ||||||
| 		echo ${index_version} | tee "${index_version_file}" > /dev/null |  | ||||||
| 	else |  | ||||||
| 		s6-setuidgid paperless python3 manage.py document_index reindex --no-progress-bar |  | ||||||
| 		echo ${index_version} | s6-setuidgid paperless tee "${index_version_file}" > /dev/null |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| if [[ (! -f "${index_version_file}") ]]; then |  | ||||||
| 	echo "${log_prefix} No index version file found" |  | ||||||
| 	update_index |  | ||||||
| elif [[ $(<"${index_version_file}") != "$index_version" ]]; then |  | ||||||
| 	echo "${log_prefix} index version updated" |  | ||||||
| 	update_index |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-search-index/run |  | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[init-start]" |  | ||||||
|  |  | ||||||
| echo "${log_prefix} paperless-ngx docker container starting..." |  | ||||||
|  |  | ||||||
| # Set some directories into environment for other steps to access via environment |  | ||||||
| # Sort of like variables for later |  | ||||||
| printf "/usr/src/paperless/src" > /var/run/s6/container_environment/PAPERLESS_SRC_DIR |  | ||||||
| echo $(date +%s) > /var/run/s6/container_environment/PAPERLESS_START_TIME_S |  | ||||||
|  |  | ||||||
| # Check if we're starting as a non-root user |  | ||||||
| if [ $(id -u) == $(id -u paperless) ]; then |  | ||||||
| 	printf "true" > /var/run/s6/container_environment/USER_IS_NON_ROOT |  | ||||||
| 	echo "${log_prefix}  paperless-ngx docker container running under a user" |  | ||||||
| else |  | ||||||
| 	echo "${log_prefix}  paperless-ngx docker container starting init as root" |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-start/run |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| #!/command/with-contenv /usr/bin/bash |  | ||||||
| # shellcheck shell=bash |  | ||||||
|  |  | ||||||
| declare -r log_prefix="[init-superuser]" |  | ||||||
|  |  | ||||||
| if [[ -n "${PAPERLESS_ADMIN_USER}" ]]; then |  | ||||||
| 	echo "${log_prefix} Creating superuser..." |  | ||||||
| 	cd "${PAPERLESS_SRC_DIR}" |  | ||||||
|  |  | ||||||
| 	if [[ -n "${USER_IS_NON_ROOT}" ]]; then |  | ||||||
| 		python3 manage.py manage_superuser |  | ||||||
| 	else |  | ||||||
| 		s6-setuidgid paperless python3 manage.py manage_superuser |  | ||||||
| 	fi |  | ||||||
|  |  | ||||||
| 	echo "${log_prefix} Superuser creation done" |  | ||||||
|  |  | ||||||
| else |  | ||||||
| 	echo "${log_prefix} Not creating superuser" |  | ||||||
| fi |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| oneshot |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| /etc/s6-overlay/s6-rc.d/init-superuser/run |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user