searx.sh 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  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 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 branch --show-current) == "${GIT_BRANCH}" ]]; then
  361. warn_msg "take into account, installing branch $GIT_BRANCH while current branch is $(git branch --show-current)"
  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 interactiv 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 interactiv 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.sh" ]]; 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. 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. # ----------------------------------------------------------------------------