mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			4c1c4a7130
			...
			feature-re
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ec12e71487 | ||
|   | 62b470f691 | ||
|   | a2e4977201 | ||
|   | 0fcd69b739 | ||
|   | af1c64e969 | ||
|   | 85c661dff2 | ||
|   | 3a7eee2c2e | ||
|   | bc4d3925cc | 
							
								
								
									
										16
									
								
								.codecov.yml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								.codecov.yml
									
									
									
									
									
								
							| @@ -1,18 +1,18 @@ | ||||
| codecov: | ||||
|   require_ci_to_pass: true | ||||
|   # https://docs.codecov.com/docs/components | ||||
| component_management: | ||||
|   individual_components: | ||||
|     - component_id: backend | ||||
| # https://docs.codecov.com/docs/flags#recommended-automatic-flag-management | ||||
| # Require each flag to have 1 upload before notification | ||||
| flag_management: | ||||
|   individual_flags: | ||||
|     - name: backend | ||||
|       paths: | ||||
|         - src/** | ||||
|     - component_id: frontend | ||||
|         - src/ | ||||
|     - name: frontend | ||||
|       paths: | ||||
|         - src-ui/** | ||||
|         - src-ui/ | ||||
| # https://docs.codecov.com/docs/pull-request-comments | ||||
| # codecov will only comment if coverage changes | ||||
| comment: | ||||
|   layout: "header, diff, components, flags, files" | ||||
|   require_changes: true | ||||
|   # https://docs.codecov.com/docs/javascript-bundle-analysis | ||||
|   require_bundle_changes: true | ||||
|   | ||||
| @@ -76,15 +76,18 @@ RUN set -eux \ | ||||
|     && apt-get update \ | ||||
|     && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} | ||||
|  | ||||
| ARG PYTHON_PACKAGES="ca-certificates" | ||||
| 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} | ||||
|  | ||||
| COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv | ||||
|  | ||||
| RUN set -eux \ | ||||
|   && echo "Installing pre-built updates" \ | ||||
|     && echo "Installing qpdf ${QPDF_VERSION}" \ | ||||
| @@ -120,15 +123,13 @@ RUN set -eux \ | ||||
| WORKDIR /usr/src/paperless/src/docker/ | ||||
|  | ||||
| COPY [ \ | ||||
|   "docker/rootfs/etc/ImageMagick-6/paperless-policy.xml", \ | ||||
|   "docker/imagemagick-policy.xml", \ | ||||
|   "./" \ | ||||
| ] | ||||
|  | ||||
| RUN set -eux \ | ||||
|   && echo "Configuring ImageMagick" \ | ||||
|     && mv paperless-policy.xml /etc/ImageMagick-6/policy.xml | ||||
|  | ||||
| COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv | ||||
|     && mv imagemagick-policy.xml /etc/ImageMagick-6/policy.xml | ||||
|  | ||||
| # Packages needed only for building a few quick Python | ||||
| # dependencies | ||||
| @@ -139,10 +140,11 @@ ARG BUILD_PACKAGES="\ | ||||
|   libpq-dev \ | ||||
|   # https://github.com/PyMySQL/mysqlclient#linux | ||||
|   default-libmysqlclient-dev \ | ||||
|   pkg-config" | ||||
|   pkg-config \ | ||||
|   pre-commit" | ||||
|  | ||||
| # hadolint ignore=DL3042 | ||||
| RUN --mount=type=cache,target=/root/.cache/uv,id=pip-cache \ | ||||
| RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \ | ||||
|   set -eux \ | ||||
|   && echo "Installing build system packages" \ | ||||
|     && apt-get update \ | ||||
| @@ -167,6 +169,9 @@ RUN set -eux \ | ||||
|     && 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", \ | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| # Paperless-ngx Development Environment | ||||
| # Paperless NGX Development Environment | ||||
|  | ||||
| ## Overview | ||||
|  | ||||
| Welcome to the Paperless-ngx development environment! This setup uses VSCode DevContainers to provide a consistent and seamless development experience. | ||||
| Welcome to the Paperless NGX development environment! This setup uses VSCode DevContainers to provide a consistent and seamless development experience. | ||||
|  | ||||
| ### What are DevContainers? | ||||
|  | ||||
| @@ -17,7 +17,7 @@ DevContainers are a feature in VSCode that allows you to develop within a Docker | ||||
|  | ||||
| ## DevContainer Setup | ||||
|  | ||||
| The DevContainer configuration provides up all the necessary services for Paperless-ngx, including: | ||||
| The DevContainer configuration provides up all the necessary services for Paperless NGX, including: | ||||
|  | ||||
| - Redis | ||||
| - Gotenberg | ||||
| @@ -36,7 +36,7 @@ The setup includes debugging configurations (`launch.json`) and tasks (`tasks.js | ||||
| - **Maintenance Tasks:** | ||||
|   - Create superuser | ||||
|   - Run migrations | ||||
|   - Recreate virtual environment (`.venv` with `uv`) | ||||
|   - Recreate virtual environment (`.venv` with pipenv) | ||||
|   - Compile frontend assets | ||||
|  | ||||
| ## Getting Started | ||||
| @@ -85,7 +85,7 @@ Once the DevContainer is up and running, perform the following steps: | ||||
|  | ||||
| You can start and debug backend services either as debugging sessions via `launch.json` or as tasks. | ||||
|  | ||||
| #### Using `launch.json` | ||||
| #### Using `launch.json`: | ||||
|  | ||||
| 1. Press `F5` or go to the **Run and Debug** view in VSCode. | ||||
| 2. Select the desired configuration: | ||||
| @@ -93,7 +93,7 @@ You can start and debug backend services either as debugging sessions via `launc | ||||
|    - `Document Consumer` | ||||
|    - `Celery` | ||||
|  | ||||
| #### Using Tasks | ||||
| #### Using Tasks: | ||||
|  | ||||
| 1. Open the command palette: | ||||
|    - **Windows/Linux**: `Ctrl+Shift+P` | ||||
| @@ -108,7 +108,7 @@ You can start and debug backend services either as debugging sessions via `launc | ||||
|  | ||||
| Additional tasks are available for common maintenance operations: | ||||
|  | ||||
| - **Recreate .venv**: For setting up the virtual environment using `uv`. | ||||
| - **Recreate .venv**: For setting up the virtual environment using pipenv. | ||||
| - **Migrate Database**: To apply database migrations. | ||||
| - **Create Superuser**: To create an admin user for the application. | ||||
|  | ||||
|   | ||||
| @@ -3,26 +3,14 @@ | ||||
|     "dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml", | ||||
|     "service": "paperless-development", | ||||
|     "workspaceFolder": "/usr/src/paperless/paperless-ngx", | ||||
|     "postCreateCommand": "/bin/bash -c 'uv sync --group dev && uv run pre-commit install'", | ||||
|     "postCreateCommand": "/bin/bash -c pre-commit install && pipenv install --dev", | ||||
|     "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 | ||||
|           } | ||||
|             "extensions": [ | ||||
|               "mhutchie.git-graph", | ||||
|               "ms-python.python" | ||||
|             ] | ||||
|         } | ||||
|       }, | ||||
|       "remoteUser": "paperless" | ||||
|     } | ||||
|     }, | ||||
|     "remoteUser": "paperless" | ||||
|   } | ||||
|   | ||||
| @@ -27,7 +27,7 @@ services: | ||||
|     image: docker.io/library/redis:7 | ||||
|     restart: unless-stopped | ||||
|     volumes: | ||||
|       - ./redisdata:/data | ||||
|       - redisdata:/data | ||||
|  | ||||
|   # No ports need to be exposed; the VSCode DevContainer plugin manages them. | ||||
|   paperless-development: | ||||
| @@ -43,16 +43,14 @@ services: | ||||
|     volumes: | ||||
|       - ..:/usr/src/paperless/paperless-ngx:delegated | ||||
|       - ../.devcontainer/vscode:/usr/src/paperless/paperless-ngx/.vscode:delegated # VSCode config files | ||||
|       - virtualenv:/usr/src/paperless/paperless-ngx/.venv # Virtual environment persisted in volume | ||||
|       - pipenv:/usr/src/paperless/paperless-ngx/.venv # Pipenv environment persisted in volume | ||||
|       - /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 | ||||
|       - data:/usr/src/paperless/paperless-ngx/data | ||||
|       - media:/usr/src/paperless/paperless-ngx/media | ||||
|     environment: | ||||
|       PAPERLESS_REDIS: redis://broker:6379 | ||||
|       PAPERLESS_TIKA_ENABLED: 1 | ||||
| @@ -65,7 +63,7 @@ services: | ||||
|     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 | ||||
|     image: docker.io/gotenberg/gotenberg:7.10 | ||||
|     restart: unless-stopped | ||||
|  | ||||
|     # The Gotenberg Chromium route is used to convert .eml files. We do not | ||||
| @@ -83,4 +81,4 @@ volumes: | ||||
|   data: | ||||
|   media: | ||||
|   redisdata: | ||||
|   virtualenv: | ||||
|   pipenv: | ||||
|   | ||||
| @@ -2,57 +2,42 @@ | ||||
|     "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", | ||||
|             "name": "manage.py runserver", | ||||
|             "type": "python", | ||||
|             "request": "launch", | ||||
|             "program": "${workspaceFolder}/src/manage.py", | ||||
|             "args": [ | ||||
|                 "runserver" | ||||
|             ], | ||||
|             "django": true, | ||||
|             "console": "integratedTerminal", | ||||
|             "env": { | ||||
|                 "PYTHONPATH": "${workspaceFolder}/src" | ||||
|             }, | ||||
|             "python": "${workspaceFolder}/.venv/bin/python" | ||||
|             "justMyCode": true, | ||||
|             "args": ["runserver"], | ||||
|             "django": true | ||||
|         }, | ||||
|         { | ||||
|             "name": "Debug: Consumer Service (manage.py document_consumer)", | ||||
| 						"description": "Debug the Consumer Service which processes files from a directory", | ||||
|             "name": "manage.py document_consumer", | ||||
|             "type": "python", | ||||
|             "request": "launch", | ||||
|             "program": "${workspaceFolder}/src/manage.py", | ||||
|             "args": [ | ||||
|                 "document_consumer" | ||||
|             ], | ||||
|             "django": true, | ||||
|             "console": "integratedTerminal", | ||||
|             "justMyCode": true, | ||||
|             "args": ["document_consumer"], | ||||
|             "django": true | ||||
|         }, | ||||
|         { | ||||
|             "name": "celery", | ||||
|             "type": "python", | ||||
|             "cwd": "${workspaceFolder}/src", | ||||
|             "request": "launch", | ||||
|             "module": "celery", | ||||
|             "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" | ||||
|               }, | ||||
|             "args": [ | ||||
|                 "-A", | ||||
|                 "paperless", | ||||
|                 "worker", | ||||
|                 "-l", | ||||
|                 "DEBUG" | ||||
|             ] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -1,223 +1,136 @@ | ||||
| { | ||||
| 	"version": "2.0.0", | ||||
| 	"tasks": [ | ||||
| 		{ | ||||
| 			"label": "Start: Celery Worker", | ||||
| 			"description": "Start the Celery Worker which processes background and consume tasks", | ||||
| 			"type": "shell", | ||||
| 			"command": "uv 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": "manage.py document_consumer", | ||||
| 		"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" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"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": "uv 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": "uv 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": "uv 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": "uv run mkdocs build --config-file mkdocs.yml && uv 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": "uv 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/* || uv 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)" | ||||
| 			] | ||||
| 		"options": { | ||||
| 			"cwd": "${workspaceFolder}/src" | ||||
| 		} | ||||
|  | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": "manage.py runserver", | ||||
| 			"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", | ||||
| 		"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: manage.py createsuperuser", | ||||
| 		"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": "compile frontend", | ||||
| 		"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": "Maintenance: recreate .venv", | ||||
| 		"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": "Celery Worker", | ||||
| 		"type": "shell", | ||||
| 		"command": "pipenv run celery --app paperless worker -l DEBUG", | ||||
| 		"group": { | ||||
| 		  "kind": "build", | ||||
| 		  "isDefault": true | ||||
| 		}, | ||||
| 		"presentation": { | ||||
| 			"echo": true, | ||||
| 			"reveal": "always", | ||||
| 			"focus": true, | ||||
| 			"panel": "shared", | ||||
| 			"showReuseMessage": false, | ||||
| 			"clear": true, | ||||
| 			"revealProblems": "onProblem" | ||||
| 		}, | ||||
| 		"options": { | ||||
| 			"cwd": "${workspaceFolder}/src" | ||||
| 		} | ||||
| 	  } | ||||
| 	] | ||||
| } | ||||
|   } | ||||
|   | ||||
| @@ -26,5 +26,3 @@ | ||||
| ./dist | ||||
| ./scripts | ||||
| ./resources | ||||
| # Other stuff | ||||
| **/*.drawio.png | ||||
|   | ||||
| @@ -27,6 +27,9 @@ indent_style = space | ||||
| [*.md] | ||||
| indent_style = space | ||||
|  | ||||
| [Pipfile.lock] | ||||
| indent_style = space | ||||
|  | ||||
| # Tests don't get a line width restriction.  It's still a good idea to follow | ||||
| # the 79 character rule, but in the interests of clarity, tests often need to | ||||
| # violate it. | ||||
|   | ||||
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | ||||
| github: [shamoon, stumpylog] | ||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug-report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug-report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -98,7 +98,7 @@ body: | ||||
|       label: Browser | ||||
|       description: Which browser you are using, if relevant. | ||||
|       placeholder: e.g. Chrome, Safari | ||||
|   - type: textarea | ||||
|   - type: input | ||||
|     id: config-changes | ||||
|     attributes: | ||||
|       label: Configuration changes | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,10 +2,10 @@ blank_issues_enabled: false | ||||
| contact_links: | ||||
|   - name: 🤔 Questions and Help | ||||
|     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 | ||||
|     url: https://matrix.to/#/#paperlessngx:matrix.org | ||||
|     about: Want to discuss Paperless-ngx with others? Check out our chat. | ||||
|   - name: 🚀 Feature Request | ||||
|     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 | ||||
|   | ||||
							
								
								
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +1,6 @@ | ||||
| # https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#package-ecosystem | ||||
|  | ||||
| version: 2 | ||||
| # Required for uv support for now | ||||
| enable-beta-ecosystems: true | ||||
| updates: | ||||
|  | ||||
|   # Enable version updates for npm | ||||
| @@ -36,8 +34,9 @@ updates: | ||||
|           - "eslint" | ||||
|  | ||||
|   # Enable version updates for Python | ||||
|   - package-ecosystem: "uv" | ||||
|   - package-ecosystem: "pip" | ||||
|     target-branch: "dev" | ||||
|     # Look for a `Pipfile` in the `root` directory | ||||
|     directory: "/" | ||||
|     # Check for updates once a week | ||||
|     schedule: | ||||
| @@ -48,13 +47,14 @@ updates: | ||||
|     # Add reviewers | ||||
|     reviewers: | ||||
|       - "paperless-ngx/backend" | ||||
|     ignore: | ||||
|       - dependency-name: "uvicorn" | ||||
|     groups: | ||||
|       development: | ||||
|         patterns: | ||||
|           - "*pytest*" | ||||
|           - "ruff" | ||||
|           - "mkdocs-material" | ||||
|           - "pre-commit*" | ||||
|       django: | ||||
|         patterns: | ||||
|           - "*django*" | ||||
| @@ -65,10 +65,6 @@ updates: | ||||
|         update-types: | ||||
|           - "minor" | ||||
|           - "patch" | ||||
|       pre-built: | ||||
|         patterns: | ||||
|           - psycopg* | ||||
|           - zxing-cpp | ||||
|  | ||||
|   # Enable updates for GitHub Actions | ||||
|   - package-ecosystem: "github-actions" | ||||
|   | ||||
							
								
								
									
										234
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										234
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -14,7 +14,9 @@ on: | ||||
|       - 'translations**' | ||||
|  | ||||
| env: | ||||
|   DEFAULT_UV_VERSION: "0.6.x" | ||||
|   # This is the version of pipenv all the steps will use | ||||
|   # If changing this, change Dockerfile | ||||
|   DEFAULT_PIP_ENV_VERSION: "2024.0.3" | ||||
|   # This is the default version of Python to use in most steps which aren't specific | ||||
|   DEFAULT_PYTHON_VERSION: "3.11" | ||||
|  | ||||
| @@ -28,7 +30,7 @@ jobs: | ||||
|       github.repository | ||||
|  | ||||
|     name: Linting Checks | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout repository | ||||
| @@ -44,7 +46,7 @@ jobs: | ||||
|  | ||||
|   documentation: | ||||
|     name: "Build & Deploy Documentation" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - pre-commit | ||||
|     steps: | ||||
| @@ -57,25 +59,24 @@ jobs: | ||||
|         uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: ${{ env.DEFAULT_PYTHON_VERSION }} | ||||
|           cache: "pipenv" | ||||
|           cache-dependency-path: 'Pipfile.lock' | ||||
|       - | ||||
|         name: Install uv | ||||
|         uses: astral-sh/setup-uv@v5 | ||||
|         with: | ||||
|           version: ${{ env.DEFAULT_UV_VERSION }} | ||||
|           enable-cache: true | ||||
|           python-version: ${{ env.DEFAULT_PYTHON_VERSION }} | ||||
|       - | ||||
|         name: Install Python dependencies | ||||
|         name: Install pipenv | ||||
|         run: | | ||||
|           uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen | ||||
|           pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} | ||||
|       - | ||||
|         name: Install dependencies | ||||
|         run: | | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev | ||||
|       - | ||||
|         name: List installed Python dependencies | ||||
|         run: | | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run pip list | ||||
|       - | ||||
|         name: Make documentation | ||||
|         run: | | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             --dev \ | ||||
|             --frozen \ | ||||
|             mkdocs build --config-file ./mkdocs.yml | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run mkdocs build --config-file ./mkdocs.yml | ||||
|       - | ||||
|         name: Deploy documentation | ||||
|         if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||||
| @@ -83,11 +84,7 @@ jobs: | ||||
|           echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME" | ||||
|           git config --global user.name "${{ github.actor }}" | ||||
|           git config --global user.email "${{ github.actor }}@users.noreply.github.com" | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             --dev \ | ||||
|             --frozen \ | ||||
|             mkdocs gh-deploy --force --no-history | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run mkdocs gh-deploy --force --no-history | ||||
|       - | ||||
|         name: Upload artifact | ||||
|         uses: actions/upload-artifact@v4 | ||||
| @@ -98,7 +95,7 @@ jobs: | ||||
|  | ||||
|   tests-backend: | ||||
|     name: "Backend Tests (Python ${{ matrix.python-version }})" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - pre-commit | ||||
|     strategy: | ||||
| @@ -120,13 +117,12 @@ jobs: | ||||
|         uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: "${{ matrix.python-version }}" | ||||
|           cache: "pipenv" | ||||
|           cache-dependency-path: 'Pipfile.lock' | ||||
|       - | ||||
|         name: Install uv | ||||
|         uses: astral-sh/setup-uv@v5 | ||||
|         with: | ||||
|           version: ${{ env.DEFAULT_UV_VERSION }} | ||||
|           enable-cache: true | ||||
|           python-version: ${{ steps.setup-python.outputs.python-version }} | ||||
|         name: Install pipenv | ||||
|         run: | | ||||
|           pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} | ||||
|       - | ||||
|         name: Install system dependencies | ||||
|         run: | | ||||
| @@ -135,18 +131,16 @@ jobs: | ||||
|       - | ||||
|         name: Configure ImageMagick | ||||
|         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 | ||||
|         run: | | ||||
|           uv sync \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             --group testing \ | ||||
|             --frozen | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run python --version | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev | ||||
|       - | ||||
|         name: List installed Python dependencies | ||||
|         run: | | ||||
|           uv pip list | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run pip list | ||||
|       - | ||||
|         name: Tests | ||||
|         env: | ||||
| @@ -156,26 +150,17 @@ jobs: | ||||
|           PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }} | ||||
|           PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }} | ||||
|         run: | | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             --dev \ | ||||
|             --frozen \ | ||||
|             pytest | ||||
|           cd src/ | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run pytest -ra | ||||
|       - | ||||
|         name: Upload backend test results to Codecov | ||||
|         if: always() | ||||
|         uses: codecov/test-results-action@v1 | ||||
|         name: Upload coverage | ||||
|         if: ${{ matrix.python-version == env.DEFAULT_PYTHON_VERSION }} | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           flags: python-${{ matrix.python-version }} | ||||
|           files: junit.xml | ||||
|       - | ||||
|         name: Upload backend coverage to Codecov | ||||
|         uses: codecov/codecov-action@v5 | ||||
|         with: | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           flags: python-${{ matrix.python-version }} | ||||
|           files: coverage.xml | ||||
|           name: backend-coverage-report | ||||
|           path: src/coverage.xml | ||||
|           retention-days: 7 | ||||
|           if-no-files-found: warn | ||||
|       - | ||||
|         name: Stop containers | ||||
|         if: always() | ||||
| @@ -183,9 +168,9 @@ jobs: | ||||
|           docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml logs | ||||
|           docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down | ||||
|  | ||||
|   install-frontend-dependencies: | ||||
|   install-frontend-depedendencies: | ||||
|     name: "Install Frontend Dependencies" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - pre-commit | ||||
|     steps: | ||||
| @@ -216,9 +201,9 @@ jobs: | ||||
|  | ||||
|   tests-frontend: | ||||
|     name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - install-frontend-dependencies | ||||
|       - install-frontend-depedendencies | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
| @@ -250,32 +235,77 @@ jobs: | ||||
|       - | ||||
|         name: Run Jest unit tests | ||||
|         run: cd src-ui && npm run test -- --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }} | ||||
|       - | ||||
|         name: Upload Jest coverage | ||||
|         if: always() | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: jest-coverage-report-${{ matrix.shard-index }} | ||||
|           path: | | ||||
|             src-ui/coverage/coverage-final.json | ||||
|             src-ui/coverage/lcov.info | ||||
|             src-ui/coverage/clover.xml | ||||
|           retention-days: 7 | ||||
|           if-no-files-found: warn | ||||
|       - | ||||
|         name: Run Playwright e2e tests | ||||
|         run: cd src-ui && npx playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }} | ||||
|       - | ||||
|         name: Upload frontend test results to Codecov | ||||
|         uses: codecov/test-results-action@v1 | ||||
|         name: Upload Playwright test results | ||||
|         if: always() | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           flags: node-${{ matrix.node-version }} | ||||
|           directory: src-ui/ | ||||
|       - | ||||
|         name: Upload frontend coverage to Codecov | ||||
|         uses: codecov/codecov-action@v5 | ||||
|         with: | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           flags: node-${{ matrix.node-version }} | ||||
|           directory: src-ui/coverage/ | ||||
|           name: playwright-report-${{ matrix.shard-index }} | ||||
|           path: src-ui/playwright-report | ||||
|           retention-days: 7 | ||||
|  | ||||
|   frontend-bundle-analysis: | ||||
|     name: "Frontend Bundle Analysis" | ||||
|     runs-on: ubuntu-24.04 | ||||
|   tests-coverage-upload: | ||||
|     name: "Upload to Codecov" | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - tests-backend | ||||
|       - tests-frontend | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Download frontend jest coverage | ||||
|         uses: actions/download-artifact@v4 | ||||
|         with: | ||||
|           path: src-ui/coverage/ | ||||
|           pattern: jest-coverage-report-* | ||||
|       - | ||||
|         name: Download frontend playwright coverage | ||||
|         uses: actions/download-artifact@v4 | ||||
|         with: | ||||
|           path: src-ui/coverage/ | ||||
|           pattern: playwright-report-* | ||||
|           merge-multiple: true | ||||
|       - | ||||
|         name: Upload frontend coverage to Codecov | ||||
|         uses: codecov/codecov-action@v4 | ||||
|         with: | ||||
|           # not required for public repos, but intermittently fails otherwise | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           flags: frontend | ||||
|           directory: src-ui/coverage/ | ||||
|           # dont include backend coverage files here | ||||
|           files: '!coverage.xml' | ||||
|       - | ||||
|         name: Download backend coverage | ||||
|         uses: actions/download-artifact@v4 | ||||
|         with: | ||||
|           name: backend-coverage-report | ||||
|           path: src/ | ||||
|       - | ||||
|         name: Upload coverage to Codecov | ||||
|         uses: codecov/codecov-action@v4 | ||||
|         with: | ||||
|           # not required for public repos, but intermittently fails otherwise | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           # future expansion | ||||
|           flags: backend | ||||
|           directory: src/ | ||||
|       - | ||||
|         name: Use Node.js 20 | ||||
|         uses: actions/setup-node@v4 | ||||
| @@ -303,7 +333,7 @@ jobs: | ||||
|  | ||||
|   build-docker-image: | ||||
|     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')) | ||||
|     concurrency: | ||||
|       group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }} | ||||
| @@ -376,7 +406,7 @@ jobs: | ||||
|       - | ||||
|         name: Login to Docker Hub | ||||
|         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' | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
| @@ -384,7 +414,7 @@ jobs: | ||||
|       - | ||||
|         name: Login to Quay.io | ||||
|         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' | ||||
|         with: | ||||
|           registry: quay.io | ||||
| @@ -431,7 +461,7 @@ jobs: | ||||
|     needs: | ||||
|       - build-docker-image | ||||
|       - documentation | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
| @@ -442,17 +472,16 @@ jobs: | ||||
|         uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: ${{ env.DEFAULT_PYTHON_VERSION }} | ||||
|           cache: "pipenv" | ||||
|           cache-dependency-path: 'Pipfile.lock' | ||||
|       - | ||||
|         name: Install uv | ||||
|         uses: astral-sh/setup-uv@v5 | ||||
|         with: | ||||
|           version: ${{ env.DEFAULT_UV_VERSION }} | ||||
|           enable-cache: true | ||||
|           python-version: ${{ steps.setup-python.outputs.python-version }} | ||||
|         name: Install pipenv + tools | ||||
|         run: | | ||||
|           pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel | ||||
|       - | ||||
|         name: Install Python dependencies | ||||
|         run: | | ||||
|           uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev | ||||
|       - | ||||
|         name: Install system dependencies | ||||
|         run: | | ||||
| @@ -473,21 +502,17 @@ jobs: | ||||
|       - | ||||
|         name: Generate requirements file | ||||
|         run: | | ||||
|            uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} requirements > requirements.txt | ||||
|       - | ||||
|         name: Compile messages | ||||
|         run: | | ||||
|           cd src/ | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             manage.py compilemessages | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run python3 manage.py compilemessages | ||||
|       - | ||||
|         name: Collect static files | ||||
|         run: | | ||||
|           cd src/ | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             manage.py collectstatic --no-input | ||||
|           pipenv --python ${{ steps.setup-python.outputs.python-version }} run python3 manage.py collectstatic --no-input | ||||
|       - | ||||
|         name: Move files | ||||
|         run: | | ||||
| @@ -503,13 +528,13 @@ jobs: | ||||
|           for file_name in .dockerignore \ | ||||
|                           .env \ | ||||
|                           Dockerfile \ | ||||
|                           pyproject.toml \ | ||||
|                           uv.lock \ | ||||
|                           Pipfile \ | ||||
|                           Pipfile.lock \ | ||||
|                           requirements.txt \ | ||||
|                           LICENSE \ | ||||
|                           README.md \ | ||||
|                           paperless.conf.example \ | ||||
|                           webserver.py | ||||
|                           gunicorn.conf.py | ||||
|           do | ||||
|             cp --verbose ${file_name} dist/paperless-ngx/ | ||||
|           done | ||||
| @@ -544,7 +569,7 @@ jobs: | ||||
|  | ||||
|   publish-release: | ||||
|     name: "Publish Release" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     outputs: | ||||
|       prerelease: ${{ steps.get_version.outputs.prerelease }} | ||||
|       changelog: ${{ steps.create-release.outputs.body }} | ||||
| @@ -594,7 +619,7 @@ jobs: | ||||
|  | ||||
|   append-changelog: | ||||
|     name: "Append Changelog" | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - publish-release | ||||
|     if: needs.publish-release.outputs.prerelease == 'false' | ||||
| @@ -606,17 +631,15 @@ jobs: | ||||
|           ref: main | ||||
|       - | ||||
|         name: Set up Python | ||||
|         id: setup-python | ||||
|         uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: ${{ env.DEFAULT_PYTHON_VERSION }} | ||||
|           cache: "pipenv" | ||||
|           cache-dependency-path: 'Pipfile.lock' | ||||
|       - | ||||
|         name: Install uv | ||||
|         uses: astral-sh/setup-uv@v5 | ||||
|         with: | ||||
|           version: ${{ env.DEFAULT_UV_VERSION }} | ||||
|           enable-cache: true | ||||
|           python-version: ${{ env.DEFAULT_PYTHON_VERSION }} | ||||
|         name: Install pipenv + tools | ||||
|         run: | | ||||
|           pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel | ||||
|       - | ||||
|         name: Append Changelog to docs | ||||
|         id: append-Changelog | ||||
| @@ -632,10 +655,7 @@ jobs: | ||||
|           CURRENT_CHANGELOG=`tail --lines +2 changelog.md` | ||||
|           echo -e "$CURRENT_CHANGELOG" >> changelog-new.md | ||||
|           mv changelog-new.md changelog.md | ||||
|           uv run \ | ||||
|             --python ${{ steps.setup-python.outputs.python-version }} \ | ||||
|             --dev \ | ||||
|             pre-commit run --files changelog.md || true | ||||
|           pipenv run pre-commit run --files changelog.md || true | ||||
|           git config --global user.name "github-actions" | ||||
|           git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||||
|           git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA" | ||||
|   | ||||
							
								
								
									
										8
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/cleanup-tags.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | ||||
|   cleanup-images: | ||||
|     name: Cleanup Image Tags for ${{ matrix.primary-name }} | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
| @@ -33,7 +33,7 @@ jobs: | ||||
|       - | ||||
|         name: Clean temporary images | ||||
|         if: "${{ env.TOKEN != '' }}" | ||||
|         uses: stumpylog/image-cleaner-action/ephemeral@v0.10.0 | ||||
|         uses: stumpylog/image-cleaner-action/ephemeral@v0.8.0 | ||||
|         with: | ||||
|           token: "${{ env.TOKEN }}" | ||||
|           owner: "${{ github.repository_owner }}" | ||||
| @@ -47,7 +47,7 @@ jobs: | ||||
|   cleanup-untagged-images: | ||||
|     name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }} | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     needs: | ||||
|       - cleanup-images | ||||
|     strategy: | ||||
| @@ -61,7 +61,7 @@ jobs: | ||||
|       - | ||||
|         name: Clean untagged images | ||||
|         if: "${{ env.TOKEN != '' }}" | ||||
|         uses: stumpylog/image-cleaner-action/untagged@v0.10.0 | ||||
|         uses: stumpylog/image-cleaner-action/untagged@v0.8.0 | ||||
|         with: | ||||
|           token: "${{ env.TOKEN }}" | ||||
|           owner: "${{ github.repository_owner }}" | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ on: | ||||
| jobs: | ||||
|   analyze: | ||||
|     name: Analyze | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     permissions: | ||||
|       actions: read | ||||
|       contents: read | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/crowdin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/crowdin.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,7 +16,7 @@ jobs: | ||||
|   synchronize-with-crowdin: | ||||
|     name: Crowdin Sync | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     steps: | ||||
|     - name: Checkout | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/project-actions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/project-actions.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,7 +15,7 @@ permissions: | ||||
| jobs: | ||||
|   pr_opened_or_reopened: | ||||
|     name: pr_opened_or_reopened | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-22.04 | ||||
|     permissions: | ||||
|       # write permission is required for autolabeler | ||||
|       pull-requests: write | ||||
|   | ||||
							
								
								
									
										10
									
								
								.github/workflows/repo-maintenance.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/repo-maintenance.yml
									
									
									
									
										vendored
									
									
								
							| @@ -17,7 +17,7 @@ jobs: | ||||
|   stale: | ||||
|     name: 'Stale' | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/stale@v9 | ||||
|         with: | ||||
| @@ -33,7 +33,7 @@ jobs: | ||||
|   lock-threads: | ||||
|     name: 'Lock Old Threads' | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: dessant/lock-threads@v5 | ||||
|         with: | ||||
| @@ -59,7 +59,7 @@ jobs: | ||||
|   close-answered-discussions: | ||||
|     name: 'Close Answered Discussions' | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/github-script@v7 | ||||
|         with: | ||||
| @@ -116,7 +116,7 @@ jobs: | ||||
|   close-outdated-discussions: | ||||
|     name: 'Close Outdated Discussions' | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/github-script@v7 | ||||
|         with: | ||||
| @@ -208,7 +208,7 @@ jobs: | ||||
|   close-unsupported-feature-requests: | ||||
|     name: 'Close Unsupported Feature Requests' | ||||
|     if: github.repository_owner == 'paperless-ngx' | ||||
|     runs-on: ubuntu-24.04 | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/github-script@v7 | ||||
|         with: | ||||
|   | ||||
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -44,7 +44,6 @@ nosetests.xml | ||||
| coverage.xml | ||||
| *,cover | ||||
| .pytest_cache | ||||
| junit.xml | ||||
|  | ||||
| # Translations | ||||
| *.mo | ||||
| @@ -101,9 +100,3 @@ scripts/nuke | ||||
|  | ||||
| # celery schedule file | ||||
| celerybeat-schedule* | ||||
|  | ||||
| # ignore .devcontainer sub folders | ||||
| /.devcontainer/consume/ | ||||
| /.devcontainer/data/ | ||||
| /.devcontainer/media/ | ||||
| /.devcontainer/redisdata/ | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| repos: | ||||
|   # General hooks | ||||
|   - repo: https://github.com/pre-commit/pre-commit-hooks | ||||
|     rev: v5.0.0 | ||||
|     rev: v4.6.0 | ||||
|     hooks: | ||||
|       - id: check-docstring-first | ||||
|       - id: check-json | ||||
| @@ -29,7 +29,7 @@ repos: | ||||
|       - id: check-case-conflict | ||||
|       - id: detect-private-key | ||||
|   - repo: https://github.com/codespell-project/codespell | ||||
|     rev: v2.4.0 | ||||
|     rev: v2.3.0 | ||||
|     hooks: | ||||
|       - id: codespell | ||||
|         exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)" | ||||
| @@ -45,19 +45,13 @@ repos: | ||||
|           - javascript | ||||
|           - ts | ||||
|           - markdown | ||||
|         additional_dependencies: | ||||
|           - prettier@3.3.3 | ||||
|           - 'prettier-plugin-organize-imports@4.1.0' | ||||
|         exclude: "(^Pipfile\\.lock$)" | ||||
|   # Python hooks | ||||
|   - repo: https://github.com/astral-sh/ruff-pre-commit | ||||
|     rev: v0.9.9 | ||||
|     rev: 'v0.6.8' | ||||
|     hooks: | ||||
|       - id: ruff | ||||
|       - id: ruff-format | ||||
|   - repo: https://github.com/tox-dev/pyproject-fmt | ||||
|     rev: "v2.5.1" | ||||
|     hooks: | ||||
|       - id: pyproject-fmt | ||||
|   # Dockerfile hooks | ||||
|   - repo: https://github.com/AleksaC/hadolint-py | ||||
|     rev: v2.12.0.3 | ||||
|   | ||||
							
								
								
									
										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": ["docs/*.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
									
								
								.python-version
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.python-version
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 3.10.15 | ||||
							
								
								
									
										47
									
								
								.ruff.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								.ruff.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| fix = true | ||||
| line-length = 88 | ||||
| respect-gitignore = true | ||||
| src = ["src"] | ||||
| target-version = "py310" | ||||
| output-format = "grouped" | ||||
| show-fixes = true | ||||
|  | ||||
| # https://docs.astral.sh/ruff/settings/ | ||||
| # https://docs.astral.sh/ruff/rules/ | ||||
| [lint] | ||||
| extend-select = [ | ||||
|   "W",     # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w | ||||
|   "I",     # https://docs.astral.sh/ruff/rules/#isort-i | ||||
|   "UP",    # https://docs.astral.sh/ruff/rules/#pyupgrade-up | ||||
|   "COM",   # https://docs.astral.sh/ruff/rules/#flake8-commas-com | ||||
|   "DJ",    # https://docs.astral.sh/ruff/rules/#flake8-django-dj | ||||
|   "EXE",   # https://docs.astral.sh/ruff/rules/#flake8-executable-exe | ||||
|   "ISC",   # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc | ||||
|   "ICN",   # https://docs.astral.sh/ruff/rules/#flake8-import-conventions-icn | ||||
|   "G201",  # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g | ||||
|   "INP",   # https://docs.astral.sh/ruff/rules/#flake8-no-pep420-inp | ||||
|   "PIE",   # https://docs.astral.sh/ruff/rules/#flake8-pie-pie | ||||
|   "Q",     # https://docs.astral.sh/ruff/rules/#flake8-quotes-q | ||||
|   "RSE",   # https://docs.astral.sh/ruff/rules/#flake8-raise-rse | ||||
|   "T20",   # https://docs.astral.sh/ruff/rules/#flake8-print-t20 | ||||
|   "SIM",   # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim | ||||
|   "TID",   # https://docs.astral.sh/ruff/rules/#flake8-tidy-imports-tid | ||||
|   "TCH",   # https://docs.astral.sh/ruff/rules/#flake8-type-checking-tch | ||||
|   "PLC",   # 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 | ||||
|   "FLY",   # https://docs.astral.sh/ruff/rules/#flynt-fly | ||||
| ] | ||||
| # TODO PTH https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth | ||||
| ignore = ["DJ001", "SIM105", "RUF012"] | ||||
|  | ||||
| [lint.per-file-ignores] | ||||
| ".github/scripts/*.py" = ["E501", "INP001", "SIM117"] | ||||
| "docker/wait-for-redis.py" = ["INP001", "T201"] | ||||
| "*/tests/*.py" = ["E501", "SIM117"] | ||||
| "*/migrations/*.py" = ["E501", "SIM", "T201"] | ||||
| "src/paperless_tesseract/tests/test_parser.py" = ["RUF001"] | ||||
| "src/documents/models.py" = ["SIM115"] | ||||
|  | ||||
| [lint.isort] | ||||
| force-single-line = true | ||||
| @@ -5,6 +5,5 @@ | ||||
| /src-ui/ @paperless-ngx/frontend | ||||
|  | ||||
| /src/ @paperless-ngx/backend | ||||
| pyproject.toml @paperless-ngx/backend | ||||
| uv.lock @paperless-ngx/backend | ||||
| Pipfile* @paperless-ngx/backend | ||||
| *.py @paperless-ngx/backend | ||||
|   | ||||
							
								
								
									
										173
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -26,66 +26,28 @@ esac | ||||
| RUN set -eux \ | ||||
|   && ./node_modules/.bin/ng build --configuration production | ||||
|  | ||||
| # Stage: s6-overlay-base | ||||
| # Purpose: Installs s6-overlay and rootfs | ||||
| # Stage: pipenv-base | ||||
| # Purpose: Generates a requirements.txt file for building | ||||
| # Comments: | ||||
| #  - Don't leave anything extra in here either | ||||
| FROM ghcr.io/astral-sh/uv:0.6.3-python3.12-bookworm-slim AS s6-overlay-base | ||||
| #  - pipenv dependencies are not left in the final image | ||||
| #  - pipenv can't touch the final image somehow | ||||
| FROM --platform=$BUILDPLATFORM docker.io/python:3.12-alpine AS pipenv-base | ||||
|  | ||||
| WORKDIR /usr/src/s6 | ||||
| WORKDIR /usr/src/pipenv | ||||
|  | ||||
| # 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" | ||||
| COPY Pipfile* ./ | ||||
|  | ||||
| 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 / | ||||
|   && echo "Installing pipenv" \ | ||||
|     && python3 -m pip install --no-cache-dir --upgrade pipenv==2024.0.3 \ | ||||
|   && echo "Generating requirement.txt" \ | ||||
|     && pipenv requirements > requirements.txt | ||||
|  | ||||
| # Stage: main-app | ||||
| # Purpose: The final image | ||||
| # Comments: | ||||
| #  - Don't leave anything extra in here | ||||
| FROM s6-overlay-base AS main-app | ||||
| FROM docker.io/python:3.12-slim-bookworm AS main-app | ||||
|  | ||||
| LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>" | ||||
| LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/" | ||||
| @@ -99,19 +61,16 @@ ARG DEBIAN_FRONTEND=noninteractive | ||||
| ARG TARGETARCH | ||||
|  | ||||
| # 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 GS_VERSION=10.03.1 | ||||
|  | ||||
| # Set Python environment variables | ||||
| ENV PYTHONDONTWRITEBYTECODE=1 \ | ||||
|     PYTHONUNBUFFERED=1 \ | ||||
|     # Ignore warning from Whitenoise about async iterators | ||||
|     # Ignore warning from Whitenoise | ||||
|     PYTHONWARNINGS="ignore:::django.http.response:517" \ | ||||
|     PNGX_CONTAINERIZED=1 \ | ||||
|     # https://docs.astral.sh/uv/reference/settings/#link-mode | ||||
|     UV_LINK_MODE=copy \ | ||||
|     UV_CACHE_DIR=/cache/uv/ | ||||
|     PNGX_CONTAINERIZED=1 | ||||
|  | ||||
| # | ||||
| # Begin installation and configuration | ||||
| @@ -168,56 +127,118 @@ RUN set -eux \ | ||||
|     && apt-get update \ | ||||
|     && apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \ | ||||
|     && 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}" \ | ||||
|         && 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 \ | ||||
|       && echo "Configuring imagemagick" \ | ||||
|         && cp /etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml \ | ||||
|       && echo "Cleaning up image layer" \ | ||||
|         && 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 webserver config | ||||
| # Copy gunicorn config | ||||
| # Changes very infrequently | ||||
| WORKDIR /usr/src/paperless/ | ||||
| COPY --chown=1000:1000 webserver.py /usr/src/paperless/webserver.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/ | ||||
|  | ||||
| # Python dependencies | ||||
| # Change pretty frequently | ||||
| COPY --chown=1000:1000 ["pyproject.toml", "uv.lock", "/usr/src/paperless/src/"] | ||||
| COPY --from=pipenv-base /usr/src/pipenv/requirements.txt ./ | ||||
|  | ||||
| # 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" | ||||
|  | ||||
| # hadolint ignore=DL3042 | ||||
| RUN --mount=type=cache,target=${UV_CACHE_DIR},id=python-cache \ | ||||
| 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 --no-install-recommends ${BUILD_PACKAGES} \ | ||||
|     && python3 -m pip install --no-cache-dir --upgrade wheel \ | ||||
|   && echo "Installing Python requirements" \ | ||||
|     && uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt \ | ||||
|     && uv pip install --system --no-python-downloads --python-preference system --requirements requirements.txt \ | ||||
|     && curl --fail --silent --show-error --location \ | ||||
|     --output psycopg_c-3.2.2-cp312-cp312-linux_x86_64.whl \ | ||||
|     https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.2/psycopg_c-3.2.2-cp312-cp312-linux_x86_64.whl \ | ||||
|     && curl --fail --silent --show-error --location \ | ||||
|     --output psycopg_c-3.2.2-cp312-cp312-linux_aarch64.whl  \ | ||||
|     https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.2/psycopg_c-3.2.2-cp312-cp312-linux_aarch64.whl \ | ||||
|     && python3 -m pip install --default-timeout=1000 --find-links . --requirement requirements.txt \ | ||||
|   && 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" stopwords \ | ||||
| @@ -255,16 +276,18 @@ RUN set -eux \ | ||||
|   && echo "Adjusting all permissions" \ | ||||
|     && chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \ | ||||
|   && echo "Collecting static files" \ | ||||
|     && s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \ | ||||
|     && s6-setuidgid paperless python3 manage.py compilemessages | ||||
|     && gosu paperless python3 manage.py collectstatic --clear --no-input --link \ | ||||
|     && gosu paperless python3 manage.py compilemessages | ||||
|  | ||||
| VOLUME ["/usr/src/paperless/data", \ | ||||
|         "/usr/src/paperless/media", \ | ||||
|         "/usr/src/paperless/consume", \ | ||||
|         "/usr/src/paperless/export"] | ||||
|  | ||||
| ENTRYPOINT ["/init"] | ||||
| ENTRYPOINT ["/sbin/docker-entrypoint.sh"] | ||||
|  | ||||
| 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" ] | ||||
|   | ||||
							
								
								
									
										100
									
								
								Pipfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Pipfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| [[source]] | ||||
| url = "https://pypi.python.org/simple" | ||||
| verify_ssl = true | ||||
| name = "pypi" | ||||
|  | ||||
| [packages] | ||||
| dateparser = "~=1.2" | ||||
| # WARNING: django does not use semver. | ||||
| #          Only patch versions are guaranteed to not introduce breaking changes. | ||||
| django = "~=5.1.1" | ||||
| django-allauth = {extras = ["socialaccount"], version = "*"} | ||||
| django-auditlog = "*" | ||||
| django-celery-results = "*" | ||||
| django-compression-middleware = "*" | ||||
| django-cors-headers = "*" | ||||
| django-extensions = "*" | ||||
| django-filter = "~=24.3" | ||||
| django-guardian = "*" | ||||
| django-multiselectfield = "*" | ||||
| django-soft-delete = "*" | ||||
| djangorestframework = "==3.15.2" | ||||
| djangorestframework-guardian = "*" | ||||
| drf-writable-nested = "*" | ||||
| bleach = "*" | ||||
| celery = {extras = ["redis"], version = "*"} | ||||
| channels = "~=4.1" | ||||
| channels-redis = "*" | ||||
| concurrent-log-handler = "*" | ||||
| filelock = "*" | ||||
| flower = "*" | ||||
| gotenberg-client = "*" | ||||
| gunicorn = "*" | ||||
| httpx-oauth = "*" | ||||
| imap-tools = "*" | ||||
| inotifyrecursive = "~=0.3" | ||||
| jinja2 = "~=3.1" | ||||
| langdetect = "*" | ||||
| mysqlclient = "*" | ||||
| nltk = "*" | ||||
| ocrmypdf = "~=16.5" | ||||
| pathvalidate = "*" | ||||
| pdf2image = "*" | ||||
| psycopg = {version = "*", extras = ["c"]} | ||||
| python-dateutil = "*" | ||||
| python-dotenv = "*" | ||||
| python-gnupg = "*" | ||||
| python-ipware = "*" | ||||
| python-magic = "*" | ||||
| pyzbar = "*" | ||||
| rapidfuzz = "*" | ||||
| redis = {extras = ["hiredis"], version = "*"} | ||||
| scikit-learn = "~=1.5" | ||||
| setproctitle = "*" | ||||
| tika-client = "*" | ||||
| tqdm = "*" | ||||
| # See https://github.com/paperless-ngx/paperless-ngx/issues/5494 | ||||
| uvicorn = {extras = ["standard"], version = "==0.25.0"} | ||||
| watchdog = "~=4.0" | ||||
| whitenoise = "~=6.8" | ||||
| whoosh = "~=2.7" | ||||
| zxing-cpp = {version = "*", platform_machine = "== 'x86_64'"} | ||||
|  | ||||
|  | ||||
| [dev-packages] | ||||
| # Linting | ||||
| pre-commit = "*" | ||||
| ruff = "*" | ||||
| factory-boy = "*" | ||||
| # Testing | ||||
| pytest = "*" | ||||
| pytest-cov = "*" | ||||
| pytest-django = "*" | ||||
| pytest-httpx = "*" | ||||
| pytest-env = "*" | ||||
| pytest-sugar = "*" | ||||
| pytest-xdist = "*" | ||||
| pytest-mock = "*" | ||||
| pytest-rerunfailures = "*" | ||||
| imagehash = "*" | ||||
| daphne = "*" | ||||
| # Documentation | ||||
| mkdocs-material = "*" | ||||
| mkdocs-glightbox = "*" | ||||
|  | ||||
| [typing-dev] | ||||
| mypy = "*" | ||||
| types-Pillow = "*" | ||||
| django-filter-stubs = "*" | ||||
| types-python-dateutil = "*" | ||||
| djangorestframework-stubs = {extras= ["compatible-mypy"], version="*"} | ||||
| celery-types = "*" | ||||
| django-stubs = {extras= ["compatible-mypy"], version="*"} | ||||
| types-dateparser = "*" | ||||
| types-bleach = "*" | ||||
| types-redis = "*" | ||||
| types-tqdm = "*" | ||||
| types-Markdown = "*" | ||||
| types-Pygments = "*" | ||||
| types-colorama = "*" | ||||
| types-setuptools = "*" | ||||
							
								
								
									
										4489
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										4489
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -55,7 +55,7 @@ A full list of [features](https://docs.paperless-ngx.com/#features) and [screens | ||||
|  | ||||
| # 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: | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|  | ||||
| services: | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:8.17 | ||||
|     image: docker.io/gotenberg/gotenberg:8.7 | ||||
|     hostname: gotenberg | ||||
|     container_name: gotenberg | ||||
|     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 | ||||
| # to your UID and GID on the host so that you have write access to the | ||||
| # consumption directory. | ||||
| #USERMAP_UID=1000 | ||||
| #USERMAP_GID=1000 | ||||
|  | ||||
| # See the documentation linked above for all options. A few commonly adjusted settings | ||||
| # are provided below. | ||||
| # 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 | ||||
|  | ||||
| ############################################################################### | ||||
| # 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 | ||||
| # (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. | ||||
| #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 | ||||
|  | ||||
| # The default language to use for OCR. Set this to the language most of your | ||||
| # documents are written in. | ||||
| #PAPERLESS_OCR_LANGUAGE=eng | ||||
|  | ||||
| # 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 | ||||
| # Set if accessing paperless via a domain subpath e.g. https://domain.com/PATHPREFIX and using a reverse-proxy like traefik or nginx | ||||
| #PAPERLESS_FORCE_SCRIPT_NAME=/PATHPREFIX | ||||
| #PAPERLESS_STATIC_URL=/PATHPREFIX/static/ # trailing slash required | ||||
|   | ||||
| @@ -77,7 +77,7 @@ services: | ||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||
|  | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:8.17 | ||||
|     image: docker.io/gotenberg/gotenberg:8.7 | ||||
|     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. | ||||
|   | ||||
| @@ -19,8 +19,6 @@ | ||||
| # | ||||
| # - Open portainer Stacks list and click 'Add stack' | ||||
| # - 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 | ||||
| # - Open the list of containers, select paperless_webserver_1 | ||||
| # - Click 'Console' and then 'Connect' to open the command line inside the container | ||||
| @@ -63,8 +61,28 @@ services: | ||||
|     environment: | ||||
|       PAPERLESS_REDIS: redis://broker:6379 | ||||
|       PAPERLESS_DBHOST: db | ||||
|     env_file: | ||||
|       - stack.env | ||||
| # 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 | ||||
| # 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: | ||||
|   data: | ||||
|   | ||||
| @@ -71,7 +71,7 @@ services: | ||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||
|  | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:8.17 | ||||
|     image: docker.io/gotenberg/gotenberg:8.7 | ||||
|     restart: unless-stopped | ||||
|  | ||||
|     # The gotenberg chromium route is used to convert .eml files. We do not | ||||
|   | ||||
| @@ -59,7 +59,7 @@ services: | ||||
|       PAPERLESS_TIKA_ENDPOINT: http://tika:9998 | ||||
|  | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:8.17 | ||||
|     image: docker.io/gotenberg/gotenberg:8.7 | ||||
|     restart: unless-stopped | ||||
|  | ||||
|     # The gotenberg chromium route is used to convert .eml files. We do not | ||||
|   | ||||
							
								
								
									
										120
									
								
								docker/docker-prepare.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										120
									
								
								docker/docker-prepare.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| #!/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 --host ${host} --port ${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 | ||||
| 	echo "Connected to PostgreSQL" | ||||
| } | ||||
|  | ||||
| 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 | ||||
| 	echo "Connected to MariaDB" | ||||
| } | ||||
|  | ||||
| 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" || ${env_name} == "PAPERLESS_MODEL_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 | ||||
|  | ||||
| # Run this script to generate the management commands again (for example if a new command is create or the template is updated) | ||||
|  | ||||
| set -eu | ||||
|  | ||||
| for command in decrypt_documents \ | ||||
| @@ -17,10 +15,9 @@ for command in decrypt_documents \ | ||||
| 	document_sanity_checker \ | ||||
| 	document_fuzzy_match \ | ||||
| 	manage_superuser \ | ||||
| 	convert_mariadb_uuid \ | ||||
| 	prune_audit_logs; | ||||
| 	convert_mariadb_uuid; | ||||
| do | ||||
| 	echo "installing $command..." | ||||
| 	sed "s/management_command/$command/g" management_script.sh >"$PWD/rootfs/usr/local/bin/$command" | ||||
| 	chmod +x "$PWD/rootfs/usr/local/bin/$command" | ||||
| 	sed "s/management_command/$command/g" management_script.sh > /usr/local/bin/$command | ||||
| 	chmod +x /usr/local/bin/$command | ||||
| done | ||||
|   | ||||
| @@ -1,13 +1,17 @@ | ||||
| #!/command/with-contenv /usr/bin/bash | ||||
| # shellcheck shell=bash | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| 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 | ||||
| 	s6-setuidgid paperless python3 manage.py management_command "$@" | ||||
| elif [[ $(id -un) == "paperless" ]]; then | ||||
| if [[ $(id -u) == 0 ]] ; | ||||
| then | ||||
| 	gosu paperless python3 manage.py management_command "$@" | ||||
| elif [[ $(id -un) == "paperless" ]] ; | ||||
| then | ||||
| 	python3 manage.py management_command "$@" | ||||
| else | ||||
| 	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 | ||||
| @@ -1,15 +0,0 @@ | ||||
| #!/command/with-contenv /usr/bin/bash | ||||
| # shellcheck shell=bash | ||||
|  | ||||
| declare -r log_prefix="[init-checks]" | ||||
|  | ||||
| # Explicitly run the Django system checks | ||||
| echo "${log_prefix} Running Django checks" | ||||
|  | ||||
| cd "${PAPERLESS_SRC_DIR}" | ||||
|  | ||||
| if [[ -n "${USER_IS_NON_ROOT}" ]]; then | ||||
| 	python3 manage.py check | ||||
| else | ||||
| 	s6-setuidgid paperless python3 manage.py check | ||||
| fi | ||||
| @@ -1 +0,0 @@ | ||||
| oneshot | ||||
| @@ -1 +0,0 @@ | ||||
| /etc/s6-overlay/s6-rc.d/init-system-checks/run | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user