diff --git a/ct/paperless-ngx.sh b/ct/paperless-ngx.sh index da6dffd0d..10fe9b37c 100644 --- a/ct/paperless-ngx.sh +++ b/ct/paperless-ngx.sh @@ -49,22 +49,44 @@ function update_script() { fi fi - RELEASE="v2.20.15" - if check_for_gh_release "paperless" "paperless-ngx/paperless-ngx" "${RELEASE}" "v3 needs further testing"; then + local PAPERLESS_INSTALLED_VERSION="" BRIDGE_UPDATE=0 + [[ -f ~/.paperless ]] && PAPERLESS_INSTALLED_VERSION="$(<~/.paperless)" + PAPERLESS_INSTALLED_VERSION="${PAPERLESS_INSTALLED_VERSION#v}" + if [[ "$PAPERLESS_INSTALLED_VERSION" == 2.* && "$PAPERLESS_INSTALLED_VERSION" != "2.20.15" ]]; then + BRIDGE_UPDATE=1 + fi + + if check_for_gh_release "paperless" "paperless-ngx/paperless-ngx"; then + if [[ "$PAPERLESS_INSTALLED_VERSION" == "2.20.15" ]]; then + msg_warn "Paperless-ngx v3 does not support encrypted documents anymore." + echo -e "${GATEWAY}${BGN}https://docs.paperless-ngx.com/migration-v3/#encryption-support${CL}" + msg_warn "Before continuing make sure that you do not use encryption or have decrypted all documents." + echo "" + read -rp "Do you want to continue with the update? (y/N): " MIGRATE + echo + if [[ ! "$MIGRATE" =~ ^[Yy]$ ]]; then + msg_info "Update aborted. Decrypt all documents before upgrading to v3." + exit 0 + fi + fi + msg_info "Stopping all Paperless-ngx Services" systemctl stop paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue msg_ok "Stopped all Paperless-ngx Services" if grep -q "uv run" /etc/systemd/system/paperless-webserver.service; then - msg_info "Backing up configuration" local BACKUP_DIR="/opt/paperless_backup_$$" mkdir -p "$BACKUP_DIR" [[ -f /opt/paperless/paperless.conf ]] && cp /opt/paperless/paperless.conf "$BACKUP_DIR/" msg_ok "Backup completed to $BACKUP_DIR" - PYTHON_VERSION="3.13" setup_uv - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "${RELEASE}" "/opt/paperless" "paperless*tar.xz" + PYTHON_VERSION="3.13" setup_uv + if ((BRIDGE_UPDATE)); then + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "v2.20.15" "/opt/paperless" "paperless*tar.xz" + else + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "latest" "/opt/paperless" "paperless*tar.xz" + fi CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jbig2enc" "ie13/jbig2enc" "tarball" "latest" "/opt/jbig2enc" . /etc/os-release @@ -73,18 +95,94 @@ function update_script() { else ensure_dependencies ghostscript fi + ensure_dependencies gnupg + + cp -r "$BACKUP_DIR"/* /opt/paperless/ + if ((BRIDGE_UPDATE == 0)) && [[ "$PAPERLESS_INSTALLED_VERSION" == 2.* ]]; then + msg_info "Migrating Paperless-ngx v2 configuration to v3" + PAPERLESS_CONF="/opt/paperless/paperless.conf" + + SECRET_KEY_CURRENT="$(sed -n 's|^PAPERLESS_SECRET_KEY=||p' "$PAPERLESS_CONF" | tail -n1)" + DBENGINE="$(sed -n 's|^PAPERLESS_DBENGINE=||p' "$PAPERLESS_CONF" | tail -n1)" + DB_OPTIONS_DEPRECATED="$(sed -n '/^PAPERLESS_DBSSLMODE=/p;/^PAPERLESS_DBSSLROOTCERT=/p;/^PAPERLESS_DBSSLCERT=/p;/^PAPERLESS_DBSSLKEY=/p;/^PAPERLESS_DB_POOLSIZE=/p;/^PAPERLESS_DB_TIMEOUT=/p' "$PAPERLESS_CONF")" + CONSUMER_POLLING="$(sed -n 's|^PAPERLESS_CONSUMER_POLLING=||p' "$PAPERLESS_CONF" | tail -n1)" + CONSUMER_POLLING_INTERVAL="$(sed -n 's|^PAPERLESS_CONSUMER_POLLING_INTERVAL=||p' "$PAPERLESS_CONF" | tail -n1)" + CONSUMER_INOTIFY_DELAY="$(sed -n 's|^PAPERLESS_CONSUMER_INOTIFY_DELAY=||p' "$PAPERLESS_CONF" | tail -n1)" + CONSUMER_STABILITY_DELAY="$(sed -n 's|^PAPERLESS_CONSUMER_STABILITY_DELAY=||p' "$PAPERLESS_CONF" | tail -n1)" + OCR_MODE="$(sed -n 's|^PAPERLESS_OCR_MODE=||p' "$PAPERLESS_CONF" | tail -n1)" + OCR_SKIP_ARCHIVE="$(sed -n 's|^PAPERLESS_OCR_SKIP_ARCHIVE_FILE=||p' "$PAPERLESS_CONF" | tail -n1)" + ARCHIVE_FILE_GENERATION="$(sed -n 's|^PAPERLESS_ARCHIVE_FILE_GENERATION=||p' "$PAPERLESS_CONF" | tail -n1)" + CONSUMER_DELETE_DUPLICATES="$(sed -n 's|^PAPERLESS_CONSUMER_DELETE_DUPLICATES=||p' "$PAPERLESS_CONF" | tail -n1)" + + sed -i \ + -e '/^PAPERLESS_CONSUMER_POLLING=/d' \ + -e '/^PAPERLESS_CONSUMER_INOTIFY_DELAY=/d' \ + -e '/^PAPERLESS_CONSUMER_POLLING_DELAY=/d' \ + -e '/^PAPERLESS_CONSUMER_POLLING_RETRY_COUNT=/d' \ + -e '/^PAPERLESS_CONSUMER_BARCODE_SCANNER=/d' \ + -e '/^PAPERLESS_PASSPHRASE=/d' \ + -e '/^PAPERLESS_OCR_SKIP_ARCHIVE_FILE=/d' \ + -e 's|^PAPERLESS_OCR_MODE="\?skip"\?$|PAPERLESS_OCR_MODE=auto|' \ + -e 's|^PAPERLESS_OCR_MODE="\?skip_noarchive"\?$|PAPERLESS_OCR_MODE=auto|' \ + "$PAPERLESS_CONF" + + if [[ -n "$DB_OPTIONS_DEPRECATED" ]]; then + msg_warn "Deprecated Paperless DB options detected; migrate them manually to PAPERLESS_DB_OPTIONS." + echo -e "${GATEWAY}${BGN}https://docs.paperless-ngx.com/migration-v3/#database-advanced-options${CL}" + fi + if [[ -z "$SECRET_KEY_CURRENT" || "$SECRET_KEY_CURRENT" == "change-me" ]]; then + SECRET_KEY="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" + sed -i \ + -e '/^#\?PAPERLESS_SECRET_KEY=/d' \ + -e "\$a\\PAPERLESS_SECRET_KEY=$SECRET_KEY" \ + "$PAPERLESS_CONF" + printf "Paperless-ngx Secret Key: %s\n" "$SECRET_KEY" >>~/paperless-ngx.creds + fi + [[ -z "$DBENGINE" ]] && sed -i '$a\PAPERLESS_DBENGINE=postgresql' "$PAPERLESS_CONF" + [[ -n "$CONSUMER_POLLING" && -z "$CONSUMER_POLLING_INTERVAL" ]] && + sed -i "\$a\\PAPERLESS_CONSUMER_POLLING_INTERVAL=$CONSUMER_POLLING" "$PAPERLESS_CONF" + [[ -n "$CONSUMER_INOTIFY_DELAY" && -z "$CONSUMER_STABILITY_DELAY" ]] && + sed -i "\$a\\PAPERLESS_CONSUMER_STABILITY_DELAY=$CONSUMER_INOTIFY_DELAY" "$PAPERLESS_CONF" + [[ -z "$CONSUMER_DELETE_DUPLICATES" ]] && + sed -i '$a\PAPERLESS_CONSUMER_DELETE_DUPLICATES=true' "$PAPERLESS_CONF" + if [[ -z "$ARCHIVE_FILE_GENERATION" ]]; then + if [[ "$OCR_MODE" == "skip_noarchive" || "$OCR_MODE" == "\"skip_noarchive\"" ]]; then + sed -i '$a\PAPERLESS_ARCHIVE_FILE_GENERATION=never' "$PAPERLESS_CONF" + elif [[ "$OCR_SKIP_ARCHIVE" == "never" || "$OCR_SKIP_ARCHIVE" == "\"never\"" ]]; then + sed -i '$a\PAPERLESS_ARCHIVE_FILE_GENERATION=always' "$PAPERLESS_CONF" + elif [[ "$OCR_SKIP_ARCHIVE" == "with_text" || "$OCR_SKIP_ARCHIVE" == "\"with_text\"" ]]; then + sed -i '$a\PAPERLESS_ARCHIVE_FILE_GENERATION=auto' "$PAPERLESS_CONF" + elif [[ "$OCR_SKIP_ARCHIVE" == "always" || "$OCR_SKIP_ARCHIVE" == "\"always\"" ]]; then + sed -i '$a\PAPERLESS_ARCHIVE_FILE_GENERATION=never' "$PAPERLESS_CONF" + fi + fi + [[ -n "$(sed -n '/^PAPERLESS_CONSUMER_IGNORE_PATTERNS=/p' "$PAPERLESS_CONF")" ]] && + msg_warn "PAPERLESS_CONSUMER_IGNORE_PATTERNS now uses regex patterns; please verify custom values." + [[ -n "$(sed -n '/^PAPERLESS_PRE_CONSUME_SCRIPT=/p;/^PAPERLESS_POST_CONSUME_SCRIPT=/p' "$PAPERLESS_CONF")" ]] && + msg_warn "Pre/post consume scripts no longer receive positional arguments in v3; please verify custom scripts." + msg_ok "Migrated Paperless-ngx configuration" + fi msg_info "Updating Paperless-ngx" - cp -r "$BACKUP_DIR"/* /opt/paperless/ + if ((BRIDGE_UPDATE == 0)); then + sed -i 's|^ExecStart=.*|ExecStart=uv run -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application"|' /etc/systemd/system/paperless-webserver.service + $STD systemctl daemon-reload + fi cd /opt/paperless $STD uv sync --all-extras cd /opt/paperless/src $STD uv run -- python manage.py migrate msg_ok "Updated Paperless-ngx" + if ((BRIDGE_UPDATE == 0)) && [[ "$PAPERLESS_INSTALLED_VERSION" == "2.20.15" ]]; then + $STD apt -y purge libzbar0t64 libzbar0 2>/dev/null || true + $STD apt -y autoremove 2>/dev/null || true + fi + rm -rf "$BACKUP_DIR" else + BRIDGE_UPDATE=1 msg_warn "You are about to migrate your Paperless-ngx installation to uv!" msg_custom "🔒" "It is strongly recommended to take a Proxmox snapshot first:" echo -e " 1. Stop the container: pct stop " @@ -139,7 +237,7 @@ function update_script() { msg_ok "Backup completed to $BACKUP_DIR" PYTHON_VERSION="3.13" setup_uv - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "${RELEASE}" "/opt/paperless" "paperless*tar.xz" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "v2.20.15" "/opt/paperless" "paperless*tar.xz" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jbig2enc" "ie13/jbig2enc" "tarball" "latest" "/opt/jbig2enc" . /etc/os-release @@ -150,14 +248,15 @@ function update_script() { ensure_dependencies ghostscript msg_ok "Installed Ghostscript" fi + ensure_dependencies gnupg - msg_info "Updating Paperless-ngx" + msg_info "Updating Paperless-ngx to v2.20.15" cp -r "$BACKUP_DIR"/* /opt/paperless/ cd /opt/paperless $STD uv sync --all-extras cd /opt/paperless/src $STD uv run -- python manage.py migrate - msg_ok "Paperless-ngx migration and update completed" + msg_ok "Migrated to uv and updated to v2.20.15 (required before v3)" rm -rf "$BACKUP_DIR" if [[ -d /opt/paperless/backup ]]; then @@ -172,6 +271,10 @@ function update_script() { systemctl start paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue sleep 1 msg_ok "Started all Paperless-ngx Services" + if ((BRIDGE_UPDATE)); then + msg_custom "â„šī¸" "${YW}" "Paperless-ngx is now on v2.20.15. Run the update again to upgrade to v3." + exit + fi msg_ok "Updated successfully!" fi exit diff --git a/install/paperless-ngx-install.sh b/install/paperless-ngx-install.sh index 19f33a70b..f26c6f9ca 100644 --- a/install/paperless-ngx-install.sh +++ b/install/paperless-ngx-install.sh @@ -19,10 +19,10 @@ $STD apt install -y \ build-essential \ imagemagick \ fonts-liberation \ + gnupg \ optipng \ libpq-dev \ libmagic-dev \ - libzbar0t64 \ poppler-utils \ default-libmysqlclient-dev \ automake \ @@ -43,16 +43,15 @@ $STD apt install -y \ ghostscript msg_ok "Installed Dependencies" -PG_VERSION="16" setup_postgresql +PG_VERSION="18" setup_postgresql PG_DB_NAME="paperlessdb" PG_DB_USER="paperless" setup_postgresql_db PYTHON_VERSION="3.13" setup_uv -fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "v2.20.15" "/opt/paperless" "paperless*tar.xz" +fetch_and_deploy_gh_release "paperless" "paperless-ngx/paperless-ngx" "prebuild" "latest" "/opt/paperless" "paperless*tar.xz" msg_info "Setup Paperless-ngx" cd /opt/paperless rm -rf /opt/paperless/docker $STD uv sync --all-extras -curl -fsSL "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/paperless.conf.example" -o /opt/paperless/paperless.conf mkdir -p /opt/paperless_data/{consume,data,media,trash} mkdir -p /opt/paperless/static SECRET_KEY="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)" @@ -69,12 +68,12 @@ sed -i \ -e "s|#PAPERLESS_MEDIA_ROOT=../media|PAPERLESS_MEDIA_ROOT=/opt/paperless_data/media|" \ -e "s|#PAPERLESS_EMPTY_TRASH_DIR=|PAPERLESS_EMPTY_TRASH_DIR=/opt/paperless_data/trash|" \ -e "s|#PAPERLESS_STATICDIR=../static|PAPERLESS_STATICDIR=/opt/paperless/static|" \ - -e 's|#PAPERLESS_DBHOST=localhost|PAPERLESS_DBHOST=localhost|' \ + -e 's|#PAPERLESS_DBHOST=localhost|PAPERLESS_DBENGINE=postgresql\nPAPERLESS_DBHOST=localhost|' \ -e 's|#PAPERLESS_DBPORT=5432|PAPERLESS_DBPORT=5432|' \ -e "s|#PAPERLESS_DBNAME=paperless|PAPERLESS_DBNAME=$PG_DB_NAME|" \ -e "s|#PAPERLESS_DBUSER=paperless|PAPERLESS_DBUSER=$PG_DB_USER|" \ -e "s|#PAPERLESS_DBPASS=paperless|PAPERLESS_DBPASS=$PG_DB_PASS|" \ - -e "s|#PAPERLESS_SECRET_KEY=change-me|PAPERLESS_SECRET_KEY=$SECRET_KEY|" \ + -e "s|PAPERLESS_SECRET_KEY=change-me|PAPERLESS_SECRET_KEY=$SECRET_KEY|" \ /opt/paperless/paperless.conf cd /opt/paperless/src set -a @@ -152,7 +151,7 @@ Requires=redis.service [Service] WorkingDirectory=/opt/paperless/src -ExecStart=uv run -- granian --interface asgi --ws "paperless.asgi:application" +ExecStart=uv run -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application" Environment=GRANIAN_HOST=:: Environment=GRANIAN_PORT=8000 Environment=GRANIAN_WORKERS=1