searx.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  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="searx.ini"
  28. # shellcheck disable=SC2034
  29. CONFIG_FILES=(
  30. "${uWSGI_SETUP}/apps-available/${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. $(basename "$0") option [debug-on|debug-off]
  50. shell
  51. start interactive shell from user ${SERVICE_USER}
  52. install / remove
  53. all: complete (de-) installation of searx service
  54. user: add/remove service user '$SERVICE_USER' at $SERVICE_HOME
  55. searx-src: clone $SEARX_GIT_URL
  56. pyenv: create/remove virtualenv (python) in $SEARX_PYENV
  57. update searx
  58. Update searx installation of user ${SERVICE_USER}
  59. activate
  60. activate and start service daemon (systemd unit)
  61. deactivate service
  62. stop and deactivate service daemon (systemd unit)
  63. show service
  64. run some small tests and show service's status and log
  65. option
  66. set one of te available options
  67. EOF
  68. [ ! -z ${1+x} ] && echo -e "$1"
  69. }
  70. main() {
  71. rst_title "$SERVICE_NAME" part
  72. local _usage="ERROR: unknown or missing $1 command $2"
  73. case $1 in
  74. --source-only) ;;
  75. -h|--help) usage; exit 0;;
  76. shell)
  77. sudo_or_exit
  78. interactive_shell
  79. ;;
  80. show)
  81. case $2 in
  82. service)
  83. sudo_or_exit
  84. show_service
  85. ;;
  86. *) usage "$_usage"; exit 42;;
  87. esac ;;
  88. install)
  89. sudo_or_exit
  90. case $2 in
  91. all) install_all ;;
  92. user) assert_user ;;
  93. pyenv) create_pyenv ;;
  94. searx-src) clone_searx ;;
  95. *) usage "$_usage"; exit 42;;
  96. esac ;;
  97. update)
  98. sudo_or_exit
  99. case $2 in
  100. searx) update_searx;;
  101. *) usage "$_usage"; exit 42;;
  102. esac ;;
  103. remove)
  104. sudo_or_exit
  105. case $2 in
  106. all) remove_all;;
  107. user) remove_user ;;
  108. pyenv) remove_pyenv ;;
  109. searx-src) remove_searx ;;
  110. *) usage "$_usage"; exit 42;;
  111. esac ;;
  112. activate)
  113. sudo_or_exit
  114. case $2 in
  115. service)
  116. activate_service; uWSGI_restart ;;
  117. *) usage "$_usage"; exit 42;;
  118. esac ;;
  119. deactivate)
  120. sudo_or_exit
  121. case $2 in
  122. service) deactivate_service; uWSGI_restart ;;
  123. *) usage "$_usage"; exit 42;;
  124. esac ;;
  125. option)
  126. sudo_or_exit
  127. case $2 in
  128. debug-on) echo; enable_debug ;;
  129. debug-off) echo; disable_debug ;;
  130. *) usage "$_usage"; exit 42;;
  131. esac ;;
  132. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  133. esac
  134. }
  135. _service_prefix=" |$SERVICE_USER| "
  136. install_all() {
  137. rst_title "Install $SERVICE_NAME (service)"
  138. pkg_install "$SEARX_APT_PACKAGES"
  139. wait_key
  140. assert_user
  141. wait_key
  142. clone_searx
  143. wait_key
  144. create_pyenv
  145. wait_key
  146. configure_searx
  147. wait_key
  148. test_local_searx
  149. wait_key
  150. install_searx_uwsgi
  151. if service_is_available; then
  152. info_msg "URL http://$SEARX_URL is available."
  153. else
  154. err_msg "URL http://$SEARX_URL not available, check searx & uwsgi setup!"
  155. fi
  156. wait_key
  157. # ToDo ...
  158. # install_apache_site
  159. # test_public_searx
  160. # info_msg "searX --> https://${SEARX_APACHE_DOMAIN}${SEARX_APACHE_URL}"
  161. }
  162. update_searx() {
  163. rst_title "Update searx instance"
  164. echo
  165. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  166. cd ${SEARX_SRC}
  167. cp -f ${SEARX_SETTINGS} ${SEARX_SETTINGS}.backup
  168. git stash push -m "BACKUP -- 'update server' at ($(date))"
  169. git checkout -b $SEARX_GIT_BRANCH" --track "$SEARX_GIT_BRANCH"
  170. git pull "$SEARX_GIT_BRANCH"
  171. ${SEARX_SRC}/manage.sh update_packages
  172. EOF
  173. configure_searx
  174. rst_title "${SEARX_SETTINGS}" section
  175. rstBlock 'Diff between new setting file (<) and backup (>):'
  176. echo
  177. diff "$SEARX_SETTINGS}" "${SEARX_SETTINGS}.backup"
  178. local action
  179. choose_one action "What should happen to the settings file? " \
  180. "keep new configuration" \
  181. "revert to the old configuration (backup file)" \
  182. "start interactiv shell"
  183. case $action in
  184. "keep new configuration")
  185. info_msg "continue using new settings file"
  186. ;;
  187. "revert to the old configuration (backup file)")
  188. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  189. cp -f ${SEARX_SETTINGS}.backup ${SEARX_SETTINGS}
  190. EOF
  191. ;;
  192. "start interactiv shell")
  193. interactive_shell
  194. ;;
  195. esac
  196. chown "${SERVICE_USER}:${SERVICE_USER}" "${SEARX_SETTINGS}"
  197. # shellcheck disable=SC2016
  198. rst_para 'Diff between local modified settings (<) and $SEARX_GIT_BRANCH branch (>):'
  199. echo
  200. git_diff
  201. wait_key
  202. uWSGI_restart
  203. }
  204. remove_all() {
  205. rst_title "De-Install $SERVICE_NAME (service)"
  206. if ! ask_yn "Do you really want to deinstall $SERVICE_NAME?"; then
  207. return
  208. fi
  209. remove_searx_uwsgi
  210. wait_key
  211. remove_user
  212. }
  213. user_is_available() {
  214. sudo -i -u "$SERVICE_USER" echo \$HOME &>/dev/null
  215. }
  216. assert_user() {
  217. rst_title "user $SERVICE_USER" section
  218. echo
  219. tee_stderr 1 <<EOF | bash | prefix_stdout
  220. sudo -H adduser --shell /bin/bash --system --home "$SERVICE_HOME" \
  221. --disabled-password --group --gecos 'searx' $SERVICE_USER
  222. sudo -H usermod -a -G shadow $SERVICE_USER
  223. groups $SERVICE_USER
  224. EOF
  225. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  226. #export SERVICE_HOME
  227. #echo "export SERVICE_HOME=$SERVICE_HOME"
  228. }
  229. remove_user() {
  230. rst_title "Drop $SERVICE_USER HOME" section
  231. if ask_yn "Do you really want to drop $SERVICE_USER home folder?"; then
  232. userdel -r -f "$SERVICE_USER" 2>&1 | prefix_stdout
  233. else
  234. rst_para "Leave HOME folder $(du -sh "$SERVICE_HOME") unchanged."
  235. fi
  236. }
  237. clone_is_available() {
  238. [[ -f "$SEARX_SETTINGS" ]]
  239. }
  240. # shellcheck disable=SC2164
  241. clone_searx() {
  242. rst_title "Clone searx sources" section
  243. echo
  244. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  245. if [[ ! "${SERVICE_HOME}" ]]; then
  246. err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"
  247. return 42
  248. fi
  249. export SERVICE_HOME
  250. git_clone "$SEARX_GIT_URL" "$SEARX_SRC" \
  251. "$SEARX_GIT_BRANCH" "$SERVICE_USER"
  252. pushd "${SEARX_SRC}" > /dev/null
  253. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  254. cd "${SEARX_SRC}"
  255. git config user.email "$ADMIN_EMAIL"
  256. git config user.name "$ADMIN_NAME"
  257. git config --list
  258. EOF
  259. popd > /dev/null
  260. }
  261. remove_searx() {
  262. rst_title "Drop searx sources" section
  263. if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then
  264. rm -rf "$SEARX_SRC"
  265. else
  266. rst_para "Leave searx sources unchanged."
  267. fi
  268. }
  269. pyenv_is_available() {
  270. [[ -f "${SEARX_PYENV}/bin/activate" ]]
  271. }
  272. create_pyenv() {
  273. rst_title "Create virtualenv (python)" section
  274. echo
  275. if [[ ! -f "${SEARX_SRC}/manage.sh" ]]; then
  276. err_msg "to create pyenv for searx, searx has to be cloned first"
  277. return 42
  278. fi
  279. info_msg "create pyenv in ${SEARX_PYENV}"
  280. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  281. rm -rf "${SEARX_PYENV}"
  282. python3 -m venv "${SEARX_PYENV}"
  283. grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \
  284. || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profile
  285. EOF
  286. info_msg "inspect python's virtual environment"
  287. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  288. command -v python && python --version
  289. EOF
  290. wait_key
  291. info_msg "install needed python packages"
  292. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  293. ${SEARX_SRC}/manage.sh update_packages
  294. EOF
  295. }
  296. remove_pyenv() {
  297. rst_title "Remove virtualenv (python)" section
  298. if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then
  299. return
  300. fi
  301. info_msg "remove pyenv activation from ~/.profile"
  302. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  303. grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  304. mv ~/.profile.## ~/.profile
  305. EOF
  306. rm -rf "${SEARX_PYENV}"
  307. }
  308. configure_searx() {
  309. rst_title "Configure searx" section
  310. rst_para "Setup searx config located at $SEARX_SETTINGS"
  311. echo
  312. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  313. cd ${SEARX_SRC}
  314. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS"
  315. sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS"
  316. EOF
  317. }
  318. test_local_searx() {
  319. rst_title "Testing searx instance localy" section
  320. echo
  321. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  322. cd ${SEARX_SRC}
  323. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS"
  324. timeout 5 python3 searx/webapp.py &
  325. sleep 1
  326. curl --location --verbose --head --insecure $SEARX_URL
  327. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS"
  328. EOF
  329. }
  330. install_searx_uwsgi() {
  331. rst_title "Install searx's uWSGI app (searx.ini)" section
  332. echo
  333. uWSGI_install_app "$SEARX_UWSGI_APP"
  334. }
  335. remove_searx_uwsgi() {
  336. rst_title "Remove searx's uWSGI app (searx.ini)" section
  337. echo
  338. uWSGI_remove_app "$SEARX_UWSGI_APP"
  339. }
  340. activate_service() {
  341. rst_title "Activate $SERVICE_NAME (service)" section
  342. echo
  343. uWSGI_enable_app "$SEARX_UWSGI_APP"
  344. }
  345. deactivate_service() {
  346. rst_title "De-Activate $SERVICE_NAME (service)" section
  347. echo
  348. uWSGI_disable_app "$SEARX_UWSGI_APP"
  349. }
  350. interactive_shell() {
  351. echo "// exit with CTRL-D"
  352. sudo -H -u "${SERVICE_USER}" -i
  353. }
  354. git_diff() {
  355. sudo -H -u "${SERVICE_USER}" -i <<EOF
  356. cd ${SEARX_REPO_FOLDER}
  357. git --no-pager diff
  358. EOF
  359. }
  360. service_is_available() {
  361. curl --insecure "http://$SEARX_URL" &>/dev/null
  362. }
  363. enable_debug() {
  364. info_msg "try to enable debug mode ..."
  365. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  366. cd ${SEARX_SRC}
  367. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS"
  368. EOF
  369. uWSGI_restart
  370. }
  371. disable_debug() {
  372. info_msg "try to disable debug mode ..."
  373. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  374. cd ${SEARX_SRC}
  375. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS"
  376. EOF
  377. uWSGI_restart
  378. }
  379. show_service() {
  380. rst_title "service status & log"
  381. echo
  382. if user_is_available; then
  383. info_msg "service account $SERVICE_USER available."
  384. else
  385. err_msg "service account $SERVICE_USER not available!"
  386. fi
  387. if service_is_available; then
  388. info_msg "URL http://$SEARX_URL is available."
  389. else
  390. err_msg "URL http://$SEARX_URL not available!"
  391. fi
  392. if pyenv_is_available; then
  393. info_msg "${SEARX_PYENV}/bin/activate is available."
  394. else
  395. err_msg "${SEARX_PYENV}/bin/activate not available!"
  396. fi
  397. if clone_is_available; then
  398. info_msg "Searx software is installed."
  399. else
  400. err_msg "Missing searx software!"
  401. fi
  402. uWSGI_app_available "$SEARX_UWSGI_APP" \
  403. || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"
  404. if uWSGI_app_enabled "$SEARX_UWSGI_APP"; then
  405. info_msg "uWSGI app $SEARX_UWSGI_APP is enabled."
  406. else
  407. err_msg "uWSGI app $SEARX_UWSGI_APP not enabled!"
  408. fi
  409. local _debug_on
  410. if ask_yn "Enable searx debug mode?"; then
  411. enable_debug
  412. _debug_on=1
  413. fi
  414. wait_key
  415. echo
  416. systemctl status uwsgi.service
  417. read -r -s -n1 -t 2 -p "// use CTRL-C to stop monitoring the log"
  418. echo
  419. while true; do
  420. trap break 2
  421. #journalctl -f -u uwsgi.service
  422. tail -f /var/log/uwsgi/app/searx.log
  423. done
  424. if [[ $_debug_on == 1 ]]; then
  425. disable_debug
  426. fi
  427. return 0
  428. }
  429. # ----------------------------------------------------------------------------
  430. main "$@"
  431. # ----------------------------------------------------------------------------