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