searx.sh 29 KB

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