mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	add basic ansible role for debian deployment
Currently only Debian 10 buster is supported. Other Debian versions, Ubuntu and derivates should be easy to integrate. Database deployment is considered out-of-scope and deferred to the user. Provides basic upgrade support between releases.
This commit is contained in:
		
							
								
								
									
										39
									
								
								ansible/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								ansible/defaults/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | --- | ||||||
|  | paperlessng_version: 0.9.8 | ||||||
|  | paperlessng_directory: /opt/paperless-ng | ||||||
|  | paperlessng_consumption_dir: "{{ paperlessng_directory }}/consumption" | ||||||
|  | paperlessng_data_dir: "{{ paperlessng_directory }}/data" | ||||||
|  | paperlessng_media_root: "{{ paperlessng_directory }}/media" | ||||||
|  | paperlessng_static_dir: "{{ paperlessng_directory }}/static" | ||||||
|  | paperlessng_filename_format: | ||||||
|  | paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv" | ||||||
|  |  | ||||||
|  | paperlessng_ocr_languages: | ||||||
|  |   - eng | ||||||
|  | paperlessng_time_zone: Europe/Berlin | ||||||
|  | paperlessng_ocrmypdf_args: --optimize 1 | ||||||
|  | # TODO Does optimze==1 really work with jbig2enc? | ||||||
|  | # https://ocrmypdf.readthedocs.io/en/latest/jbig2.html#lossy-mode-jbig2 | ||||||
|  | # Documentation states -O1 only applies lossless transformations | ||||||
|  | # https://ocrmypdf.readthedocs.io/en/latest/optimizer.html#lossless-optimizations | ||||||
|  | paperlessng_use_jbig2enc: true | ||||||
|  |  | ||||||
|  | paperlessng_superuser_name: paperlessng | ||||||
|  | paperlessng_superuser_email: paperlessng@example.com | ||||||
|  | paperlessng_superuser_password: paperlessng | ||||||
|  |  | ||||||
|  | paperlessng_system_user: paperlessng | ||||||
|  | paperlessng_system_group: paperlessng | ||||||
|  |  | ||||||
|  | paperlessng_listen_address: 127.0.0.1 | ||||||
|  | paperlessng_listen_port: 8000 | ||||||
|  |  | ||||||
|  | paperlessng_redis_host: localhost | ||||||
|  | paperlessng_redis_port: 6379 | ||||||
|  |  | ||||||
|  | paperlessng_db_type: sqlite # or postgresql | ||||||
|  | paperlessng_db_host: localhost | ||||||
|  | paperlessng_db_port: 5432 | ||||||
|  | paperlessng_db_name: paperlessng | ||||||
|  | paperlessng_db_user: paperlessng | ||||||
|  | paperlessng_db_pass: paperlessng | ||||||
							
								
								
									
										350
									
								
								ansible/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								ansible/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,350 @@ | |||||||
|  | --- | ||||||
|  | - name: verify operating system | ||||||
|  |   fail: | ||||||
|  |     msg: Sorry, only Debian 10 supported at the moment. | ||||||
|  |   when: not(ansible_distribution == 'Debian' and ansible_distribution_version == '10') | ||||||
|  |  | ||||||
|  | - name: install base dependencies | ||||||
|  |   apt: | ||||||
|  |     update_cache: yes | ||||||
|  |     pkg: | ||||||
|  |       # paperless-ng | ||||||
|  |       - python3-dev | ||||||
|  |       - python3-pip | ||||||
|  |       - imagemagick | ||||||
|  |       - unpaper | ||||||
|  |       - ghostscript | ||||||
|  |       - optipng | ||||||
|  |       - tesseract-ocr | ||||||
|  |       - gnupg | ||||||
|  |       - libpoppler-cpp-dev | ||||||
|  |       - libmagic-dev | ||||||
|  |       - libpq-dev | ||||||
|  |       # OCRmyPDF | ||||||
|  |       - icc-profiles-free | ||||||
|  |       - qpdf | ||||||
|  |       - liblept5 | ||||||
|  |       - libxml2 | ||||||
|  |       - pngquant | ||||||
|  |       - zlib1g | ||||||
|  |       # dev | ||||||
|  |       - build-essential | ||||||
|  |       - python3-setuptools | ||||||
|  |       - python3-wheel | ||||||
|  |       - python3-virtualenv | ||||||
|  |  | ||||||
|  | - name: install ocr languages | ||||||
|  |   apt: | ||||||
|  |     pkg: "{{ paperlessng_ocr_languages | map('regex_replace', '^(.*)$', 'tesseract-ocr-\\1') | list }}" | ||||||
|  |  | ||||||
|  | - name: set up notesalexp repository key (for jbig2enc) | ||||||
|  |   apt_key: | ||||||
|  |     url: https://notesalexp.org/debian/alexp_key.asc | ||||||
|  |     state: present | ||||||
|  |   when: paperlessng_use_jbig2enc | ||||||
|  |  | ||||||
|  | - name: set up notesalexp repository (for jbig2enc) | ||||||
|  |   apt_repository: | ||||||
|  |     repo: deb https://notesalexp.org/debian/buster/ buster main | ||||||
|  |     state: present | ||||||
|  |   when: paperlessng_use_jbig2enc | ||||||
|  |  | ||||||
|  | - name: set up notesalexp repository pinning | ||||||
|  |   copy: | ||||||
|  |     content: | | ||||||
|  |       Package: * | ||||||
|  |       Pin: release o=notesalexp.org | ||||||
|  |       Pin-Priority: 1 | ||||||
|  |  | ||||||
|  |       Package: jbig2enc | ||||||
|  |       Pin: release o=notesalexp.org | ||||||
|  |       Pin-Priority: 500 | ||||||
|  |     dest: /etc/apt/preferences.d/notesalexp | ||||||
|  |   when: paperlessng_use_jbig2enc | ||||||
|  |  | ||||||
|  | - name: install jbig2enc | ||||||
|  |   apt: | ||||||
|  |     pkg: jbig2enc | ||||||
|  |     update_cache: yes | ||||||
|  |   when: paperlessng_use_jbig2enc | ||||||
|  |  | ||||||
|  | - name: install redis | ||||||
|  |   apt: | ||||||
|  |     pkg: redis-server | ||||||
|  |   when: paperlessng_redis_host == 'localhost' or paperlessng_redis_host == '127.0.0.1' | ||||||
|  |  | ||||||
|  | - name: enable redis | ||||||
|  |   systemd: | ||||||
|  |     name: redis-server | ||||||
|  |     enabled: yes | ||||||
|  |     masked: no | ||||||
|  |     state: started | ||||||
|  |   when: paperlessng_redis_host == 'localhost' or paperlessng_redis_host == '127.0.0.1' | ||||||
|  |  | ||||||
|  | - name: check for paperless-ng installation | ||||||
|  |   command: | ||||||
|  |     cmd: 'grep -Po "(?<=Paperless-ng )\d+\.\d+\.\d+" {{ paperlessng_directory }}/docs/changelog.html' | ||||||
|  |   changed_when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |   failed_when: false | ||||||
|  |   ignore_errors: yes | ||||||
|  |   register: paperlessng_current_version | ||||||
|  |  | ||||||
|  | - name: backup current paperless-ng installation | ||||||
|  |   copy: | ||||||
|  |     src: "{{ paperlessng_directory }}" | ||||||
|  |     dest: "{{ paperlessng_directory }}-{{ ansible_date_time.iso8601 }}/" | ||||||
|  |     remote_src: yes | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: download paperless-ng | ||||||
|  |   get_url: | ||||||
|  |     url: "https://github.com/jonaswinkler/paperless-ng/releases/download/ng-{{ paperlessng_version }}/paperless-ng-{{ paperlessng_version }}.tar.xz" | ||||||
|  |     dest: /opt/paperless-ng-{{ paperlessng_version }}.tar.xz | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: create paperless-ng directories | ||||||
|  |   file: | ||||||
|  |     path: "{{ item }}" | ||||||
|  |     state: directory | ||||||
|  |     owner: "{{ paperlessng_system_user }}" | ||||||
|  |     group: "{{ paperlessng_system_group }}" | ||||||
|  |     mode: 0750 | ||||||
|  |     recurse: yes | ||||||
|  |   with_items: | ||||||
|  |     - "{{ paperlessng_directory }}" | ||||||
|  |     - "{{ paperlessng_consumption_dir }}" | ||||||
|  |     - "{{ paperlessng_data_dir }}" | ||||||
|  |     - "{{ paperlessng_media_root }}" | ||||||
|  |     - "{{ paperlessng_static_dir }}" | ||||||
|  |  | ||||||
|  | - name: create temporary directory | ||||||
|  |   tempfile: | ||||||
|  |     state: directory | ||||||
|  |   register: tempdir | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: extract paperless-ng | ||||||
|  |   unarchive: | ||||||
|  |     src: /opt/paperless-ng-{{ paperlessng_version }}.tar.xz | ||||||
|  |     dest: "{{ tempdir.path }}" | ||||||
|  |     remote_src: yes | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: move paperless-ng | ||||||
|  |   command: | ||||||
|  |     cmd: "cp -R {{ tempdir.path }}/paperless-ng/. {{ paperlessng_directory }}" | ||||||
|  |   args: | ||||||
|  |     warn: false | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: remove temporary directory | ||||||
|  |   file: | ||||||
|  |     path: "{{ tempdir.path }}" | ||||||
|  |     state: absent | ||||||
|  |   when: '"No such file or directory" in paperlessng_current_version.stderr or paperlessng_current_version.stdout != paperlessng_version | string' | ||||||
|  |  | ||||||
|  | - name: configure paperless-ng | ||||||
|  |   lineinfile: | ||||||
|  |     path: "{{ paperlessng_directory }}/paperless.conf" | ||||||
|  |     regexp: "{{ item.regexp }}" | ||||||
|  |     line: "{{ item.line }}" | ||||||
|  |   with_items: | ||||||
|  |     - regexp: "^#?PAPERLESS_REDIS=" | ||||||
|  |       line: "PAPERLESS_REDIS=redis://{{ paperlessng_redis_host }}:{{ paperlessng_redis_port }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_CONSUMPTION_DIR=" | ||||||
|  |       line: "PAPERLESS_CONSUMPTION_DIR={{ paperlessng_consumption_dir }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_DATA_DIR=" | ||||||
|  |       line: "PAPERLESS_DATA_DIR={{ paperlessng_data_dir }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_MEDIA_ROOT=" | ||||||
|  |       line: "PAPERLESS_MEDIA_ROOT={{ paperlessng_media_root }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_STATICDIR=" | ||||||
|  |       line: "PAPERLESS_STATICDIR={{ paperlessng_static_dir }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_FILENAME_FORMAT=" | ||||||
|  |       line: "PAPERLESS_FILENAME_FORMAT={{ paperlessng_filename_format }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_OCR_LANGUAGE=" | ||||||
|  |       line: "PAPERLESS_OCR_LANGUAGE={{ paperlessng_ocr_languages | join('+') }}" | ||||||
|  |     - regexp: "^#PAPERLESS_OCR_USER_ARG=" | ||||||
|  |       # TODO JSON dict required in conf? | ||||||
|  |       # https://paperless-ng.readthedocs.io/en/latest/configuration.html#ocr-settings | ||||||
|  |       line: "PAPERLESS_OCR_USER_ARG=\"{{ paperlessng_ocrmypdf_args }}{{ ' --jbig2-lossy' if  paperlessng_use_jbig2enc else '' }}\"" | ||||||
|  |     - regexp: "^#?PAPERLESS_TIME_ZONE=" | ||||||
|  |       line: "PAPERLESS_TIME_ZONE={{ paperlessng_time_zone }}" | ||||||
|  |   no_log: true | ||||||
|  |  | ||||||
|  | - name: configure paperless-ng database [sqlite] | ||||||
|  |   lineinfile: | ||||||
|  |     path: "{{ paperlessng_directory }}/paperless.conf" | ||||||
|  |     regexp: "^#?PAPERLESS_DBHOST=" | ||||||
|  |     state: absent | ||||||
|  |   when: paperlessng_db_type == 'sqlite' | ||||||
|  |  | ||||||
|  | - name: configure paperless-ng database [postgresql] | ||||||
|  |   lineinfile: | ||||||
|  |     path: "{{ paperlessng_directory }}/paperless.conf" | ||||||
|  |     regexp: "{{ item.regexp }}" | ||||||
|  |     line: "{{ item.line }}" | ||||||
|  |   with_items: | ||||||
|  |     - regexp: "^#?PAPERLESS_DBHOST=" | ||||||
|  |       line: "PAPERLESS_DBHOST={{ paperlessng_db_host }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_DBPORT=" | ||||||
|  |       line: "PAPERLESS_DBPORT={{ paperlessng_db_port }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_DBNAME=" | ||||||
|  |       line: "PAPERLESS_DBNAME={{ paperlessng_db_name }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_DBUSER=" | ||||||
|  |       line: "PAPERLESS_DBUSER={{ paperlessng_db_user }}" | ||||||
|  |     - regexp: "^#?PAPERLESS_DBPASS=" | ||||||
|  |       line: "PAPERLESS_DBPASS={{ paperlessng_db_pass }}" | ||||||
|  |   when: paperlessng_db_type == 'postgresql' | ||||||
|  |   no_log: true | ||||||
|  |  | ||||||
|  | - name: create paperlessng venv | ||||||
|  |   command: | ||||||
|  |     cmd: "python3 -m virtualenv {{ paperlessng_virtualenv }} -p /usr/bin/python3" | ||||||
|  |     creates: "{{ paperlessng_virtualenv }}" | ||||||
|  |  | ||||||
|  | - name: install paperlessng requirements | ||||||
|  |   pip: | ||||||
|  |     requirements: "{{ paperlessng_directory }}/requirements.txt" | ||||||
|  |     virtualenv: "{{ paperlessng_virtualenv }}" | ||||||
|  |     extra_args: --upgrade | ||||||
|  |  | ||||||
|  | - name: collect static files | ||||||
|  |   command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py collectstatic --clear --no-input" | ||||||
|  |  | ||||||
|  | - name: create database schema | ||||||
|  |   command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py migrate" | ||||||
|  |   register: database_schema | ||||||
|  |   changed_when: '"No migrations to apply." not in database_schema.stdout' | ||||||
|  |  | ||||||
|  | - name: create first paperless user | ||||||
|  |   # "manage.py createsuperuser" only works on interactive TTYs | ||||||
|  |   command: | | ||||||
|  |     {{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py shell -c " | ||||||
|  |     from django.contrib.auth.models import User | ||||||
|  |     from django.contrib.auth.hashers import get_hasher | ||||||
|  |  | ||||||
|  |     if User.objects.filter(username='{{ paperlessng_superuser_name }}').exists(): | ||||||
|  |         user = User.objects.get(username='{{ paperlessng_superuser_name }}') | ||||||
|  |         old = user.__dict__.copy() | ||||||
|  |  | ||||||
|  |         user.is_superuser = True | ||||||
|  |         user.email = '{{ paperlessng_superuser_email }}' | ||||||
|  |         user.set_password('{{ paperlessng_superuser_password }}') | ||||||
|  |         user.save() | ||||||
|  |         new = user.__dict__ | ||||||
|  |  | ||||||
|  |         algorithm, iterations, old_salt, old_hash = old['password'].split('$') | ||||||
|  |         new_password_old_salt = get_hasher(algorithm).encode(password='{{ paperlessng_superuser_password }}', salt=old_salt, iterations=int(iterations)) | ||||||
|  |         _, _, _, new_hash = new_password_old_salt.split('$') | ||||||
|  |         if not (old_hash == new_hash and old['is_superuser'] == new['is_superuser'] and old['email'] == new['email']): | ||||||
|  |             print('changed') | ||||||
|  |     else: | ||||||
|  |         User.objects.create_superuser('{{ paperlessng_superuser_name }}', '{{ paperlessng_superuser_email }}', '{{ paperlessng_superuser_password }}') | ||||||
|  |         print('changed') | ||||||
|  |     " | ||||||
|  |   register: superuser | ||||||
|  |   changed_when: superuser.stdout == 'changed' | ||||||
|  |   no_log: true | ||||||
|  |  | ||||||
|  | - name: configure ghostscript for PDF | ||||||
|  |   lineinfile: | ||||||
|  |     path: "/etc/ImageMagick-6/policy.xml" | ||||||
|  |     regexp: '<policy domain="coder" rights="none" pattern="PDF" />' | ||||||
|  |     line: '<policy domain="coder" rights="read|write" pattern="PDF" />' | ||||||
|  |  | ||||||
|  | - name: create paperless group | ||||||
|  |   group: | ||||||
|  |     name: "{{ paperlessng_system_group }}" | ||||||
|  |  | ||||||
|  | - name: create paperless user | ||||||
|  |   user: | ||||||
|  |     name: "{{ paperlessng_system_user }}" | ||||||
|  |     groups: | ||||||
|  |       - "{{ paperlessng_system_group }}" | ||||||
|  |     shell: /usr/sbin/nologin | ||||||
|  |     # GNUPG_HOME required due to paperless db.py | ||||||
|  |     create_home: yes | ||||||
|  |  | ||||||
|  | - name: configure systemd services | ||||||
|  |   ini_file: | ||||||
|  |     path: "{{ paperlessng_directory }}/scripts/{{ item[0] }}" | ||||||
|  |     section: "{{ item[1].section }}" | ||||||
|  |     option: "{{ item[1].option  }}" | ||||||
|  |     value: "{{ item[1].value }}" | ||||||
|  |   with_nested: | ||||||
|  |     - [ | ||||||
|  |         paperless-consumer.service, | ||||||
|  |         paperless-scheduler.service, | ||||||
|  |         paperless-webserver.service, | ||||||
|  |       ] | ||||||
|  |     - [ | ||||||
|  |         { | ||||||
|  |           section: "Service", | ||||||
|  |           option: "User", | ||||||
|  |           value: "{{ paperlessng_system_user }}", | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           section: "Service", | ||||||
|  |           option: "Group", | ||||||
|  |           value: "{{ paperlessng_system_group }}", | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           section: "Service", | ||||||
|  |           option: "WorkingDirectory", | ||||||
|  |           value: "{{ paperlessng_directory }}/src", | ||||||
|  |         }, | ||||||
|  |       ] | ||||||
|  |  | ||||||
|  | - name: configure paperless-consumer service | ||||||
|  |   ini_file: | ||||||
|  |     path: "{{ paperlessng_directory }}/scripts/paperless-consumer.service" | ||||||
|  |     section: "Service" | ||||||
|  |     option: "ExecStart" | ||||||
|  |     value: "{{ paperlessng_virtualenv }}/bin/python3 manage.py document_consumer" | ||||||
|  |  | ||||||
|  | - name: configure paperless-scheduler service | ||||||
|  |   ini_file: | ||||||
|  |     path: "{{ paperlessng_directory }}/scripts/paperless-scheduler.service" | ||||||
|  |     section: "Service" | ||||||
|  |     option: "ExecStart" | ||||||
|  |     value: "{{ paperlessng_virtualenv }}/bin/python3 manage.py qcluster" | ||||||
|  |  | ||||||
|  | - name: configure paperless-webserver service | ||||||
|  |   ini_file: | ||||||
|  |     path: "{{ paperlessng_directory }}/scripts/paperless-webserver.service" | ||||||
|  |     section: "Service" | ||||||
|  |     option: "ExecStart" | ||||||
|  |     value: "{{ paperlessng_virtualenv }}/bin/gunicorn paperless.wsgi -w 2 -b {{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}" | ||||||
|  |  | ||||||
|  | - name: copy systemd services | ||||||
|  |   copy: | ||||||
|  |     src: "{{ paperlessng_directory }}/scripts/{{ item }}" | ||||||
|  |     dest: "/etc/systemd/system/{{ item }}" | ||||||
|  |     remote_src: yes | ||||||
|  |   with_items: | ||||||
|  |     - paperless-consumer.service | ||||||
|  |     - paperless-scheduler.service | ||||||
|  |     - paperless-webserver.service | ||||||
|  |   register: paperless_services | ||||||
|  |  | ||||||
|  | - name: reload systemd daemon | ||||||
|  |   systemd: | ||||||
|  |     name: "{{ item }}" | ||||||
|  |     state: restarted | ||||||
|  |     daemon_reload: yes | ||||||
|  |   with_items: | ||||||
|  |     - paperless-consumer | ||||||
|  |     - paperless-scheduler | ||||||
|  |     - paperless-webserver | ||||||
|  |   when: paperless_services.changed | ||||||
|  |  | ||||||
|  | - name: enable paperlessng services | ||||||
|  |   systemd: | ||||||
|  |     name: "{{ item }}" | ||||||
|  |     enabled: yes | ||||||
|  |     masked: no | ||||||
|  |     state: started | ||||||
|  |   with_items: | ||||||
|  |     - paperless-consumer | ||||||
|  |     - paperless-scheduler | ||||||
|  |     - paperless-webserver | ||||||
		Reference in New Issue
	
	Block a user
	 Fabian Koller
					Fabian Koller