searx.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #!/usr/bin/env bash
  2. # -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
  3. # shellcheck disable=SC2119
  4. # shellcheck source=utils/lib.sh
  5. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  6. # ----------------------------------------------------------------------------
  7. # config
  8. # ----------------------------------------------------------------------------
  9. SERVICE_NAME="searx"
  10. SERVICE_USER="${SERVICE_NAME}"
  11. # shellcheck disable=SC2034
  12. SERVICE_GROUP="${SERVICE_USER}"
  13. SERVICE_HOME="/home/${SERVICE_USER}"
  14. # shellcheck disable=SC2034
  15. SEARX_URL="127.0.0.1:8888"
  16. SEARX_GIT_URL="https://github.com/asciimoo/searx.git"
  17. SEARX_GIT_BRANCH="master"
  18. # FIXME: Arch Linux & RHEL should be added
  19. SEARX_APT_PACKAGES="\
  20. libapache2-mod-uwsgi uwsgi uwsgi-plugin-python3 \
  21. git build-essential libxslt-dev python3-dev python3-babel zlib1g-dev \
  22. libffi-dev libssl-dev"
  23. SEARX_PYENV="${SERVICE_HOME}/searx-pyenv"
  24. SEARX_SRC="${SERVICE_HOME}/searx-src"
  25. SEARX_SETTINGS="${SEARX_SRC}/searx/settings.yml"
  26. SEARX_INSTANCE_NAME="${SEARX_INSTANCE_NAME:-searx@$(uname -n)}"
  27. SEARX_UWSGI_APP="${uWSGI_SETUP}/apps-available/searx.ini"
  28. # shellcheck disable=SC2034
  29. CONFIG_FILES=(
  30. "${SEARX_UWSGI_APP}"
  31. )
  32. # shellcheck disable=SC2034
  33. CONFIG_BACKUP_ENCRYPTED=(
  34. "${SEARX_SETTINGS}"
  35. )
  36. # ----------------------------------------------------------------------------
  37. usage(){
  38. # ----------------------------------------------------------------------------
  39. # shellcheck disable=SC1117
  40. cat <<EOF
  41. usage:
  42. $(basename "$0") shell
  43. $(basename "$0") install [all|user|pyenv|searx-src]
  44. $(basename "$0") update [searx]
  45. $(basename "$0") remove [all|user|pyenv|searx-src]
  46. $(basename "$0") activate [service]
  47. $(basename "$0") deactivate [service]
  48. $(basename "$0") show [service]
  49. shell
  50. start interactive shell from user ${SERVICE_USER}
  51. install / remove
  52. all: complete (de-) installation of searx service
  53. user: add/remove service user '$SERVICE_USER' at $SERVICE_HOME
  54. searx-src: clone $SEARX_GIT_URL
  55. pyenv: create/remove virtualenv (python) in $SEARX_PYENV
  56. update searx
  57. Update searx installation of user ${SERVICE_USER}
  58. activate
  59. activate and start service daemon (systemd unit)
  60. deactivate service
  61. stop and deactivate service daemon (systemd unit)
  62. show service
  63. show service status and log
  64. EOF
  65. [ ! -z ${1+x} ] && echo -e "$1"
  66. }
  67. main(){
  68. rst_title "$SERVICE_NAME" part
  69. local _usage="ERROR: unknown or missing $1 command $2"
  70. case $1 in
  71. --source-only) ;;
  72. -h|--help) usage; exit 0;;
  73. shell)
  74. sudo_or_exit
  75. interactive_shell
  76. ;;
  77. show)
  78. case $2 in
  79. service)
  80. sudo_or_exit
  81. show_service
  82. ;;
  83. *) usage "$_usage"; exit 42;;
  84. esac ;;
  85. install)
  86. sudo_or_exit
  87. case $2 in
  88. all) install_all ;;
  89. user) assert_user ;;
  90. pyenv) create_pyenv ;;
  91. searx-src) clone_searx ;;
  92. *) usage "$_usage"; exit 42;;
  93. esac ;;
  94. update)
  95. sudo_or_exit
  96. case $2 in
  97. searx) update_searx;;
  98. *) usage "$_usage"; exit 42;;
  99. esac ;;
  100. remove)
  101. sudo_or_exit
  102. case $2 in
  103. all) remove_all;;
  104. user) remove_user ;;
  105. pyenv) remove_pyenv ;;
  106. searx-src) remove_searx ;;
  107. *) usage "$_usage"; exit 42;;
  108. esac ;;
  109. activate)
  110. sudo_or_exit
  111. case $2 in
  112. service) activate_service ;;
  113. *) usage "$_usage"; exit 42;;
  114. esac ;;
  115. deactivate)
  116. sudo_or_exit
  117. case $2 in
  118. service) deactivate_service ;;
  119. *) usage "$_usage"; exit 42;;
  120. esac ;;
  121. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  122. esac
  123. }
  124. _service_prefix=" |$SERVICE_USER| "
  125. install_all() {
  126. rst_title "Install $SERVICE_NAME (service)"
  127. pkg_install "$SEARX_APT_PACKAGES"
  128. wait_key
  129. assert_user
  130. wait_key
  131. clone_searx
  132. wait_key
  133. create_pyenv
  134. wait_key
  135. configure_searx
  136. wait_key
  137. test_local_searx
  138. wait_key
  139. install_searx_uwsgi
  140. wait_key
  141. # ToDo ...
  142. # install_apache_site
  143. # test_public_searx
  144. # info_msg "searX --> https://${SEARX_APACHE_DOMAIN}${SEARX_APACHE_URL}"
  145. }
  146. update_searx() {
  147. rst_title "Update searx instance"
  148. echo
  149. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  150. cd ${SEARX_SRC}
  151. cp -f ${SEARX_SETTINGS} ${SEARX_SETTINGS}.backup
  152. git stash push -m "BACKUP -- 'update server' at ($(date))"
  153. git checkout -b $SEARX_GIT_BRANCH" --track "$SEARX_GIT_BRANCH"
  154. git pull "$SEARX_GIT_BRANCH"
  155. ${SEARX_SRC}/manage.sh update_packages
  156. EOF
  157. configure_searx
  158. rst_title "${SEARX_SETTINGS}" section
  159. rstBlock 'Diff between new setting file (<) and backup (>):'
  160. echo
  161. diff "$SEARX_SETTINGS}" "${SEARX_SETTINGS}.backup"
  162. local action
  163. choose_one action "What should happen to the settings file? " \
  164. "keep new configuration" \
  165. "revert to the old configuration (backup file)" \
  166. "start interactiv shell"
  167. case $action in
  168. "keep new configuration")
  169. info_msg "continue using new settings file"
  170. ;;
  171. "revert to the old configuration (backup file)")
  172. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  173. cp -f ${SEARX_SETTINGS}.backup ${SEARX_SETTINGS}
  174. EOF
  175. ;;
  176. "start interactiv shell")
  177. interactive_shell
  178. ;;
  179. esac
  180. chown "${SERVICE_USER}:${SERVICE_USER}" "${SEARX_SETTINGS}"
  181. # shellcheck disable=SC2016
  182. rst_para 'Diff between local modified settings (<) and $SEARX_GIT_BRANCH branch (>):'
  183. echo
  184. git_diff
  185. wait_key
  186. uWSGI_restart
  187. }
  188. remove_all() {
  189. rst_title "De-Install $SERVICE_NAME (service)"
  190. if ! ask_yn "Do you really want to deinstall $SERVICE_NAME?"; then
  191. return
  192. fi
  193. remove_searx_uwsgi
  194. wait_key
  195. remove_user
  196. }
  197. assert_user() {
  198. rst_title "user $SERVICE_USER" section
  199. echo
  200. tee_stderr 1 <<EOF | bash | prefix_stdout
  201. sudo -H adduser --shell /bin/bash --system --home "$SERVICE_HOME" \
  202. --disabled-password --group --gecos 'searx' $SERVICE_USER
  203. sudo -H usermod -a -G shadow $SERVICE_USER
  204. groups $SERVICE_USER
  205. EOF
  206. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  207. #export SERVICE_HOME
  208. #echo "export SERVICE_HOME=$SERVICE_HOME"
  209. }
  210. remove_user() {
  211. rst_title "Drop $SERVICE_USER HOME" section
  212. if ask_yn "Do you really want to drop $SERVICE_USER home folder?"; then
  213. userdel -r -f "$SERVICE_USER" 2>&1 | prefix_stdout
  214. else
  215. rst_para "Leave HOME folder $(du -sh "$SERVICE_HOME") unchanged."
  216. fi
  217. }
  218. # shellcheck disable=SC2164
  219. clone_searx(){
  220. rst_title "Clone searx sources" section
  221. echo
  222. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  223. if [[ ! "${SERVICE_HOME}" ]]; then
  224. err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"
  225. return 42
  226. fi
  227. export SERVICE_HOME
  228. git_clone "$SEARX_GIT_URL" "$SEARX_SRC" \
  229. "$SEARX_GIT_BRANCH" "$SERVICE_USER"
  230. pushd "${SEARX_SRC}" > /dev/null
  231. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  232. cd "${SEARX_SRC}"
  233. git config user.email "$ADMIN_EMAIL"
  234. git config user.name "$ADMIN_NAME"
  235. git config --list
  236. EOF
  237. popd > /dev/null
  238. }
  239. remove_searx() {
  240. rst_title "Drop searx sources" section
  241. if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then
  242. rm -rf "$SEARX_SRC"
  243. else
  244. rst_para "Leave searx sources unchanged."
  245. fi
  246. }
  247. create_pyenv(){
  248. rst_title "Create virtualenv (python)" section
  249. echo
  250. if [[ ! -f "${SEARX_SRC}/manage.sh" ]]; then
  251. err_msg "to create pyenv for searx, searx has to be cloned first"
  252. return 42
  253. fi
  254. info_msg "create pyenv in ${SEARX_PYENV}"
  255. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  256. rm -rf "${SEARX_PYENV}"
  257. python3 -m venv "${SEARX_PYENV}"
  258. grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \
  259. || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profile
  260. EOF
  261. info_msg "inspect python's virtual environment"
  262. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  263. command -v python && python --version
  264. EOF
  265. wait_key
  266. info_msg "install needed python packages"
  267. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  268. ${SEARX_SRC}/manage.sh update_packages
  269. EOF
  270. }
  271. remove_pyenv(){
  272. rst_title "Remove virtualenv (python)" section
  273. if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then
  274. return
  275. fi
  276. info_msg "remove pyenv activation from ~/.profile"
  277. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  278. grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  279. mv ~/.profile.## ~/.profile
  280. EOF
  281. rm -rf "${SEARX_PYENV}"
  282. }
  283. configure_searx(){
  284. rst_title "Configure searx" section
  285. rst_para "Setup searx config located at $SEARX_SETTINGS"
  286. echo
  287. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  288. cd ${SEARX_SRC}
  289. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS"
  290. sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS"
  291. EOF
  292. }
  293. test_local_searx(){
  294. rst_title "Testing searx instance localy" section
  295. echo
  296. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  297. cd ${SEARX_SRC}
  298. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS"
  299. timeout 5 python3 searx/webapp.py &
  300. sleep 1
  301. curl --location --verbose --head --insecure http://127.0.0.1:8888/
  302. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS"
  303. EOF
  304. }
  305. install_searx_uwsgi() {
  306. rst_title "Install searx's uWSGI app (searx.ini)" section
  307. echo
  308. uWSGI_install_app "$SEARX_UWSGI_APP"
  309. }
  310. remove_searx_uwsgi() {
  311. rst_title "Remove searx's uWSGI app (searx.ini)" section
  312. echo
  313. uWSGI_remove_app "$SEARX_UWSGI_APP"
  314. }
  315. activate_service () {
  316. rst_title "Activate $SERVICE_NAME (service)" section
  317. uWSGI_enable_app "$SEARX_UWSGI_APP"
  318. }
  319. deactivate_service () {
  320. rst_title "De-Activate $SERVICE_NAME (service)" section
  321. uWSGI_disable_app "$SEARX_UWSGI_APP"
  322. }
  323. interactive_shell(){
  324. echo "// exit with CTRL-D"
  325. sudo -H -u "${SERVICE_USER}" -i
  326. }
  327. git_diff(){
  328. sudo -H -u "${SERVICE_USER}" -i <<EOF
  329. cd ${SEARX_REPO_FOLDER}
  330. git --no-pager diff
  331. EOF
  332. }
  333. show_service () {
  334. rst_title "service status & log"
  335. echo
  336. systemctl status uwsgi.service
  337. echo
  338. read -r -s -n1 -t 5 -p "// use CTRL-C to stop monitoring the log"
  339. echo
  340. while true; do
  341. trap break 2
  342. journalctl -f -u uwsgi.service
  343. done
  344. return 0
  345. }
  346. # ----------------------------------------------------------------------------
  347. main "$@"
  348. # ----------------------------------------------------------------------------