paperless-ngx-install.sh 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #!/usr/bin/env bash
  2. YW=`echo "\033[33m"`
  3. RD=`echo "\033[01;31m"`
  4. BL=`echo "\033[36m"`
  5. GN=`echo "\033[1;92m"`
  6. CL=`echo "\033[m"`
  7. RETRY_NUM=10
  8. RETRY_EVERY=3
  9. NUM=$RETRY_NUM
  10. CM="${GN}✓${CL}"
  11. CROSS="${RD}✗${CL}"
  12. BFR="\\r\\033[K"
  13. HOLD="-"
  14. set -o errexit
  15. set -o errtrace
  16. set -o nounset
  17. set -o pipefail
  18. shopt -s expand_aliases
  19. alias die='EXIT=$? LINE=$LINENO error_exit'
  20. trap die ERR
  21. function error_exit() {
  22. trap - ERR
  23. local reason="Unknown failure occurred."
  24. local msg="${1:-$reason}"
  25. local flag="${RD}‼ ERROR ${CL}$EXIT@$LINE"
  26. echo -e "$flag $msg" 1>&2
  27. exit $EXIT
  28. }
  29. function msg_info() {
  30. local msg="$1"
  31. echo -ne " ${HOLD} ${YW}${msg}..."
  32. }
  33. function msg_ok() {
  34. local msg="$1"
  35. echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
  36. }
  37. function msg_error() {
  38. local msg="$1"
  39. echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
  40. }
  41. msg_info "Setting up Container OS "
  42. sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen
  43. locale-gen >/dev/null
  44. while [ "$(hostname -I)" = "" ]; do
  45. 1>&2 echo -en "${CROSS}${RD} No Network! "
  46. sleep $RETRY_EVERY
  47. ((NUM--))
  48. if [ $NUM -eq 0 ]
  49. then
  50. 1>&2 echo -e "${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
  51. exit 1
  52. fi
  53. done
  54. msg_ok "Set up Container OS"
  55. msg_ok "Network Connected: ${BL}$(hostname -I)"
  56. if nc -zw1 8.8.8.8 443; then msg_ok "Internet Connected"; else msg_error "Internet NOT Connected"; exit 1; fi;
  57. RESOLVEDIP=$(nslookup "github.com" | awk -F':' '/^Address: / { matched = 1 } matched { print $2}' | xargs)
  58. if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi;
  59. msg_info "Updating Container OS"
  60. apt-get update &>/dev/null
  61. apt-get -y upgrade &>/dev/null
  62. msg_ok "Updated Container OS"
  63. msg_info "Installing Paperless-ngx Dependencies"
  64. apt-get install -y --no-install-recommends \
  65. python3 \
  66. python3-pip \
  67. python3-dev \
  68. imagemagick \
  69. fonts-liberation \
  70. optipng \
  71. gnupg \
  72. libpq-dev \
  73. libmagic-dev \
  74. mime-support \
  75. libzbar0 \
  76. poppler-utils \
  77. sudo &>/dev/null
  78. msg_ok "Installed Paperless-ngx Dependencies"
  79. msg_info "Installing OCR Dependencies"
  80. apt-get install -y --no-install-recommends \
  81. unpaper \
  82. ghostscript \
  83. icc-profiles-free \
  84. qpdf \
  85. liblept5 \
  86. libxml2 \
  87. pngquant \
  88. zlib1g \
  89. tesseract-ocr \
  90. tesseract-ocr-eng &>/dev/null
  91. msg_ok "Installed OCR Dependencies"
  92. msg_info "Installing Extra Dependencies"
  93. apt-get install -y --no-install-recommends \
  94. redis \
  95. postgresql \
  96. build-essential \
  97. python3-setuptools \
  98. python3-wheel &>/dev/null
  99. msg_ok "Installed Extra Dependencies"
  100. msg_info "Installing JBIG2"
  101. apt-get install -y --no-install-recommends \
  102. automake \
  103. libtool \
  104. pkg-config \
  105. git \
  106. curl \
  107. libtiff-dev \
  108. libpng-dev \
  109. libleptonica-dev &>/dev/null
  110. git clone https://github.com/agl/jbig2enc /opt/jbig2enc &>/dev/null
  111. cd /opt/jbig2enc
  112. /bin/bash -c "./autogen.sh" &>/dev/null && \
  113. /bin/bash -c "./configure && make" &>/dev/null && \
  114. /bin/bash -c "make install" &>/dev/null
  115. rm -rf /opt/jbig2enc
  116. msg_ok "Installed JBIG2"
  117. msg_info "Downloading Paperless-ngx"
  118. Paperlessngx=$(wget -q https://github.com/paperless-ngx/paperless-ngx/releases/latest -O - | grep "title>Release" | cut -d " " -f 5)
  119. cd /opt && \
  120. wget https://github.com/paperless-ngx/paperless-ngx/releases/download/$Paperlessngx/paperless-ngx-$Paperlessngx.tar.xz &>/dev/null && \
  121. tar -xf paperless-ngx-$Paperlessngx.tar.xz -C /opt/ &>/dev/null && \
  122. mv paperless-ngx paperless && \
  123. rm paperless-ngx-$Paperlessngx.tar.xz
  124. cd /opt/paperless
  125. ## python 3.10+ doesn't like the '-e', so we remove it from this the requirements file
  126. sed -i -e 's|-e git+https://github.com/paperless-ngx/django-q.git|git+https://github.com/paperless-ngx/django-q.git|' /opt/paperless/requirements.txt
  127. /usr/bin/python3 -m pip install --upgrade pip &>/dev/null
  128. /usr/bin/python3 -m pip install -r requirements.txt &>/dev/null
  129. msg_ok "Downloaded Paperless-ngx"
  130. msg_info "Setting up database"
  131. DB_USER=paperless
  132. DB_PASS="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13)"
  133. DB_NAME=paperlessdb
  134. sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" &>/dev/null
  135. sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER TEMPLATE template0;" &>/dev/null
  136. echo "Paperless-ngx Database User" >> ~/paperless.creds
  137. echo $DB_USER >> ~/paperless.creds
  138. echo "Paperless-ngx Database Password" >> ~/paperless.creds
  139. echo $DB_PASS >> ~/paperless.creds
  140. echo "Paperless-ngx Database Name" >> ~/paperless.creds
  141. echo $DB_NAME >> ~/paperless.creds
  142. /bin/bash -c "mkdir -p {consume,media}"
  143. sed -i -e 's|#PAPERLESS_DBNAME=paperless|PAPERLESS_DBNAME=paperlessdb|' /opt/paperless/paperless.conf
  144. sed -i -e "s|#PAPERLESS_DBPASS=paperless|PAPERLESS_DBPASS=$DB_PASS|" /opt/paperless/paperless.conf
  145. SECRET_KEY="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)"
  146. sed -i -e "s|#PAPERLESS_SECRET_KEY=change-me|PAPERLESS_SECRET_KEY=$SECRET_KEY|" /opt/paperless/paperless.conf
  147. cd /opt/paperless/src
  148. /usr/bin/python3 manage.py migrate &>/dev/null
  149. msg_ok "Set up database"
  150. msg_info "Setting up admin Paperless-ngx User & Password"
  151. ## From https://github.com/linuxserver/docker-paperless-ngx/blob/main/root/etc/cont-init.d/99-migrations
  152. cat << EOF | python3 /opt/paperless/src/manage.py shell
  153. from django.contrib.auth import get_user_model
  154. UserModel = get_user_model()
  155. if len(UserModel.objects.all()) == 1:
  156. user = UserModel.objects.create_user('admin', password='$DB_PASS')
  157. user.is_superuser = True
  158. user.is_staff = True
  159. user.save()
  160. EOF
  161. echo "" >> ~/paperless.creds
  162. echo "Paperless-ngx WebUI User" >> ~/paperless.creds
  163. echo admin >> ~/paperless.creds
  164. echo "Paperless-ngx WebUI Password" >> ~/paperless.creds
  165. echo $DB_PASS >> ~/paperless.creds
  166. msg_ok "Set up admin Paperless-ngx User & Password"
  167. cat << EOF > /etc/systemd/system/paperless-scheduler.service
  168. [Unit]
  169. Description=Paperless consumer
  170. Requires=redis.service
  171. [Service]
  172. WorkingDirectory=/opt/paperless/src
  173. ExecStart=python3 manage.py qcluster
  174. [Install]
  175. WantedBy=multi-user.target
  176. EOF
  177. cat << EOF > /etc/systemd/system/paperless-consumer.service
  178. [Unit]
  179. Description=Paperless consumer
  180. Requires=redis.service
  181. [Service]
  182. WorkingDirectory=/opt/paperless/src
  183. ExecStart=python3 manage.py document_consumer
  184. [Install]
  185. WantedBy=multi-user.target
  186. EOF
  187. cat << EOF > /etc/systemd/system/paperless-webserver.service
  188. [Unit]
  189. Description=Paperless webserver
  190. After=network.target
  191. Wants=network.target
  192. Requires=redis.service
  193. [Service]
  194. WorkingDirectory=/opt/paperless/src
  195. ExecStart=/usr/local/bin/gunicorn -c /opt/paperless/gunicorn.conf.py paperless.asgi:application
  196. [Install]
  197. WantedBy=multi-user.target
  198. EOF
  199. sed -i -e 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' /etc/ImageMagick-6/policy.xml
  200. systemctl daemon-reload
  201. systemctl enable --now paperless-consumer paperless-webserver paperless-scheduler &>/dev/null
  202. msg_ok "Finished installing Paperless-ngx"
  203. PASS=$(grep -w "root" /etc/shadow | cut -b6);
  204. if [[ $PASS != $ ]]; then
  205. msg_info "Customizing Container"
  206. rm /etc/motd
  207. rm /etc/update-motd.d/10-uname
  208. touch ~/.hushlogin
  209. GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
  210. mkdir -p $(dirname $GETTY_OVERRIDE)
  211. cat << EOF > $GETTY_OVERRIDE
  212. [Service]
  213. ExecStart=
  214. ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
  215. EOF
  216. systemctl daemon-reload
  217. systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
  218. msg_ok "Customized Container"
  219. fi
  220. msg_info "Cleaning up"
  221. apt-get autoremove >/dev/null
  222. apt-get autoclean >/dev/null
  223. msg_ok "Cleaned"