searx.sh 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. #!/usr/bin/env bash
  2. # -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
  3. # SPDX-License-Identifier: AGPL-3.0-or-later
  4. # shellcheck disable=SC2001
  5. # shellcheck source=utils/lib.sh
  6. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  7. # shellcheck source=utils/brand.env
  8. source "${REPO_ROOT}/utils/brand.env"
  9. source_dot_config
  10. source "${REPO_ROOT}/utils/lxc-searx.env"
  11. in_container && lxc_set_suite_env
  12. # ----------------------------------------------------------------------------
  13. # config
  14. # ----------------------------------------------------------------------------
  15. PUBLIC_URL="${PUBLIC_URL:-http://$(uname -n)/searx}"
  16. SEARX_INTERNAL_HTTP="${SEARX_INTERNAL_HTTP:-127.0.0.1:8888}"
  17. SEARX_URL_PATH="${SEARX_URL_PATH:-$(echo "${PUBLIC_URL}" \
  18. | sed -e 's,^.*://[^/]*\(/.*\),\1,g')}"
  19. [[ "${SEARX_URL_PATH}" == "${PUBLIC_URL}" ]] && SEARX_URL_PATH=/
  20. SEARX_INSTANCE_NAME="${SEARX_INSTANCE_NAME:-searx@$(echo "$PUBLIC_URL" \
  21. | sed -e 's,^.*://\([^\:/]*\).*,\1,g') }"
  22. SERVICE_NAME="searx"
  23. SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
  24. SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}"
  25. SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}"
  26. # shellcheck disable=SC2034
  27. SERVICE_GROUP="${SERVICE_USER}"
  28. GIT_BRANCH="${GIT_BRANCH:-master}"
  29. SEARX_PYENV="${SERVICE_HOME}/searx-pyenv"
  30. SEARX_SRC="${SERVICE_HOME}/searx-src"
  31. SEARX_SETTINGS_PATH="/etc/searx/settings.yml"
  32. SEARX_SETTINGS_TEMPLATE="${SEARX_SETTINGS_TEMPLATE:-${REPO_ROOT}/utils/templates/etc/searx/use_default_settings.yml}"
  33. SEARX_UWSGI_APP="searx.ini"
  34. # shellcheck disable=SC2034
  35. SEARX_UWSGI_SOCKET="/run/uwsgi/app/searx/socket"
  36. # apt packages
  37. SEARX_PACKAGES_debian="\
  38. python3-dev python3-babel python3-venv
  39. uwsgi uwsgi-plugin-python3
  40. git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-dev
  41. shellcheck"
  42. BUILD_PACKAGES_debian="\
  43. firefox graphviz imagemagick texlive-xetex librsvg2-bin
  44. texlive-latex-recommended texlive-extra-utils ttf-dejavu
  45. latexmk"
  46. # pacman packages
  47. SEARX_PACKAGES_arch="\
  48. python python-pip python-lxml python-babel
  49. uwsgi uwsgi-plugin-python
  50. git base-devel libxml2
  51. shellcheck"
  52. BUILD_PACKAGES_arch="\
  53. firefox graphviz imagemagick texlive-bin extra/librsvg
  54. texlive-core texlive-latexextra ttf-dejavu"
  55. # dnf packages
  56. SEARX_PACKAGES_fedora="\
  57. python python-pip python-lxml python-babel
  58. uwsgi uwsgi-plugin-python3
  59. git @development-tools libxml2
  60. ShellCheck"
  61. BUILD_PACKAGES_fedora="\
  62. firefox graphviz graphviz-gd ImageMagick librsvg2-tools
  63. texlive-xetex-bin texlive-collection-fontsrecommended
  64. texlive-collection-latex dejavu-sans-fonts dejavu-serif-fonts
  65. dejavu-sans-mono-fonts"
  66. # yum packages
  67. SEARX_PACKAGES_centos="\
  68. python36 python36-pip python36-lxml python-babel
  69. uwsgi uwsgi-plugin-python3
  70. git @development-tools libxml2
  71. ShellCheck"
  72. BUILD_PACKAGES_centos="\
  73. firefox graphviz graphviz-gd ImageMagick librsvg2-tools
  74. texlive-xetex-bin texlive-collection-fontsrecommended
  75. texlive-collection-latex dejavu-sans-fonts dejavu-serif-fonts
  76. dejavu-sans-mono-fonts"
  77. case $DIST_ID-$DIST_VERS in
  78. ubuntu-16.04|ubuntu-18.04)
  79. SEARX_PACKAGES="${SEARX_PACKAGES_debian}"
  80. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  81. APACHE_PACKAGES="$APACHE_PACKAGES libapache2-mod-proxy-uwsgi"
  82. ;;
  83. ubuntu-20.04)
  84. # https://askubuntu.com/a/1224710
  85. SEARX_PACKAGES="${SEARX_PACKAGES_debian} python-is-python3"
  86. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  87. ;;
  88. ubuntu-*|debian-*)
  89. SEARX_PACKAGES="${SEARX_PACKAGES_debian}"
  90. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  91. ;;
  92. arch-*)
  93. SEARX_PACKAGES="${SEARX_PACKAGES_arch}"
  94. BUILD_PACKAGES="${BUILD_PACKAGES_arch}"
  95. ;;
  96. fedora-*)
  97. SEARX_PACKAGES="${SEARX_PACKAGES_fedora}"
  98. BUILD_PACKAGES="${BUILD_PACKAGES_fedora}"
  99. ;;
  100. centos-7)
  101. SEARX_PACKAGES="${SEARX_PACKAGES_centos}"
  102. BUILD_PACKAGES="${BUILD_PACKAGES_centos}"
  103. ;;
  104. esac
  105. # Apache Settings
  106. APACHE_SEARX_SITE="searx.conf"
  107. # shellcheck disable=SC2034
  108. CONFIG_FILES=(
  109. "${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}"
  110. )
  111. # shellcheck disable=SC2034
  112. CONFIG_BACKUP_ENCRYPTED=(
  113. "${SEARX_SETTINGS_PATH}"
  114. )
  115. # ----------------------------------------------------------------------------
  116. usage() {
  117. # ----------------------------------------------------------------------------
  118. # shellcheck disable=SC1117
  119. cat <<EOF
  120. usage::
  121. $(basename "$0") shell
  122. $(basename "$0") install [all|user|searx-src|pyenv|uwsgi|packages|settings|buildhost]
  123. $(basename "$0") update [searx]
  124. $(basename "$0") remove [all|user|pyenv|searx-src]
  125. $(basename "$0") activate [service]
  126. $(basename "$0") deactivate [service]
  127. $(basename "$0") inspect [service]
  128. $(basename "$0") option [debug-[on|off]|image-proxy-[on|off]|result-proxy <url> <key>]
  129. $(basename "$0") apache [install|remove]
  130. shell
  131. start interactive shell from user ${SERVICE_USER}
  132. install / remove
  133. :all: complete (de-) installation of searx service
  134. :user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME)
  135. :searx-src: clone $GIT_URL
  136. :pyenv: create/remove virtualenv (python) in $SEARX_PYENV
  137. :uwsgi: install searx uWSGI application
  138. :settings: reinstall settings from ${SEARX_SETTINGS_TEMPLATE}
  139. :packages: install needed packages from OS package manager
  140. :buildhost: install packages from OS package manager needed by buildhosts
  141. update searx
  142. Update searx installation ($SERVICE_HOME)
  143. activate service
  144. activate and start service daemon (systemd unit)
  145. deactivate service
  146. stop and deactivate service daemon (systemd unit)
  147. inspect service
  148. run some small tests and inspect service's status and log
  149. option
  150. set one of the available options
  151. apache
  152. :install: apache site with the searx uwsgi app
  153. :remove: apache site ${APACHE_FILTRON_SITE}
  154. searx settings: ${SEARX_SETTINGS_PATH}
  155. If needed, set PUBLIC_URL of your WEB service in the '${DOT_CONFIG#"$REPO_ROOT/"}' file::
  156. PUBLIC_URL : ${PUBLIC_URL}
  157. SEARX_INSTANCE_NAME : ${SEARX_INSTANCE_NAME}
  158. SERVICE_USER : ${SERVICE_USER}
  159. SEARX_INTERNAL_HTTP : http://${SEARX_INTERNAL_HTTP}
  160. EOF
  161. if in_container; then
  162. # searx is listening on 127.0.0.1 and not available from outside container
  163. # in containers the service is listening on 0.0.0.0 (see lxc-searx.env)
  164. echo -e "${_BBlack}HINT:${_creset} searx only listen on loopback device" \
  165. "${_BBlack}inside${_creset} the container."
  166. for ip in $(global_IPs) ; do
  167. if [[ $ip =~ .*:.* ]]; then
  168. echo " container (IPv6): [${ip#*|}]"
  169. else
  170. # IPv4:
  171. echo " container (IPv4): ${ip#*|}"
  172. fi
  173. done
  174. fi
  175. [[ -n ${1} ]] && err_msg "$1"
  176. }
  177. main() {
  178. required_commands \
  179. sudo systemctl install git wget curl \
  180. || exit
  181. local _usage="unknown or missing $1 command $2"
  182. case $1 in
  183. --getenv) var="$2"; echo "${!var}"; exit 0;;
  184. -h|--help) usage; exit 0;;
  185. shell)
  186. sudo_or_exit
  187. interactive_shell "${SERVICE_USER}"
  188. ;;
  189. inspect)
  190. case $2 in
  191. service)
  192. sudo_or_exit
  193. inspect_service
  194. ;;
  195. *) usage "$_usage"; exit 42;;
  196. esac ;;
  197. install)
  198. rst_title "$SEARX_INSTANCE_NAME" part
  199. sudo_or_exit
  200. case $2 in
  201. all) install_all ;;
  202. user) assert_user ;;
  203. pyenv) create_pyenv ;;
  204. searx-src) clone_searx ;;
  205. settings) install_settings ;;
  206. uwsgi)
  207. install_searx_uwsgi
  208. if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then
  209. err_msg "URL http://${SEARX_INTERNAL_HTTP} not available, check searx & uwsgi setup!"
  210. fi
  211. ;;
  212. packages)
  213. pkg_install "$SEARX_PACKAGES"
  214. ;;
  215. buildhost)
  216. pkg_install "$SEARX_PACKAGES"
  217. pkg_install "$BUILD_PACKAGES"
  218. ;;
  219. *) usage "$_usage"; exit 42;;
  220. esac ;;
  221. update)
  222. sudo_or_exit
  223. case $2 in
  224. searx) update_searx;;
  225. *) usage "$_usage"; exit 42;;
  226. esac ;;
  227. remove)
  228. sudo_or_exit
  229. case $2 in
  230. all) remove_all;;
  231. user) drop_service_account "${SERVICE_USER}";;
  232. pyenv) remove_pyenv ;;
  233. searx-src) remove_searx ;;
  234. *) usage "$_usage"; exit 42;;
  235. esac ;;
  236. activate)
  237. sudo_or_exit
  238. case $2 in
  239. service)
  240. activate_service ;;
  241. *) usage "$_usage"; exit 42;;
  242. esac ;;
  243. deactivate)
  244. sudo_or_exit
  245. case $2 in
  246. service) deactivate_service ;;
  247. *) usage "$_usage"; exit 42;;
  248. esac ;;
  249. option)
  250. sudo_or_exit
  251. case $2 in
  252. debug-on) echo; enable_debug ;;
  253. debug-off) echo; disable_debug ;;
  254. result-proxy) set_result_proxy "$3" "$4" ;;
  255. image-proxy-on) enable_image_proxy ;;
  256. image-proxy-off) disable_image_proxy ;;
  257. *) usage "$_usage"; exit 42;;
  258. esac ;;
  259. apache)
  260. sudo_or_exit
  261. case $2 in
  262. install) install_apache_site ;;
  263. remove) remove_apache_site ;;
  264. *) usage "$_usage"; exit 42;;
  265. esac ;;
  266. doc) rst-doc;;
  267. *) usage "unknown or missing command $1"; exit 42;;
  268. esac
  269. }
  270. _service_prefix=" ${_Yellow}|$SERVICE_USER|${_creset} "
  271. install_all() {
  272. rst_title "Install $SEARX_INSTANCE_NAME (service)"
  273. pkg_install "$SEARX_PACKAGES"
  274. wait_key
  275. assert_user
  276. wait_key
  277. clone_searx
  278. wait_key
  279. create_pyenv
  280. wait_key
  281. install_settings
  282. wait_key
  283. test_local_searx
  284. wait_key
  285. install_searx_uwsgi
  286. if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then
  287. err_msg "URL http://${SEARX_INTERNAL_HTTP} not available, check searx & uwsgi setup!"
  288. fi
  289. if ask_yn "Do you want to inspect the installation?" Ny; then
  290. inspect_service
  291. fi
  292. }
  293. update_searx() {
  294. rst_title "Update searx instance"
  295. echo
  296. tee_stderr 0.3 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  297. cd ${SEARX_SRC}
  298. git checkout -B "$GIT_BRANCH"
  299. git pull
  300. pip install -U pip
  301. pip install -U setuptools
  302. pip install -U wheel
  303. pip install -U -e .
  304. EOF
  305. install_settings
  306. uWSGI_restart "$SEARX_UWSGI_APP"
  307. }
  308. remove_all() {
  309. rst_title "De-Install $SEARX_INSTANCE_NAME (service)"
  310. rst_para "\
  311. It goes without saying that this script can only be used to remove
  312. installations that were installed with this script."
  313. if ! ask_yn "Do you really want to deinstall $SEARX_INSTANCE_NAME?"; then
  314. return
  315. fi
  316. remove_searx_uwsgi
  317. drop_service_account "${SERVICE_USER}"
  318. remove_settings
  319. wait_key
  320. if service_is_available "${PUBLIC_URL}"; then
  321. MSG="** Don't forgett to remove your public site! (${PUBLIC_URL}) **" wait_key 10
  322. fi
  323. }
  324. assert_user() {
  325. rst_title "user $SERVICE_USER" section
  326. echo
  327. tee_stderr 1 <<EOF | bash | prefix_stdout
  328. useradd --shell /bin/bash --system \
  329. --home-dir "$SERVICE_HOME" \
  330. --comment 'Privacy-respecting metasearch engine' $SERVICE_USER
  331. mkdir "$SERVICE_HOME"
  332. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  333. groups $SERVICE_USER
  334. EOF
  335. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  336. #export SERVICE_HOME
  337. #echo "export SERVICE_HOME=$SERVICE_HOME"
  338. }
  339. clone_is_available() {
  340. [[ -f "$SEARX_SRC/.git/config" ]]
  341. }
  342. # shellcheck disable=SC2164
  343. clone_searx() {
  344. rst_title "Clone searx sources" section
  345. echo
  346. if ! sudo -i -u "$SERVICE_USER" ls -d "$REPO_ROOT" > /dev/null; then
  347. die 42 "user '$SERVICE_USER' missed read permission: $REPO_ROOT"
  348. fi
  349. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  350. if [[ ! "${SERVICE_HOME}" ]]; then
  351. err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"
  352. return 42
  353. fi
  354. export SERVICE_HOME
  355. git_clone "$REPO_ROOT" "$SEARX_SRC" \
  356. "$GIT_BRANCH" "$SERVICE_USER"
  357. pushd "${SEARX_SRC}" > /dev/null
  358. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  359. cd "${SEARX_SRC}"
  360. git remote set-url origin ${GIT_URL}
  361. git config user.email "$ADMIN_EMAIL"
  362. git config user.name "$ADMIN_NAME"
  363. git config --list
  364. EOF
  365. popd > /dev/null
  366. }
  367. install_settings() {
  368. rst_title "${SEARX_SETTINGS_PATH}" section
  369. if ! clone_is_available; then
  370. err_msg "you have to install searx first"
  371. exit 42
  372. fi
  373. mkdir -p "$(dirname ${SEARX_SETTINGS_PATH})"
  374. if [[ ! -f ${SEARX_SETTINGS_PATH} ]]; then
  375. info_msg "install settings ${SEARX_SETTINGS_TEMPLATE}"
  376. info_msg " --> ${SEARX_SETTINGS_PATH}"
  377. cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  378. configure_searx
  379. return
  380. fi
  381. rst_para "Diff between origin's setting file (+) and current (-):"
  382. echo "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"
  383. $DIFF_CMD "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"
  384. local action
  385. choose_one action "What should happen to the settings file? " \
  386. "keep configuration unchanged" \
  387. "use origin settings" \
  388. "start interactiv shell"
  389. case $action in
  390. "keep configuration unchanged")
  391. info_msg "leave settings file unchanged"
  392. ;;
  393. "use origin settings")
  394. backup_file "${SEARX_SETTINGS_PATH}"
  395. info_msg "install origin settings"
  396. cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  397. ;;
  398. "start interactiv shell")
  399. backup_file "${SEARX_SETTINGS_PATH}"
  400. echo -e "// exit with [${_BCyan}CTRL-D${_creset}]"
  401. sudo -H -i
  402. rst_para 'Diff between new setting file (-) and current (+):'
  403. echo
  404. $DIFF_CMD "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  405. wait_key
  406. ;;
  407. esac
  408. }
  409. remove_settings() {
  410. rst_title "remove searx settings" section
  411. echo
  412. info_msg "delete ${SEARX_SETTINGS_PATH}"
  413. rm -f "${SEARX_SETTINGS_PATH}"
  414. }
  415. remove_searx() {
  416. rst_title "Drop searx sources" section
  417. if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then
  418. rm -rf "$SEARX_SRC"
  419. else
  420. rst_para "Leave searx sources unchanged."
  421. fi
  422. }
  423. pyenv_is_available() {
  424. [[ -f "${SEARX_PYENV}/bin/activate" ]]
  425. }
  426. create_pyenv() {
  427. rst_title "Create virtualenv (python)" section
  428. echo
  429. if [[ ! -f "${SEARX_SRC}/manage.sh" ]]; then
  430. err_msg "to create pyenv for searx, searx has to be cloned first"
  431. return 42
  432. fi
  433. info_msg "create pyenv in ${SEARX_PYENV}"
  434. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  435. rm -rf "${SEARX_PYENV}"
  436. python3 -m venv "${SEARX_PYENV}"
  437. grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \
  438. || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profile
  439. EOF
  440. info_msg "inspect python's virtual environment"
  441. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  442. command -v python && python --version
  443. EOF
  444. wait_key
  445. info_msg "install needed python packages"
  446. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  447. pip install -U pip
  448. pip install -U setuptools
  449. pip install -U wheel
  450. pip install -U -e .
  451. cd ${SEARX_SRC}
  452. pip install -e .
  453. EOF
  454. }
  455. remove_pyenv() {
  456. rst_title "Remove virtualenv (python)" section
  457. if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then
  458. return
  459. fi
  460. info_msg "remove pyenv activation from ~/.profile"
  461. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  462. grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  463. mv ~/.profile.## ~/.profile
  464. EOF
  465. rm -rf "${SEARX_PYENV}"
  466. }
  467. configure_searx() {
  468. rst_title "Configure searx" section
  469. rst_para "Setup searx config located at $SEARX_SETTINGS_PATH"
  470. echo
  471. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  472. cd ${SEARX_SRC}
  473. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS_PATH"
  474. sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS_PATH"
  475. EOF
  476. }
  477. test_local_searx() {
  478. rst_title "Testing searx instance localy" section
  479. echo
  480. if service_is_available "http://${SEARX_INTERNAL_HTTP}" &>/dev/null; then
  481. err_msg "URL/port http://${SEARX_INTERNAL_HTTP} is already in use, you"
  482. err_msg "should stop that service before starting local tests!"
  483. if ! ask_yn "Continue with local tests?"; then
  484. return
  485. fi
  486. fi
  487. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"
  488. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  489. export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}"
  490. cd ${SEARX_SRC}
  491. timeout 10 python searx/webapp.py &
  492. sleep 3
  493. curl --location --verbose --head --insecure $SEARX_INTERNAL_HTTP
  494. EOF
  495. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"
  496. }
  497. install_searx_uwsgi() {
  498. rst_title "Install searx's uWSGI app (searx.ini)" section
  499. echo
  500. install_uwsgi
  501. uWSGI_install_app "$SEARX_UWSGI_APP"
  502. }
  503. remove_searx_uwsgi() {
  504. rst_title "Remove searx's uWSGI app (searx.ini)" section
  505. echo
  506. uWSGI_remove_app "$SEARX_UWSGI_APP"
  507. }
  508. activate_service() {
  509. rst_title "Activate $SEARX_INSTANCE_NAME (service)" section
  510. echo
  511. uWSGI_enable_app "$SEARX_UWSGI_APP"
  512. uWSGI_restart "$SEARX_UWSGI_APP"
  513. }
  514. deactivate_service() {
  515. rst_title "De-Activate $SEARX_INSTANCE_NAME (service)" section
  516. echo
  517. uWSGI_disable_app "$SEARX_UWSGI_APP"
  518. uWSGI_restart "$SEARX_UWSGI_APP"
  519. }
  520. enable_image_proxy() {
  521. info_msg "try to enable image_proxy ..."
  522. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  523. cd ${SEARX_SRC}
  524. sed -i -e "s/image_proxy : False/image_proxy : True/g" "$SEARX_SETTINGS_PATH"
  525. EOF
  526. uWSGI_restart "$SEARX_UWSGI_APP"
  527. }
  528. disable_image_proxy() {
  529. info_msg "try to enable image_proxy ..."
  530. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  531. cd ${SEARX_SRC}
  532. sed -i -e "s/image_proxy : True/image_proxy : False/g" "$SEARX_SETTINGS_PATH"
  533. EOF
  534. uWSGI_restart "$SEARX_UWSGI_APP"
  535. }
  536. enable_debug() {
  537. warn_msg "Do not enable debug in production enviroments!!"
  538. info_msg "try to enable debug mode ..."
  539. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  540. cd ${SEARX_SRC}
  541. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"
  542. EOF
  543. uWSGI_restart "$SEARX_UWSGI_APP"
  544. }
  545. disable_debug() {
  546. info_msg "try to disable debug mode ..."
  547. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  548. cd ${SEARX_SRC}
  549. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"
  550. EOF
  551. uWSGI_restart "$SEARX_UWSGI_APP"
  552. }
  553. set_result_proxy() {
  554. # usage: set_result_proxy <URL> [<key>]
  555. info_msg "try to set result proxy: '$1' ($2)"
  556. cp "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_PATH}.bak"
  557. _set_result_proxy "$1" "$2" > "${SEARX_SETTINGS_PATH}"
  558. }
  559. _set_result_proxy() {
  560. local line
  561. local stage=0
  562. local url=" url: $1"
  563. local key=" key: !!binary \"$2\""
  564. if [[ -z $2 ]]; then
  565. key=
  566. fi
  567. while IFS= read -r line
  568. do
  569. if [[ $stage = 0 ]] || [[ $stage = 2 ]] ; then
  570. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*result_proxy[[:space:]]*:[[:space:]]*$ ]]; then
  571. if [[ $stage = 0 ]]; then
  572. stage=1
  573. echo "result_proxy:"
  574. continue
  575. elif [[ $stage = 2 ]]; then
  576. continue
  577. fi
  578. fi
  579. fi
  580. if [[ $stage = 1 ]] || [[ $stage = 2 ]] ; then
  581. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*url[[:space:]]*:[[:space:]] ]]; then
  582. [[ $stage = 1 ]] && echo "$url"
  583. continue
  584. elif [[ $line =~ ^[[:space:]]*#*[[:space:]]*key[[:space:]]*:[[:space:]] ]]; then
  585. [[ $stage = 1 ]] && [[ -n $key ]] && echo "$key"
  586. continue
  587. elif [[ $line =~ ^[[:space:]]*$ ]]; then
  588. stage=2
  589. fi
  590. fi
  591. echo "$line"
  592. done < "${SEARX_SETTINGS_PATH}.bak"
  593. }
  594. function has_substring() {
  595. [[ "$1" != "${2/$1/}" ]]
  596. }
  597. inspect_service() {
  598. rst_title "service status & log"
  599. cat <<EOF
  600. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  601. PUBLIC_URL : ${PUBLIC_URL}
  602. SEARX_URL_PATH : ${SEARX_URL_PATH}
  603. SEARX_INSTANCE_NAME : ${SEARX_INSTANCE_NAME}
  604. SEARX_INTERNAL_HTTP : ${SEARX_INTERNAL_HTTP}
  605. EOF
  606. if service_account_is_available "$SERVICE_USER"; then
  607. info_msg "Service account $SERVICE_USER exists."
  608. else
  609. err_msg "Service account $SERVICE_USER does not exists!"
  610. fi
  611. if pyenv_is_available; then
  612. info_msg "~$SERVICE_USER: python environment is available."
  613. else
  614. err_msg "~$SERVICE_USER: python environment is not available!"
  615. fi
  616. if clone_is_available; then
  617. info_msg "~$SERVICE_USER: Searx software is installed."
  618. else
  619. err_msg "~$SERVICE_USER: Missing searx software!"
  620. fi
  621. if uWSGI_app_enabled "$SEARX_UWSGI_APP"; then
  622. info_msg "uWSGI app $SEARX_UWSGI_APP is enabled."
  623. else
  624. err_msg "uWSGI app $SEARX_UWSGI_APP not enabled!"
  625. fi
  626. uWSGI_app_available "$SEARX_UWSGI_APP" \
  627. || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"
  628. if in_container; then
  629. lxc_suite_info
  630. else
  631. info_msg "public URL --> ${PUBLIC_URL}"
  632. info_msg "internal URL --> http://${SEARX_INTERNAL_HTTP}"
  633. fi
  634. if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then
  635. err_msg "uWSGI app (service) at http://${SEARX_INTERNAL_HTTP} is not available!"
  636. MSG="${_Green}[${_BCyan}CTRL-C${_Green}] to stop or [${_BCyan}KEY${_Green}] to continue"\
  637. wait_key
  638. fi
  639. if ! service_is_available "${PUBLIC_URL}"; then
  640. warn_msg "Public service at ${PUBLIC_URL} is not available!"
  641. if ! in_container; then
  642. warn_msg "Check if public name is correct and routed or use the public IP from above."
  643. fi
  644. fi
  645. local _debug_on
  646. if ask_yn "Enable searx debug mode?"; then
  647. enable_debug
  648. _debug_on=1
  649. fi
  650. echo
  651. case $DIST_ID-$DIST_VERS in
  652. ubuntu-*|debian-*)
  653. systemctl --no-pager -l status "${SERVICE_NAME}"
  654. ;;
  655. arch-*)
  656. systemctl --no-pager -l status "uwsgi@${SERVICE_NAME%.*}"
  657. ;;
  658. fedora-*|centos-7)
  659. systemctl --no-pager -l status uwsgi
  660. ;;
  661. esac
  662. # shellcheck disable=SC2059
  663. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  664. read -r -s -n1 -t 5
  665. echo
  666. while true; do
  667. trap break 2
  668. case $DIST_ID-$DIST_VERS in
  669. ubuntu-*|debian-*) tail -f /var/log/uwsgi/app/searx.log ;;
  670. arch-*) journalctl -f -u "uwsgi@${SERVICE_NAME%.*}" ;;
  671. fedora-*|centos-7) journalctl -f -u uwsgi ;;
  672. esac
  673. done
  674. if [[ $_debug_on == 1 ]]; then
  675. disable_debug
  676. fi
  677. return 0
  678. }
  679. install_apache_site() {
  680. rst_title "Install Apache site $APACHE_SEARX_SITE"
  681. rst_para "\
  682. This installs the searx uwsgi app as apache site. If your server is public to
  683. the internet, you should instead use a reverse proxy (filtron) to block
  684. excessively bot queries."
  685. ! apache_is_installed && err_msg "Apache is not installed."
  686. if ! ask_yn "Do you really want to continue?" Yn; then
  687. return
  688. else
  689. install_apache
  690. fi
  691. apache_install_site --variant=uwsgi "${APACHE_SEARX_SITE}"
  692. rst_title "Install searx's uWSGI app (searx.ini)" section
  693. echo
  694. uWSGI_install_app --variant=socket "$SEARX_UWSGI_APP"
  695. if ! service_is_available "${PUBLIC_URL}"; then
  696. err_msg "Public service at ${PUBLIC_URL} is not available!"
  697. fi
  698. }
  699. remove_apache_site() {
  700. rst_title "Remove Apache site ${APACHE_SEARX_SITE}"
  701. rst_para "\
  702. This removes apache site ${APACHE_SEARX_SITE}."
  703. ! apache_is_installed && err_msg "Apache is not installed."
  704. if ! ask_yn "Do you really want to continue?" Yn; then
  705. return
  706. fi
  707. apache_remove_site "${APACHE_SEARX_SITE}"
  708. rst_title "Remove searx's uWSGI app (searx.ini)" section
  709. echo
  710. uWSGI_remove_app "$SEARX_UWSGI_APP"
  711. }
  712. rst-doc() {
  713. local debian="${SEARX_PACKAGES_debian}"
  714. local arch="${SEARX_PACKAGES_arch}"
  715. local fedora="${SEARX_PACKAGES_fedora}"
  716. local centos="${SEARX_PACKAGES_centos}"
  717. local debian_build="${BUILD_PACKAGES_debian}"
  718. local arch_build="${BUILD_PACKAGES_arch}"
  719. local fedora_build="${BUILD_PACKAGES_fedora}"
  720. local centos_build="${SEARX_PACKAGES_centos}"
  721. debian="$(echo "${debian}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  722. arch="$(echo "${arch}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  723. fedora="$(echo "${fedora}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  724. centos="$(echo "${centos}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  725. debian_build="$(echo "${debian_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  726. arch_build="$(echo "${arch_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  727. fedora_build="$(echo "${fedora_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  728. centos_build="$(echo "${centos_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  729. eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/searx.rst")\""
  730. # I use ubuntu-20.04 here to demonstrate that versions are also suported,
  731. # normaly debian-* and ubuntu-* are most the same.
  732. for DIST_NAME in ubuntu-20.04 arch fedora; do
  733. (
  734. DIST_ID=${DIST_NAME%-*}
  735. DIST_VERS=${DIST_NAME#*-}
  736. [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=
  737. uWSGI_distro_setup
  738. echo -e "\n.. START searx uwsgi-description $DIST_NAME"
  739. case $DIST_ID-$DIST_VERS in
  740. ubuntu-*|debian-*) cat <<EOF
  741. .. code:: bash
  742. # init.d --> /usr/share/doc/uwsgi/README.Debian.gz
  743. # For uWSGI debian uses the LSB init process, this might be changed
  744. # one day, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=833067
  745. create ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}
  746. enable: sudo -H ln -s ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP} ${uWSGI_APPS_ENABLED}/
  747. start: sudo -H service uwsgi start ${SEARX_UWSGI_APP%.*}
  748. restart: sudo -H service uwsgi restart ${SEARX_UWSGI_APP%.*}
  749. stop: sudo -H service uwsgi stop ${SEARX_UWSGI_APP%.*}
  750. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  751. EOF
  752. ;;
  753. arch-*) cat <<EOF
  754. .. code:: bash
  755. # systemd --> /usr/lib/systemd/system/uwsgi@.service
  756. # For uWSGI archlinux uses systemd template units, see
  757. # - http://0pointer.de/blog/projects/instances.html
  758. # - https://uwsgi-docs.readthedocs.io/en/latest/Systemd.html#one-service-per-app-in-systemd
  759. create: ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  760. enable: sudo -H systemctl enable uwsgi@${SEARX_UWSGI_APP%.*}
  761. start: sudo -H systemctl start uwsgi@${SEARX_UWSGI_APP%.*}
  762. restart: sudo -H systemctl restart uwsgi@${SEARX_UWSGI_APP%.*}
  763. stop: sudo -H systemctl stop uwsgi@${SEARX_UWSGI_APP%.*}
  764. disable: sudo -H systemctl disable uwsgi@${SEARX_UWSGI_APP%.*}
  765. EOF
  766. ;;
  767. fedora-*|centos-7) cat <<EOF
  768. .. code:: bash
  769. # systemd --> /usr/lib/systemd/system/uwsgi.service
  770. # The unit file starts uWSGI in emperor mode (/etc/uwsgi.ini), see
  771. # - https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html
  772. create: ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  773. restart: sudo -H touch ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  774. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  775. EOF
  776. ;;
  777. esac
  778. echo -e ".. END searx uwsgi-description $DIST_NAME"
  779. echo -e "\n.. START searx uwsgi-appini $DIST_NAME"
  780. echo ".. code:: bash"
  781. echo
  782. eval "echo \"$(< "${TEMPLATES}/${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}")\"" | prefix_stdout " "
  783. echo -e "\n.. END searx uwsgi-appini $DIST_NAME"
  784. )
  785. done
  786. }
  787. # ----------------------------------------------------------------------------
  788. main "$@"
  789. # ----------------------------------------------------------------------------