searx.sh 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  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="${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 fonts-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 pyyaml
  304. pip install -U -e .
  305. EOF
  306. install_settings
  307. uWSGI_restart "$SEARX_UWSGI_APP"
  308. }
  309. remove_all() {
  310. rst_title "De-Install $SEARX_INSTANCE_NAME (service)"
  311. rst_para "\
  312. It goes without saying that this script can only be used to remove
  313. installations that were installed with this script."
  314. if ! ask_yn "Do you really want to deinstall $SEARX_INSTANCE_NAME?"; then
  315. return
  316. fi
  317. remove_searx_uwsgi
  318. drop_service_account "${SERVICE_USER}"
  319. remove_settings
  320. wait_key
  321. if service_is_available "${PUBLIC_URL}"; then
  322. MSG="** Don't forgett to remove your public site! (${PUBLIC_URL}) **" wait_key 10
  323. fi
  324. }
  325. assert_user() {
  326. rst_title "user $SERVICE_USER" section
  327. echo
  328. tee_stderr 1 <<EOF | bash | prefix_stdout
  329. useradd --shell /bin/bash --system \
  330. --home-dir "$SERVICE_HOME" \
  331. --comment 'Privacy-respecting metasearch engine' $SERVICE_USER
  332. mkdir "$SERVICE_HOME"
  333. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  334. groups $SERVICE_USER
  335. EOF
  336. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  337. #export SERVICE_HOME
  338. #echo "export SERVICE_HOME=$SERVICE_HOME"
  339. }
  340. clone_is_available() {
  341. [[ -f "$SEARX_SRC/.git/config" ]]
  342. }
  343. # shellcheck disable=SC2164
  344. clone_searx() {
  345. rst_title "Clone searx sources" section
  346. echo
  347. if ! sudo -i -u "$SERVICE_USER" ls -d "$REPO_ROOT" > /dev/null; then
  348. die 42 "user '$SERVICE_USER' missed read permission: $REPO_ROOT"
  349. fi
  350. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  351. if [[ ! "${SERVICE_HOME}" ]]; then
  352. err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"
  353. return 42
  354. fi
  355. if [[ ! $(git show-ref "refs/heads/${GIT_BRANCH}") ]]; then
  356. warn_msg "missing local branch ${GIT_BRANCH}"
  357. info_msg "create local branch ${GIT_BRANCH} from start point: origin/${GIT_BRANCH}"
  358. git branch "${GIT_BRANCH}" "origin/${GIT_BRANCH}"
  359. fi
  360. if [[ ! $(git rev-parse --abbrev-ref HEAD) == "${GIT_BRANCH}" ]]; then
  361. warn_msg "take into account, installing branch $GIT_BRANCH while current branch is $(git rev-parse --abbrev-ref HEAD)"
  362. fi
  363. export SERVICE_HOME
  364. git_clone "$REPO_ROOT" "$SEARX_SRC" \
  365. "$GIT_BRANCH" "$SERVICE_USER"
  366. pushd "${SEARX_SRC}" > /dev/null
  367. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  368. cd "${SEARX_SRC}"
  369. git remote set-url origin ${GIT_URL}
  370. git config user.email "$ADMIN_EMAIL"
  371. git config user.name "$ADMIN_NAME"
  372. git config --list
  373. EOF
  374. popd > /dev/null
  375. }
  376. install_settings() {
  377. rst_title "${SEARX_SETTINGS_PATH}" section
  378. if ! clone_is_available; then
  379. err_msg "you have to install searx first"
  380. exit 42
  381. fi
  382. mkdir -p "$(dirname "${SEARX_SETTINGS_PATH}")"
  383. if [[ ! -f ${SEARX_SETTINGS_PATH} ]]; then
  384. info_msg "install settings ${SEARX_SETTINGS_TEMPLATE}"
  385. info_msg " --> ${SEARX_SETTINGS_PATH}"
  386. cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  387. configure_searx
  388. return
  389. fi
  390. rst_para "Diff between origin's setting file (+) and current (-):"
  391. echo "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"
  392. $DIFF_CMD "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"
  393. local action
  394. choose_one action "What should happen to the settings file? " \
  395. "keep configuration unchanged" \
  396. "use origin settings" \
  397. "start interactive shell"
  398. case $action in
  399. "keep configuration unchanged")
  400. info_msg "leave settings file unchanged"
  401. ;;
  402. "use origin settings")
  403. backup_file "${SEARX_SETTINGS_PATH}"
  404. info_msg "install origin settings"
  405. cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  406. ;;
  407. "start interactive shell")
  408. backup_file "${SEARX_SETTINGS_PATH}"
  409. echo -e "// exit with [${_BCyan}CTRL-D${_creset}]"
  410. sudo -H -i
  411. rst_para 'Diff between new setting file (-) and current (+):'
  412. echo
  413. $DIFF_CMD "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"
  414. wait_key
  415. ;;
  416. esac
  417. }
  418. remove_settings() {
  419. rst_title "remove searx settings" section
  420. echo
  421. info_msg "delete ${SEARX_SETTINGS_PATH}"
  422. rm -f "${SEARX_SETTINGS_PATH}"
  423. }
  424. remove_searx() {
  425. rst_title "Drop searx sources" section
  426. if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then
  427. rm -rf "$SEARX_SRC"
  428. else
  429. rst_para "Leave searx sources unchanged."
  430. fi
  431. }
  432. pyenv_is_available() {
  433. [[ -f "${SEARX_PYENV}/bin/activate" ]]
  434. }
  435. create_pyenv() {
  436. rst_title "Create virtualenv (python)" section
  437. echo
  438. if [[ ! -f "${SEARX_SRC}/manage" ]]; then
  439. err_msg "to create pyenv for searx, searx has to be cloned first"
  440. return 42
  441. fi
  442. info_msg "create pyenv in ${SEARX_PYENV}"
  443. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  444. rm -rf "${SEARX_PYENV}"
  445. python3 -m venv "${SEARX_PYENV}"
  446. grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \
  447. || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profile
  448. EOF
  449. info_msg "inspect python's virtual environment"
  450. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  451. command -v python && python --version
  452. EOF
  453. wait_key
  454. info_msg "install needed python packages"
  455. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  456. pip install -U pip
  457. pip install -U setuptools
  458. pip install -U wheel
  459. pip install -U pyyaml
  460. cd ${SEARX_SRC}
  461. pip install -e .
  462. EOF
  463. }
  464. remove_pyenv() {
  465. rst_title "Remove virtualenv (python)" section
  466. if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then
  467. return
  468. fi
  469. info_msg "remove pyenv activation from ~/.profile"
  470. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  471. grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  472. mv ~/.profile.## ~/.profile
  473. EOF
  474. rm -rf "${SEARX_PYENV}"
  475. }
  476. configure_searx() {
  477. rst_title "Configure searx" section
  478. rst_para "Setup searx config located at $SEARX_SETTINGS_PATH"
  479. echo
  480. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  481. cd ${SEARX_SRC}
  482. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS_PATH"
  483. sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS_PATH"
  484. EOF
  485. }
  486. test_local_searx() {
  487. rst_title "Testing searx instance locally" section
  488. echo
  489. if service_is_available "http://${SEARX_INTERNAL_HTTP}" &>/dev/null; then
  490. err_msg "URL/port http://${SEARX_INTERNAL_HTTP} is already in use, you"
  491. err_msg "should stop that service before starting local tests!"
  492. if ! ask_yn "Continue with local tests?"; then
  493. return
  494. fi
  495. fi
  496. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"
  497. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  498. export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}"
  499. cd ${SEARX_SRC}
  500. timeout 10 python searx/webapp.py &
  501. sleep 3
  502. curl --location --verbose --head --insecure $SEARX_INTERNAL_HTTP
  503. EOF
  504. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"
  505. }
  506. install_searx_uwsgi() {
  507. rst_title "Install searx's uWSGI app (searx.ini)" section
  508. echo
  509. install_uwsgi
  510. uWSGI_install_app "$SEARX_UWSGI_APP"
  511. }
  512. remove_searx_uwsgi() {
  513. rst_title "Remove searx's uWSGI app (searx.ini)" section
  514. echo
  515. uWSGI_remove_app "$SEARX_UWSGI_APP"
  516. }
  517. activate_service() {
  518. rst_title "Activate $SEARX_INSTANCE_NAME (service)" section
  519. echo
  520. uWSGI_enable_app "$SEARX_UWSGI_APP"
  521. uWSGI_restart "$SEARX_UWSGI_APP"
  522. }
  523. deactivate_service() {
  524. rst_title "De-Activate $SEARX_INSTANCE_NAME (service)" section
  525. echo
  526. uWSGI_disable_app "$SEARX_UWSGI_APP"
  527. uWSGI_restart "$SEARX_UWSGI_APP"
  528. }
  529. enable_image_proxy() {
  530. info_msg "try to enable image_proxy ..."
  531. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  532. cd ${SEARX_SRC}
  533. sed -i -e "s/image_proxy : False/image_proxy : True/g" "$SEARX_SETTINGS_PATH"
  534. EOF
  535. uWSGI_restart "$SEARX_UWSGI_APP"
  536. }
  537. disable_image_proxy() {
  538. info_msg "try to enable image_proxy ..."
  539. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  540. cd ${SEARX_SRC}
  541. sed -i -e "s/image_proxy : True/image_proxy : False/g" "$SEARX_SETTINGS_PATH"
  542. EOF
  543. uWSGI_restart "$SEARX_UWSGI_APP"
  544. }
  545. enable_debug() {
  546. warn_msg "Do not enable debug in production environments!!"
  547. info_msg "try to enable debug mode ..."
  548. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  549. cd ${SEARX_SRC}
  550. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"
  551. EOF
  552. uWSGI_restart "$SEARX_UWSGI_APP"
  553. }
  554. disable_debug() {
  555. info_msg "try to disable debug mode ..."
  556. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  557. cd ${SEARX_SRC}
  558. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"
  559. EOF
  560. uWSGI_restart "$SEARX_UWSGI_APP"
  561. }
  562. set_result_proxy() {
  563. # usage: set_result_proxy <URL> [<key>]
  564. info_msg "try to set result proxy: '$1' ($2)"
  565. cp "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_PATH}.bak"
  566. _set_result_proxy "$1" "$2" > "${SEARX_SETTINGS_PATH}"
  567. }
  568. _set_result_proxy() {
  569. local line
  570. local stage=0
  571. local url=" url: $1"
  572. local key=" key: !!binary \"$2\""
  573. if [[ -z $2 ]]; then
  574. key=
  575. fi
  576. while IFS= read -r line
  577. do
  578. if [[ $stage = 0 ]] || [[ $stage = 2 ]] ; then
  579. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*result_proxy[[:space:]]*:[[:space:]]*$ ]]; then
  580. if [[ $stage = 0 ]]; then
  581. stage=1
  582. echo "result_proxy:"
  583. continue
  584. elif [[ $stage = 2 ]]; then
  585. continue
  586. fi
  587. fi
  588. fi
  589. if [[ $stage = 1 ]] || [[ $stage = 2 ]] ; then
  590. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*url[[:space:]]*:[[:space:]] ]]; then
  591. [[ $stage = 1 ]] && echo "$url"
  592. continue
  593. elif [[ $line =~ ^[[:space:]]*#*[[:space:]]*key[[:space:]]*:[[:space:]] ]]; then
  594. [[ $stage = 1 ]] && [[ -n $key ]] && echo "$key"
  595. continue
  596. elif [[ $line =~ ^[[:space:]]*$ ]]; then
  597. stage=2
  598. fi
  599. fi
  600. echo "$line"
  601. done < "${SEARX_SETTINGS_PATH}.bak"
  602. }
  603. function has_substring() {
  604. [[ "$1" != "${2/$1/}" ]]
  605. }
  606. inspect_service() {
  607. rst_title "service status & log"
  608. cat <<EOF
  609. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  610. PUBLIC_URL : ${PUBLIC_URL}
  611. SEARX_URL_PATH : ${SEARX_URL_PATH}
  612. SEARX_INSTANCE_NAME : ${SEARX_INSTANCE_NAME}
  613. SEARX_INTERNAL_HTTP : ${SEARX_INTERNAL_HTTP}
  614. EOF
  615. if service_account_is_available "$SERVICE_USER"; then
  616. info_msg "Service account $SERVICE_USER exists."
  617. else
  618. err_msg "Service account $SERVICE_USER does not exists!"
  619. fi
  620. if pyenv_is_available; then
  621. info_msg "~$SERVICE_USER: python environment is available."
  622. else
  623. err_msg "~$SERVICE_USER: python environment is not available!"
  624. fi
  625. if clone_is_available; then
  626. info_msg "~$SERVICE_USER: Searx software is installed."
  627. else
  628. err_msg "~$SERVICE_USER: Missing searx software!"
  629. fi
  630. if uWSGI_app_enabled "$SEARX_UWSGI_APP"; then
  631. info_msg "uWSGI app $SEARX_UWSGI_APP is enabled."
  632. else
  633. err_msg "uWSGI app $SEARX_UWSGI_APP not enabled!"
  634. fi
  635. uWSGI_app_available "$SEARX_UWSGI_APP" \
  636. || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"
  637. if in_container; then
  638. lxc_suite_info
  639. else
  640. info_msg "public URL --> ${PUBLIC_URL}"
  641. info_msg "internal URL --> http://${SEARX_INTERNAL_HTTP}"
  642. fi
  643. if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then
  644. err_msg "uWSGI app (service) at http://${SEARX_INTERNAL_HTTP} is not available!"
  645. MSG="${_Green}[${_BCyan}CTRL-C${_Green}] to stop or [${_BCyan}KEY${_Green}] to continue"\
  646. wait_key
  647. fi
  648. if ! service_is_available "${PUBLIC_URL}"; then
  649. warn_msg "Public service at ${PUBLIC_URL} is not available!"
  650. if ! in_container; then
  651. warn_msg "Check if public name is correct and routed or use the public IP from above."
  652. fi
  653. fi
  654. local _debug_on
  655. if ask_yn "Enable searx debug mode?"; then
  656. enable_debug
  657. _debug_on=1
  658. fi
  659. echo
  660. case $DIST_ID-$DIST_VERS in
  661. ubuntu-*|debian-*)
  662. systemctl --no-pager -l status "${SERVICE_NAME}"
  663. ;;
  664. arch-*)
  665. systemctl --no-pager -l status "uwsgi@${SERVICE_NAME%.*}"
  666. ;;
  667. fedora-*|centos-7)
  668. systemctl --no-pager -l status uwsgi
  669. ;;
  670. esac
  671. # shellcheck disable=SC2059
  672. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  673. read -r -s -n1 -t 5
  674. echo
  675. while true; do
  676. trap break 2
  677. case $DIST_ID-$DIST_VERS in
  678. ubuntu-*|debian-*) tail -f /var/log/uwsgi/app/searx.log ;;
  679. arch-*) journalctl -f -u "uwsgi@${SERVICE_NAME%.*}" ;;
  680. fedora-*|centos-7) journalctl -f -u uwsgi ;;
  681. esac
  682. done
  683. if [[ $_debug_on == 1 ]]; then
  684. disable_debug
  685. fi
  686. return 0
  687. }
  688. install_apache_site() {
  689. rst_title "Install Apache site $APACHE_SEARX_SITE"
  690. rst_para "\
  691. This installs the searx uwsgi app as apache site. If your server is public to
  692. the internet, you should instead use a reverse proxy (filtron) to block
  693. excessively bot queries."
  694. ! apache_is_installed && err_msg "Apache is not installed."
  695. if ! ask_yn "Do you really want to continue?" Yn; then
  696. return
  697. else
  698. install_apache
  699. fi
  700. apache_install_site --variant=uwsgi "${APACHE_SEARX_SITE}"
  701. rst_title "Install searx's uWSGI app (searx.ini)" section
  702. echo
  703. uWSGI_install_app --variant=socket "$SEARX_UWSGI_APP"
  704. if ! service_is_available "${PUBLIC_URL}"; then
  705. err_msg "Public service at ${PUBLIC_URL} is not available!"
  706. fi
  707. }
  708. remove_apache_site() {
  709. rst_title "Remove Apache site ${APACHE_SEARX_SITE}"
  710. rst_para "\
  711. This removes apache site ${APACHE_SEARX_SITE}."
  712. ! apache_is_installed && err_msg "Apache is not installed."
  713. if ! ask_yn "Do you really want to continue?" Yn; then
  714. return
  715. fi
  716. apache_remove_site "${APACHE_SEARX_SITE}"
  717. rst_title "Remove searx's uWSGI app (searx.ini)" section
  718. echo
  719. uWSGI_remove_app "$SEARX_UWSGI_APP"
  720. }
  721. rst-doc() {
  722. local debian="${SEARX_PACKAGES_debian}"
  723. local arch="${SEARX_PACKAGES_arch}"
  724. local fedora="${SEARX_PACKAGES_fedora}"
  725. local centos="${SEARX_PACKAGES_centos}"
  726. local debian_build="${BUILD_PACKAGES_debian}"
  727. local arch_build="${BUILD_PACKAGES_arch}"
  728. local fedora_build="${BUILD_PACKAGES_fedora}"
  729. local centos_build="${SEARX_PACKAGES_centos}"
  730. debian="$(echo "${debian}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  731. arch="$(echo "${arch}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  732. fedora="$(echo "${fedora}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  733. centos="$(echo "${centos}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  734. debian_build="$(echo "${debian_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  735. arch_build="$(echo "${arch_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  736. fedora_build="$(echo "${fedora_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  737. centos_build="$(echo "${centos_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  738. eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/searx.rst")\""
  739. # I use ubuntu-20.04 here to demonstrate that versions are also supported,
  740. # normally debian-* and ubuntu-* are most the same.
  741. for DIST_NAME in ubuntu-20.04 arch fedora; do
  742. (
  743. DIST_ID=${DIST_NAME%-*}
  744. DIST_VERS=${DIST_NAME#*-}
  745. [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=
  746. uWSGI_distro_setup
  747. echo -e "\n.. START searx uwsgi-description $DIST_NAME"
  748. case $DIST_ID-$DIST_VERS in
  749. ubuntu-*|debian-*) cat <<EOF
  750. .. code:: bash
  751. # init.d --> /usr/share/doc/uwsgi/README.Debian.gz
  752. # For uWSGI debian uses the LSB init process, this might be changed
  753. # one day, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=833067
  754. create ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}
  755. enable: sudo -H ln -s ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP} ${uWSGI_APPS_ENABLED}/
  756. start: sudo -H service uwsgi start ${SEARX_UWSGI_APP%.*}
  757. restart: sudo -H service uwsgi restart ${SEARX_UWSGI_APP%.*}
  758. stop: sudo -H service uwsgi stop ${SEARX_UWSGI_APP%.*}
  759. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  760. EOF
  761. ;;
  762. arch-*) cat <<EOF
  763. .. code:: bash
  764. # systemd --> /usr/lib/systemd/system/uwsgi@.service
  765. # For uWSGI archlinux uses systemd template units, see
  766. # - http://0pointer.de/blog/projects/instances.html
  767. # - https://uwsgi-docs.readthedocs.io/en/latest/Systemd.html#one-service-per-app-in-systemd
  768. create: ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  769. enable: sudo -H systemctl enable uwsgi@${SEARX_UWSGI_APP%.*}
  770. start: sudo -H systemctl start uwsgi@${SEARX_UWSGI_APP%.*}
  771. restart: sudo -H systemctl restart uwsgi@${SEARX_UWSGI_APP%.*}
  772. stop: sudo -H systemctl stop uwsgi@${SEARX_UWSGI_APP%.*}
  773. disable: sudo -H systemctl disable uwsgi@${SEARX_UWSGI_APP%.*}
  774. EOF
  775. ;;
  776. fedora-*|centos-7) cat <<EOF
  777. .. code:: bash
  778. # systemd --> /usr/lib/systemd/system/uwsgi.service
  779. # The unit file starts uWSGI in emperor mode (/etc/uwsgi.ini), see
  780. # - https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html
  781. create: ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  782. restart: sudo -H touch ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  783. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}
  784. EOF
  785. ;;
  786. esac
  787. echo -e ".. END searx uwsgi-description $DIST_NAME"
  788. echo -e "\n.. START searx uwsgi-appini $DIST_NAME"
  789. echo ".. code:: bash"
  790. echo
  791. eval "echo \"$(< "${TEMPLATES}/${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}")\"" | prefix_stdout " "
  792. echo -e "\n.. END searx uwsgi-appini $DIST_NAME"
  793. )
  794. done
  795. }
  796. # ----------------------------------------------------------------------------
  797. main "$@"
  798. # ----------------------------------------------------------------------------