searx.sh 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. #!/usr/bin/env bash
  2. # SPDX-License-Identifier: AGPL-3.0-or-later
  3. # shellcheck disable=SC2001
  4. # shellcheck source=utils/lib.sh
  5. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  6. # shellcheck source=utils/lib_install.sh
  7. source "${REPO_ROOT}/utils/lib_install.sh"
  8. # ----------------------------------------------------------------------------
  9. # config
  10. # ----------------------------------------------------------------------------
  11. SEARXNG_INTERNAL_HTTP="${SEARXNG_BIND_ADDRESS}:${SEARXNG_PORT}"
  12. SEARXNG_URL_PATH="${SEARXNG_URL_PATH:-$(echo "${PUBLIC_URL}" \
  13. | sed -e 's,^.*://[^/]*\(/.*\),\1,g')}"
  14. [[ "${SEARXNG_URL_PATH}" == "${PUBLIC_URL}" ]] && SEARXNG_URL_PATH=/
  15. SERVICE_NAME="searx"
  16. SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
  17. SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}"
  18. SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}"
  19. # shellcheck disable=SC2034
  20. SERVICE_GROUP="${SERVICE_USER}"
  21. GIT_BRANCH="${GIT_BRANCH:-master}"
  22. SEARXNG_PYENV="${SERVICE_HOME}/searx-pyenv"
  23. SEARXNG_SRC="${SERVICE_HOME}/searx-src"
  24. # shellcheck disable=SC2034
  25. SEARXNG_STATIC="${SEARXNG_SRC}/searx/static"
  26. SEARXNG_SETTINGS_PATH="/etc/searxng/settings.yml"
  27. SEARXNG_UWSGI_APP="searxng.ini"
  28. # shellcheck disable=SC2034
  29. SEARXNG_UWSGI_SOCKET="/run/uwsgi/app/searxng/socket"
  30. # apt packages
  31. SEARX_PACKAGES_debian="\
  32. python3-dev python3-babel python3-venv
  33. uwsgi uwsgi-plugin-python3
  34. git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-dev
  35. shellcheck"
  36. BUILD_PACKAGES_debian="\
  37. firefox graphviz imagemagick texlive-xetex librsvg2-bin
  38. texlive-latex-recommended texlive-extra-utils fonts-dejavu
  39. latexmk"
  40. # pacman packages
  41. SEARX_PACKAGES_arch="\
  42. python python-pip python-lxml python-babel
  43. uwsgi uwsgi-plugin-python
  44. git base-devel libxml2
  45. shellcheck"
  46. BUILD_PACKAGES_arch="\
  47. firefox graphviz imagemagick texlive-bin extra/librsvg
  48. texlive-core texlive-latexextra ttf-dejavu"
  49. # dnf packages
  50. SEARX_PACKAGES_fedora="\
  51. python python-pip python-lxml python-babel python3-devel
  52. uwsgi uwsgi-plugin-python3
  53. git @development-tools libxml2 openssl
  54. ShellCheck"
  55. BUILD_PACKAGES_fedora="\
  56. firefox graphviz graphviz-gd ImageMagick librsvg2-tools
  57. texlive-xetex-bin texlive-collection-fontsrecommended
  58. texlive-collection-latex dejavu-sans-fonts dejavu-serif-fonts
  59. dejavu-sans-mono-fonts"
  60. # yum packages
  61. #
  62. # hint: We do no longer support yum packages, it is to complex to maintain
  63. # automate installation of packages like npm. In the firts step we ignore
  64. # CentOS-7 as developer & build platform (the inital patch which brought
  65. # CentOS-7 supports was not intended to be a developer platform).
  66. SEARX_PACKAGES_centos="\
  67. python36 python36-pip python36-lxml python-babel
  68. uwsgi uwsgi-plugin-python3
  69. git @development-tools libxml2
  70. ShellCheck"
  71. BUILD_PACKAGES_centos="\
  72. firefox graphviz graphviz-gd ImageMagick librsvg2-tools
  73. texlive-xetex-bin texlive-collection-fontsrecommended
  74. texlive-collection-latex dejavu-sans-fonts dejavu-serif-fonts
  75. dejavu-sans-mono-fonts"
  76. case $DIST_ID-$DIST_VERS in
  77. ubuntu-16.04|ubuntu-18.04)
  78. SEARX_PACKAGES="${SEARX_PACKAGES_debian}"
  79. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  80. APACHE_PACKAGES="$APACHE_PACKAGES libapache2-mod-proxy-uwsgi"
  81. ;;
  82. ubuntu-20.04)
  83. # https://askubuntu.com/a/1224710
  84. SEARX_PACKAGES="${SEARX_PACKAGES_debian} python-is-python3"
  85. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  86. ;;
  87. ubuntu-*|debian-*)
  88. SEARX_PACKAGES="${SEARX_PACKAGES_debian}"
  89. BUILD_PACKAGES="${BUILD_PACKAGES_debian}"
  90. ;;
  91. arch-*)
  92. SEARX_PACKAGES="${SEARX_PACKAGES_arch}"
  93. BUILD_PACKAGES="${BUILD_PACKAGES_arch}"
  94. ;;
  95. fedora-*)
  96. SEARX_PACKAGES="${SEARX_PACKAGES_fedora}"
  97. BUILD_PACKAGES="${BUILD_PACKAGES_fedora}"
  98. ;;
  99. centos-7)
  100. SEARX_PACKAGES="${SEARX_PACKAGES_centos}"
  101. BUILD_PACKAGES="${BUILD_PACKAGES_centos}"
  102. ;;
  103. esac
  104. # Apache Settings
  105. APACHE_SEARX_SITE="searxng.conf"
  106. # shellcheck disable=SC2034
  107. CONFIG_FILES=(
  108. "${uWSGI_APPS_AVAILABLE}/${SEARXNG_UWSGI_APP}"
  109. )
  110. # shellcheck disable=SC2034
  111. CONFIG_BACKUP_ENCRYPTED=(
  112. "${SEARXNG_SETTINGS_PATH}"
  113. )
  114. # ----------------------------------------------------------------------------
  115. usage() {
  116. # ----------------------------------------------------------------------------
  117. # shellcheck disable=SC1117
  118. cat <<EOF
  119. usage::
  120. $(basename "$0") shell
  121. $(basename "$0") install [all|check|init-src|dot-config|user|searx-src|pyenv|uwsgi|packages|settings|buildhost]
  122. $(basename "$0") reinstall all
  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|settings <key>]
  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 SearXNG service
  134. :user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME)
  135. :dot-config: copy ./config.sh to ${SEARXNG_SRC}
  136. :searx-src: clone $GIT_URL
  137. :init-src: copy files (SEARXNG_SRC_INIT_FILES) to ${SEARXNG_SRC}
  138. :pyenv: create/remove virtualenv (python) in $SEARXNG_PYENV
  139. :uwsgi: install SearXNG uWSGI application
  140. :settings: reinstall settings from ${SEARXNG_SETTINGS_PATH}
  141. :packages: install needed packages from OS package manager
  142. :buildhost: install packages from OS package manager needed by buildhosts
  143. install
  144. :check: check the SearXNG installation
  145. reinstall:
  146. :all: runs 'install/remove all'
  147. update searx
  148. Update SearXNG installation ($SERVICE_HOME)
  149. activate service
  150. activate and start service daemon (systemd unit)
  151. deactivate service
  152. stop and deactivate service daemon (systemd unit)
  153. inspect
  154. :service: run some small tests and inspect service's status and log
  155. :settings: inspect YAML setting <key> from SearXNG instance (${SEARXNG_SRC})
  156. option
  157. set one of the available options
  158. apache
  159. :install: apache site with the SearXNG uwsgi app
  160. :remove: apache site ${APACHE_FILTRON_SITE}
  161. ---- sourced ${DOT_CONFIG}
  162. SERVICE_USER : ${SERVICE_USER}
  163. SERVICE_HOME : ${SERVICE_HOME}
  164. EOF
  165. install_log_searx_instance
  166. [[ -n ${1} ]] && err_msg "$1"
  167. }
  168. main() {
  169. required_commands \
  170. sudo systemctl install git wget curl \
  171. || exit
  172. local _usage="unknown or missing $1 command $2"
  173. case $1 in
  174. --getenv) var="$2"; echo "${!var}"; exit 0;;
  175. -h|--help) usage; exit 0;;
  176. shell)
  177. sudo_or_exit
  178. interactive_shell "${SERVICE_USER}"
  179. ;;
  180. inspect)
  181. case $2 in
  182. service)
  183. sudo_or_exit
  184. inspect_service
  185. ;;
  186. settings)
  187. prompt_installation_setting "$3"
  188. dump_return $?
  189. ;;
  190. *) usage "$_usage"; exit 42;;
  191. esac ;;
  192. reinstall)
  193. rst_title "re-install $SERVICE_NAME" part
  194. sudo_or_exit
  195. case $2 in
  196. all)
  197. remove_all
  198. install_all
  199. ;;
  200. *) usage "$_usage"; exit 42;;
  201. esac ;;
  202. install)
  203. sudo_or_exit
  204. case $2 in
  205. all)
  206. rst_title "SearXNG (install)" part
  207. install_all
  208. ;;
  209. check)
  210. rst_title "SearXNG (check installation)" part
  211. verify_continue_install
  212. install_check
  213. ;;
  214. user)
  215. rst_title "SearXNG (install user)"
  216. verify_continue_install
  217. assert_user
  218. ;;
  219. pyenv)
  220. rst_title "SearXNG (install pyenv)"
  221. verify_continue_install
  222. create_pyenv
  223. ;;
  224. searx-src)
  225. rst_title "SearXNG (install searx-src)"
  226. verify_continue_install
  227. assert_user
  228. clone_searx
  229. install_DOT_CONFIG
  230. init_SEARX_SRC
  231. ;;
  232. init-src)
  233. init_SEARX_SRC
  234. ;;
  235. dot-config)
  236. install_DOT_CONFIG
  237. ;;
  238. settings)
  239. install_settings
  240. ;;
  241. uwsgi)
  242. rst_title "SearXNG (install uwsgi)"
  243. verify_continue_install
  244. install_searx_uwsgi
  245. if ! service_is_available "http://${SEARXNG_INTERNAL_HTTP}"; then
  246. err_msg "URL http://${SEARXNG_INTERNAL_HTTP} not available, check SearXNG & uwsgi setup!"
  247. fi
  248. ;;
  249. packages)
  250. rst_title "SearXNG (install packages)"
  251. pkg_install "$SEARX_PACKAGES"
  252. ;;
  253. buildhost)
  254. rst_title "SearXNG (install buildhost)"
  255. pkg_install "$SEARX_PACKAGES"
  256. pkg_install "$BUILD_PACKAGES"
  257. ;;
  258. *) usage "$_usage"; exit 42;;
  259. esac ;;
  260. update)
  261. sudo_or_exit
  262. case $2 in
  263. searx) update_searx;;
  264. *) usage "$_usage"; exit 42;;
  265. esac ;;
  266. remove)
  267. rst_title "SearXNG (remove)" part
  268. sudo_or_exit
  269. case $2 in
  270. all) remove_all;;
  271. user) drop_service_account "${SERVICE_USER}";;
  272. pyenv) remove_pyenv ;;
  273. searx-src) remove_searx ;;
  274. *) usage "$_usage"; exit 42;;
  275. esac ;;
  276. activate)
  277. sudo_or_exit
  278. case $2 in
  279. service)
  280. activate_service ;;
  281. *) usage "$_usage"; exit 42;;
  282. esac ;;
  283. deactivate)
  284. sudo_or_exit
  285. case $2 in
  286. service) deactivate_service ;;
  287. *) usage "$_usage"; exit 42;;
  288. esac ;;
  289. option)
  290. sudo_or_exit
  291. case $2 in
  292. debug-on) echo; enable_debug ;;
  293. debug-off) echo; disable_debug ;;
  294. result-proxy) set_result_proxy "$3" "$4" ;;
  295. image-proxy-on) enable_image_proxy ;;
  296. image-proxy-off) disable_image_proxy ;;
  297. *) usage "$_usage"; exit 42;;
  298. esac ;;
  299. apache)
  300. sudo_or_exit
  301. case $2 in
  302. install) install_apache_site ;;
  303. remove) remove_apache_site ;;
  304. *) usage "$_usage"; exit 42;;
  305. esac ;;
  306. doc) rst-doc;;
  307. *) usage "unknown or missing command $1"; exit 42;;
  308. esac
  309. }
  310. _service_prefix=" ${_Yellow}|$SERVICE_USER|${_creset} "
  311. install_all() {
  312. rst_title "Install SearXNG (service)"
  313. verify_continue_install
  314. pkg_install "$SEARX_PACKAGES"
  315. wait_key
  316. assert_user
  317. wait_key
  318. clone_searx
  319. wait_key
  320. install_DOT_CONFIG
  321. wait_key
  322. init_SEARX_SRC
  323. wait_key
  324. create_pyenv
  325. wait_key
  326. install_settings
  327. wait_key
  328. test_local_searx
  329. wait_key
  330. install_searx_uwsgi
  331. if ! service_is_available "http://${SEARXNG_INTERNAL_HTTP}"; then
  332. err_msg "URL http://${SEARXNG_INTERNAL_HTTP} not available, check SearXNG & uwsgi setup!"
  333. fi
  334. if ask_yn "Do you want to inspect the installation?" Ny; then
  335. inspect_service
  336. fi
  337. }
  338. install_check() {
  339. if service_account_is_available "$SERVICE_USER"; then
  340. info_msg "Service account $SERVICE_USER exists."
  341. else
  342. err_msg "Service account $SERVICE_USER does not exists!"
  343. fi
  344. if pyenv_is_available; then
  345. info_msg "~$SERVICE_USER: python environment is available."
  346. else
  347. err_msg "~$SERVICE_USER: python environment is not available!"
  348. fi
  349. if clone_is_available; then
  350. info_msg "~$SERVICE_USER: SearXNG software is installed."
  351. else
  352. err_msg "~$SERVICE_USER: Missing SearXNG software!"
  353. fi
  354. if uWSGI_app_enabled "$SEARXNG_UWSGI_APP"; then
  355. info_msg "uWSGI app $SEARXNG_UWSGI_APP is enabled."
  356. else
  357. err_msg "uWSGI app $SEARXNG_UWSGI_APP not enabled!"
  358. fi
  359. uWSGI_app_available "$SEARXNG_UWSGI_APP" \
  360. || err_msg "uWSGI app $SEARXNG_UWSGI_APP not available!"
  361. sudo -H -u "${SERVICE_USER}" "${SEARXNG_PYENV}/bin/python" "utils/searxng_check.py"
  362. if uWSGI_app_available 'searx.ini'; then
  363. warn_msg "old searx.ini uWSGI app exists"
  364. warn_msg "you need to reinstall $SERVICE_USER --> $0 reinstall all"
  365. fi
  366. }
  367. update_searx() {
  368. rst_title "Update SearXNG instance"
  369. rst_para "fetch from $GIT_URL and reset to origin/$GIT_BRANCH"
  370. tee_stderr 0.3 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  371. cd ${SEARXNG_SRC}
  372. git fetch origin "$GIT_BRANCH"
  373. git reset --hard "origin/$GIT_BRANCH"
  374. pip install -U pip
  375. pip install -U setuptools
  376. pip install -U wheel
  377. pip install -U pyyaml
  378. pip install -U -e .
  379. EOF
  380. install_settings
  381. uWSGI_restart "$SEARXNG_UWSGI_APP"
  382. }
  383. remove_all() {
  384. rst_title "De-Install SearXNG (service)"
  385. rst_para "\
  386. It goes without saying that this script can only be used to remove
  387. installations that were installed with this script."
  388. if ! ask_yn "Do you really want to deinstall SearXNG?"; then
  389. return
  390. fi
  391. remove_searx_uwsgi
  392. drop_service_account "${SERVICE_USER}"
  393. remove_settings
  394. wait_key
  395. if service_is_available "${PUBLIC_URL}"; then
  396. MSG="** Don't forgett to remove your public site! (${PUBLIC_URL}) **" wait_key 10
  397. fi
  398. }
  399. assert_user() {
  400. rst_title "user $SERVICE_USER" section
  401. echo
  402. if getent passwd "$SERVICE_USER" > /dev/null; then
  403. echo "user exists"
  404. return 0
  405. fi
  406. tee_stderr 1 <<EOF | bash | prefix_stdout
  407. useradd --shell /bin/bash --system \
  408. --home-dir "$SERVICE_HOME" \
  409. --comment 'Privacy-respecting metasearch engine' $SERVICE_USER
  410. mkdir "$SERVICE_HOME"
  411. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  412. groups $SERVICE_USER
  413. EOF
  414. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  415. #export SERVICE_HOME
  416. #echo "export SERVICE_HOME=$SERVICE_HOME"
  417. }
  418. clone_is_available() {
  419. [[ -f "$SEARXNG_SRC/.git/config" ]]
  420. }
  421. # shellcheck disable=SC2164
  422. clone_searx() {
  423. rst_title "Clone SearXNG sources" section
  424. echo
  425. if ! sudo -i -u "$SERVICE_USER" ls -d "$REPO_ROOT" > /dev/null; then
  426. die 42 "user '$SERVICE_USER' missed read permission: $REPO_ROOT"
  427. fi
  428. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  429. if [[ ! "${SERVICE_HOME}" ]]; then
  430. err_msg "to clone SearXNG sources, user $SERVICE_USER hast to be created first"
  431. return 42
  432. fi
  433. if [[ ! $(git show-ref "refs/heads/${GIT_BRANCH}") ]]; then
  434. warn_msg "missing local branch ${GIT_BRANCH}"
  435. info_msg "create local branch ${GIT_BRANCH} from start point: origin/${GIT_BRANCH}"
  436. git branch "${GIT_BRANCH}" "origin/${GIT_BRANCH}"
  437. fi
  438. if [[ ! $(git rev-parse --abbrev-ref HEAD) == "${GIT_BRANCH}" ]]; then
  439. warn_msg "take into account, installing branch $GIT_BRANCH while current branch is $(git rev-parse --abbrev-ref HEAD)"
  440. fi
  441. export SERVICE_HOME
  442. git_clone "$REPO_ROOT" "$SEARXNG_SRC" \
  443. "$GIT_BRANCH" "$SERVICE_USER"
  444. pushd "${SEARXNG_SRC}" > /dev/null
  445. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  446. cd "${SEARXNG_SRC}"
  447. git remote set-url origin ${GIT_URL}
  448. git config user.email "$ADMIN_EMAIL"
  449. git config user.name "$ADMIN_NAME"
  450. git config --list
  451. EOF
  452. popd > /dev/null
  453. }
  454. prompt_installation_status(){
  455. # shellcheck disable=SC2034
  456. local GIT_URL GIT_BRANCH VERSION_STRING VERSION_TAG
  457. local ret_val state branch remote remote_url
  458. state="$(install_searx_get_state)"
  459. case $state in
  460. missing-searx-clone|missing-searx-pyenv)
  461. info_msg "${_BBlue}(status: $(install_searx_get_state))${_creset}"
  462. return 0
  463. ;;
  464. *)
  465. info_msg "SearXNG instance already installed at: $SEARXNG_SRC"
  466. info_msg "status: ${_BBlue}$(install_searx_get_state)${_creset} "
  467. branch="$(git name-rev --name-only HEAD)"
  468. remote="$(git config branch."${branch}".remote)"
  469. remote_url="$(git config remote."${remote}".url)"
  470. eval "$(get_installed_version_variables)"
  471. ret_val=0
  472. if ! [ "$GIT_URL" = "$remote_url" ]; then
  473. warn_msg "instance's git URL: '${GIT_URL}'" \
  474. "differs from local clone's remote URL: ${remote_url}"
  475. ret_val=42
  476. fi
  477. if ! [ "$GIT_BRANCH" = "$branch" ]; then
  478. warn_msg "instance git branch: ${GIT_BRANCH}" \
  479. "differs from local clone's branch: ${branch}"
  480. ret_val=42
  481. fi
  482. return $ret_val
  483. ;;
  484. esac
  485. }
  486. verify_continue_install(){
  487. if ! prompt_installation_status; then
  488. MSG="[${_BCyan}KEY${_creset}] to continue installation / [${_BCyan}CTRL-C${_creset}] to exit" \
  489. wait_key
  490. fi
  491. }
  492. prompt_installation_setting(){
  493. # usage: prompt_installation_setting brand.docs_url
  494. #
  495. # Prompts the value of the (YAML) setting in the SearXNG instance.
  496. local _state
  497. _state="$(install_searx_get_state)"
  498. case $_state in
  499. python-installed|installer-modified)
  500. sudo -H -u "${SERVICE_USER}" "${SEARXNG_PYENV}/bin/python" <<EOF
  501. import sys
  502. from searx import get_setting
  503. name = "${1}"
  504. unset = object()
  505. value = get_setting(name, unset)
  506. if value is unset:
  507. sys.stderr.write("error: setting '%s' does not exists\n" % name)
  508. sys.exit(42)
  509. print(value)
  510. sys.exit(0)
  511. EOF
  512. ;;
  513. *)
  514. return 42
  515. ;;
  516. esac
  517. }
  518. get_installed_version_variables() {
  519. # usage: eval "$(get_installed_version_variables)"
  520. #
  521. # Set variables VERSION_STRING, VERSION_TAG, GIT_URL, GIT_BRANCH
  522. local _state
  523. _state="$(install_searx_get_state)"
  524. case $_state in
  525. python-installed|installer-modified)
  526. sudo -H -u "${SERVICE_USER}" "${SEARXNG_PYENV}/bin/python" -m searx.version;;
  527. *)
  528. return 42
  529. ;;
  530. esac
  531. }
  532. init_SEARX_SRC(){
  533. rst_title "Update instance: ${SEARXNG_SRC}/" section
  534. if ! clone_is_available; then
  535. err_msg "you have to install SearXNG first"
  536. return 1
  537. fi
  538. init_SEARX_SRC_INIT_FILES
  539. if [ ${#SEARX_SRC_INIT_FILES[*]} -eq 0 ]; then
  540. info_msg "no files registered in SEARX_SRC_INIT_FILES"
  541. return 2
  542. fi
  543. echo
  544. echo "Update instance with file(s) from: ${REPO_ROOT}"
  545. echo
  546. for i in "${SEARX_SRC_INIT_FILES[@]}"; do
  547. echo "- $i"
  548. done
  549. echo
  550. echo "Be careful when modifying an existing installation."
  551. if ! ask_yn "Do you really want to update these files in the instance?" Yn; then
  552. return 42
  553. fi
  554. for fname in "${SEARX_SRC_INIT_FILES[@]}"; do
  555. while true; do
  556. choose_one _reply "choose next step with file ${fname}" \
  557. "replace file" \
  558. "leave file unchanged" \
  559. "diff files" \
  560. "interactive shell"
  561. case $_reply in
  562. "leave file unchanged")
  563. break
  564. ;;
  565. "replace file")
  566. info_msg "copy: ${REPO_ROOT}/${fname} --> ${SEARXNG_SRC}/${fname}"
  567. cp "${REPO_ROOT}/${fname}" "${SEARXNG_SRC}/${fname}"
  568. break
  569. ;;
  570. "diff files")
  571. $DIFF_CMD "${SEARXNG_SRC}/${fname}" "${REPO_ROOT}/${fname}"
  572. ;;
  573. "interactive shell")
  574. backup_file "${SEARXNG_SRC}/${fname}"
  575. echo -e "// edit ${_Red}${dst}${_creset} to your needs"
  576. echo -e "// exit with [${_BCyan}CTRL-D${_creset}]"
  577. sudo -H -u "${SERVICE_USER}" -i
  578. $DIFF_CMD "${SEARXNG_SRC}/${fname}" "${REPO_ROOT}/${fname}"
  579. echo
  580. echo -e "// ${_BBlack}did you edit file ...${_creset}"
  581. echo -en "// ${_Red}${dst}${_creset}"
  582. if ask_yn "//${_BBlack}... to your needs?${_creset}"; then
  583. break
  584. fi
  585. ;;
  586. esac
  587. done
  588. done
  589. }
  590. install_DOT_CONFIG(){
  591. rst_title "Update instance: ${SEARXNG_SRC}/.config.sh" section
  592. if cmp --silent "${REPO_ROOT}/.config.sh" "${SEARXNG_SRC}/.config.sh"; then
  593. info_msg "${SEARXNG_SRC}/.config.sh is up to date"
  594. return 0
  595. fi
  596. diff "${REPO_ROOT}/.config.sh" "${SEARXNG_SRC}/.config.sh"
  597. if ! ask_yn "Do you want to copy file .config.sh into instance?" Yn; then
  598. return 42
  599. fi
  600. backup_file "${SEARXNG_SRC}/.config.sh"
  601. cp "${REPO_ROOT}/.config.sh" "${SEARXNG_SRC}/.config.sh"
  602. }
  603. install_settings() {
  604. rst_title "${SEARXNG_SETTINGS_PATH}" section
  605. if ! clone_is_available; then
  606. err_msg "you have to install SearXNG first"
  607. exit 42
  608. fi
  609. mkdir -p "$(dirname "${SEARXNG_SETTINGS_PATH}")"
  610. install_template --no-eval \
  611. "${SEARXNG_SETTINGS_PATH}" \
  612. "${SERVICE_USER}" "${SERVICE_GROUP}"
  613. configure_searx
  614. }
  615. remove_settings() {
  616. rst_title "remove SearXNG settings" section
  617. echo
  618. info_msg "delete ${SEARXNG_SETTINGS_PATH}"
  619. rm -f "${SEARXNG_SETTINGS_PATH}"
  620. }
  621. remove_searx() {
  622. rst_title "Drop SearXNG sources" section
  623. if ask_yn "Do you really want to drop SearXNG sources ($SEARXNG_SRC)?"; then
  624. rm -rf "$SEARXNG_SRC"
  625. else
  626. rst_para "Leave SearXNG sources unchanged."
  627. fi
  628. }
  629. pyenv_is_available() {
  630. [[ -f "${SEARXNG_PYENV}/bin/activate" ]]
  631. }
  632. create_pyenv() {
  633. rst_title "Create virtualenv (python)" section
  634. echo
  635. if [[ ! -f "${SEARXNG_SRC}/manage" ]]; then
  636. err_msg "to create pyenv for SearXNG, SearXNG has to be cloned first"
  637. return 42
  638. fi
  639. info_msg "create pyenv in ${SEARXNG_PYENV}"
  640. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  641. rm -rf "${SEARXNG_PYENV}"
  642. python3 -m venv "${SEARXNG_PYENV}"
  643. grep -qFs -- 'source ${SEARXNG_PYENV}/bin/activate' ~/.profile \
  644. || echo 'source ${SEARXNG_PYENV}/bin/activate' >> ~/.profile
  645. EOF
  646. info_msg "inspect python's virtual environment"
  647. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  648. command -v python && python --version
  649. EOF
  650. wait_key
  651. info_msg "install needed python packages"
  652. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  653. pip install -U pip
  654. pip install -U setuptools
  655. pip install -U wheel
  656. pip install -U pyyaml
  657. cd ${SEARXNG_SRC}
  658. pip install -e .
  659. EOF
  660. }
  661. remove_pyenv() {
  662. rst_title "Remove virtualenv (python)" section
  663. if ! ask_yn "Do you really want to drop ${SEARXNG_PYENV} ?"; then
  664. return
  665. fi
  666. info_msg "remove pyenv activation from ~/.profile"
  667. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  668. grep -v 'source ${SEARXNG_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  669. mv ~/.profile.## ~/.profile
  670. EOF
  671. rm -rf "${SEARXNG_PYENV}"
  672. }
  673. configure_searx() {
  674. rst_title "Configure SearXNG" section
  675. rst_para "Setup SearXNG config located at $SEARXNG_SETTINGS_PATH"
  676. echo
  677. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  678. cd ${SEARXNG_SRC}
  679. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARXNG_SETTINGS_PATH"
  680. EOF
  681. }
  682. test_local_searx() {
  683. rst_title "Testing SearXNG instance localy" section
  684. echo
  685. if service_is_available "http://${SEARXNG_INTERNAL_HTTP}" &>/dev/null; then
  686. err_msg "URL/port http://${SEARXNG_INTERNAL_HTTP} is already in use, you"
  687. err_msg "should stop that service before starting local tests!"
  688. if ! ask_yn "Continue with local tests?"; then
  689. return
  690. fi
  691. fi
  692. sed -i -e "s/debug: false/debug: true/g" "$SEARXNG_SETTINGS_PATH"
  693. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  694. export SEARXNG_SETTINGS_PATH="${SEARXNG_SETTINGS_PATH}"
  695. cd ${SEARXNG_SRC}
  696. timeout 10 python searx/webapp.py &
  697. sleep 3
  698. curl --location --verbose --head --insecure $SEARXNG_INTERNAL_HTTP
  699. EOF
  700. sed -i -e "s/debug: true/debug: false/g" "$SEARXNG_SETTINGS_PATH"
  701. }
  702. install_searx_uwsgi() {
  703. rst_title "Install SearXNG's uWSGI app (searxng.ini)" section
  704. echo
  705. install_uwsgi
  706. uWSGI_install_app "$SEARXNG_UWSGI_APP"
  707. }
  708. remove_searx_uwsgi() {
  709. rst_title "Remove SearXNG's uWSGI app (searxng.ini)" section
  710. echo
  711. uWSGI_remove_app "$SEARXNG_UWSGI_APP"
  712. }
  713. activate_service() {
  714. rst_title "Activate SearXNG (service)" section
  715. echo
  716. uWSGI_enable_app "$SEARXNG_UWSGI_APP"
  717. uWSGI_restart "$SEARXNG_UWSGI_APP"
  718. }
  719. deactivate_service() {
  720. rst_title "De-Activate SearXNG (service)" section
  721. echo
  722. uWSGI_disable_app "$SEARXNG_UWSGI_APP"
  723. uWSGI_restart "$SEARXNG_UWSGI_APP"
  724. }
  725. enable_image_proxy() {
  726. info_msg "try to enable image_proxy ..."
  727. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  728. cd ${SEARXNG_SRC}
  729. sed -i -e "s/image_proxy: false/image_proxy: true/g" "$SEARXNG_SETTINGS_PATH"
  730. EOF
  731. uWSGI_restart "$SEARXNG_UWSGI_APP"
  732. }
  733. disable_image_proxy() {
  734. info_msg "try to enable image_proxy ..."
  735. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  736. cd ${SEARXNG_SRC}
  737. sed -i -e "s/image_proxy: true/image_proxy: false/g" "$SEARXNG_SETTINGS_PATH"
  738. EOF
  739. uWSGI_restart "$SEARXNG_UWSGI_APP"
  740. }
  741. enable_debug() {
  742. warn_msg "Do not enable debug in production environments!!"
  743. info_msg "try to enable debug mode ..."
  744. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  745. cd ${SEARXNG_SRC}
  746. sed -i -e "s/debug: false/debug: true/g" "$SEARXNG_SETTINGS_PATH"
  747. EOF
  748. uWSGI_restart "$SEARXNG_UWSGI_APP"
  749. }
  750. disable_debug() {
  751. info_msg "try to disable debug mode ..."
  752. tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 | prefix_stdout "$_service_prefix"
  753. cd ${SEARXNG_SRC}
  754. sed -i -e "s/debug: true/debug: false/g" "$SEARXNG_SETTINGS_PATH"
  755. EOF
  756. uWSGI_restart "$SEARXNG_UWSGI_APP"
  757. }
  758. set_result_proxy() {
  759. # usage: set_result_proxy <URL> [<key>]
  760. info_msg "try to set result proxy: '$1' ($2)"
  761. cp "${SEARXNG_SETTINGS_PATH}" "${SEARXNG_SETTINGS_PATH}.bak"
  762. _set_result_proxy "$1" "$2" > "${SEARXNG_SETTINGS_PATH}"
  763. }
  764. _set_result_proxy() {
  765. local line
  766. local stage=0
  767. local url=" url: $1"
  768. local key=" key: !!binary \"$2\""
  769. if [[ -z $2 ]]; then
  770. key=
  771. fi
  772. while IFS= read -r line
  773. do
  774. if [[ $stage = 0 ]] || [[ $stage = 2 ]] ; then
  775. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*result_proxy[[:space:]]*:[[:space:]]*$ ]]; then
  776. if [[ $stage = 0 ]]; then
  777. stage=1
  778. echo "result_proxy:"
  779. continue
  780. elif [[ $stage = 2 ]]; then
  781. continue
  782. fi
  783. fi
  784. fi
  785. if [[ $stage = 1 ]] || [[ $stage = 2 ]] ; then
  786. if [[ $line =~ ^[[:space:]]*#*[[:space:]]*url[[:space:]]*:[[:space:]] ]]; then
  787. [[ $stage = 1 ]] && echo "$url"
  788. continue
  789. elif [[ $line =~ ^[[:space:]]*#*[[:space:]]*key[[:space:]]*:[[:space:]] ]]; then
  790. [[ $stage = 1 ]] && [[ -n $key ]] && echo "$key"
  791. continue
  792. elif [[ $line =~ ^[[:space:]]*$ ]]; then
  793. stage=2
  794. fi
  795. fi
  796. echo "$line"
  797. done < "${SEARXNG_SETTINGS_PATH}.bak"
  798. }
  799. function has_substring() {
  800. [[ "$1" != "${2/$1/}" ]]
  801. }
  802. inspect_service() {
  803. rst_title "service status & log"
  804. cat <<EOF
  805. sourced ${DOT_CONFIG} :
  806. SERVICE_USER : ${SERVICE_USER}
  807. SERVICE_HOME : ${SERVICE_HOME}
  808. EOF
  809. install_log_searx_instance
  810. install_check
  811. if in_container; then
  812. lxc_suite_info
  813. else
  814. info_msg "public URL --> ${PUBLIC_URL}"
  815. info_msg "internal URL --> http://${SEARXNG_INTERNAL_HTTP}"
  816. fi
  817. if ! service_is_available "http://${SEARXNG_INTERNAL_HTTP}"; then
  818. err_msg "uWSGI app (service) at http://${SEARXNG_INTERNAL_HTTP} is not available!"
  819. MSG="${_Green}[${_BCyan}CTRL-C${_Green}] to stop or [${_BCyan}KEY${_Green}] to continue"\
  820. wait_key
  821. fi
  822. if ! service_is_available "${PUBLIC_URL}"; then
  823. warn_msg "Public service at ${PUBLIC_URL} is not available!"
  824. if ! in_container; then
  825. warn_msg "Check if public name is correct and routed or use the public IP from above."
  826. fi
  827. fi
  828. local _debug_on
  829. if ask_yn "Enable SearXNG debug mode?"; then
  830. enable_debug
  831. _debug_on=1
  832. fi
  833. echo
  834. case $DIST_ID-$DIST_VERS in
  835. ubuntu-*|debian-*)
  836. systemctl --no-pager -l status "${SERVICE_NAME}"
  837. ;;
  838. arch-*)
  839. systemctl --no-pager -l status "uwsgi@${SERVICE_NAME%.*}"
  840. ;;
  841. fedora-*|centos-7)
  842. systemctl --no-pager -l status uwsgi
  843. ;;
  844. esac
  845. # shellcheck disable=SC2059
  846. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  847. read -r -s -n1 -t 5
  848. echo
  849. while true; do
  850. trap break 2
  851. case $DIST_ID-$DIST_VERS in
  852. ubuntu-*|debian-*) tail -f /var/log/uwsgi/app/searx.log ;;
  853. arch-*) journalctl -f -u "uwsgi@${SERVICE_NAME%.*}" ;;
  854. fedora-*|centos-7) journalctl -f -u uwsgi ;;
  855. esac
  856. done
  857. if [[ $_debug_on == 1 ]]; then
  858. disable_debug
  859. fi
  860. return 0
  861. }
  862. install_apache_site() {
  863. rst_title "Install Apache site $APACHE_SEARX_SITE"
  864. rst_para "\
  865. This installs the SearXNG uwsgi app as apache site. If your server is public to
  866. the internet, you should instead use a reverse proxy (filtron) to block
  867. excessively bot queries."
  868. ! apache_is_installed && err_msg "Apache is not installed."
  869. if ! ask_yn "Do you really want to continue?" Yn; then
  870. return
  871. else
  872. install_apache
  873. fi
  874. apache_install_site --variant=uwsgi "${APACHE_SEARX_SITE}"
  875. rst_title "Install SearXNG's uWSGI app (searxng.ini)" section
  876. echo
  877. uWSGI_install_app --variant=socket "$SEARXNG_UWSGI_APP"
  878. if ! service_is_available "${PUBLIC_URL}"; then
  879. err_msg "Public service at ${PUBLIC_URL} is not available!"
  880. fi
  881. }
  882. remove_apache_site() {
  883. rst_title "Remove Apache site ${APACHE_SEARX_SITE}"
  884. rst_para "\
  885. This removes apache site ${APACHE_SEARX_SITE}."
  886. ! apache_is_installed && err_msg "Apache is not installed."
  887. if ! ask_yn "Do you really want to continue?" Yn; then
  888. return
  889. fi
  890. apache_remove_site "${APACHE_SEARX_SITE}"
  891. rst_title "Remove SearXNG's uWSGI app (searxng.ini)" section
  892. echo
  893. uWSGI_remove_app "$SEARXNG_UWSGI_APP"
  894. }
  895. rst-doc() {
  896. local debian="${SEARX_PACKAGES_debian}"
  897. local arch="${SEARX_PACKAGES_arch}"
  898. local fedora="${SEARX_PACKAGES_fedora}"
  899. local centos="${SEARX_PACKAGES_centos}"
  900. local debian_build="${BUILD_PACKAGES_debian}"
  901. local arch_build="${BUILD_PACKAGES_arch}"
  902. local fedora_build="${BUILD_PACKAGES_fedora}"
  903. local centos_build="${SEARX_PACKAGES_centos}"
  904. debian="$(echo "${debian}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  905. arch="$(echo "${arch}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  906. fedora="$(echo "${fedora}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  907. centos="$(echo "${centos}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  908. debian_build="$(echo "${debian_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  909. arch_build="$(echo "${arch_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  910. fedora_build="$(echo "${fedora_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  911. centos_build="$(echo "${centos_build}" | sed 's/.*/ & \\/' | sed '$ s/.$//')"
  912. eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/searx.rst")\""
  913. # I use ubuntu-20.04 here to demonstrate that versions are also suported,
  914. # normaly debian-* and ubuntu-* are most the same.
  915. for DIST_NAME in ubuntu-20.04 arch fedora; do
  916. (
  917. DIST_ID=${DIST_NAME%-*}
  918. DIST_VERS=${DIST_NAME#*-}
  919. [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=
  920. uWSGI_distro_setup
  921. echo -e "\n.. START searxng uwsgi-description $DIST_NAME"
  922. case $DIST_ID-$DIST_VERS in
  923. ubuntu-*|debian-*) cat <<EOF
  924. .. code:: bash
  925. # init.d --> /usr/share/doc/uwsgi/README.Debian.gz
  926. # For uWSGI debian uses the LSB init process, this might be changed
  927. # one day, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=833067
  928. create ${uWSGI_APPS_AVAILABLE}/${SEARXNG_UWSGI_APP}
  929. enable: sudo -H ln -s ${uWSGI_APPS_AVAILABLE}/${SEARXNG_UWSGI_APP} ${uWSGI_APPS_ENABLED}/
  930. start: sudo -H service uwsgi start ${SEARXNG_UWSGI_APP%.*}
  931. restart: sudo -H service uwsgi restart ${SEARXNG_UWSGI_APP%.*}
  932. stop: sudo -H service uwsgi stop ${SEARXNG_UWSGI_APP%.*}
  933. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARXNG_UWSGI_APP}
  934. EOF
  935. ;;
  936. arch-*) cat <<EOF
  937. .. code:: bash
  938. # systemd --> /usr/lib/systemd/system/uwsgi@.service
  939. # For uWSGI archlinux uses systemd template units, see
  940. # - http://0pointer.de/blog/projects/instances.html
  941. # - https://uwsgi-docs.readthedocs.io/en/latest/Systemd.html#one-service-per-app-in-systemd
  942. create: ${uWSGI_APPS_ENABLED}/${SEARXNG_UWSGI_APP}
  943. enable: sudo -H systemctl enable uwsgi@${SEARXNG_UWSGI_APP%.*}
  944. start: sudo -H systemctl start uwsgi@${SEARXNG_UWSGI_APP%.*}
  945. restart: sudo -H systemctl restart uwsgi@${SEARXNG_UWSGI_APP%.*}
  946. stop: sudo -H systemctl stop uwsgi@${SEARXNG_UWSGI_APP%.*}
  947. disable: sudo -H systemctl disable uwsgi@${SEARXNG_UWSGI_APP%.*}
  948. EOF
  949. ;;
  950. fedora-*|centos-7) cat <<EOF
  951. .. code:: bash
  952. # systemd --> /usr/lib/systemd/system/uwsgi.service
  953. # The unit file starts uWSGI in emperor mode (/etc/uwsgi.ini), see
  954. # - https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html
  955. create: ${uWSGI_APPS_ENABLED}/${SEARXNG_UWSGI_APP}
  956. restart: sudo -H touch ${uWSGI_APPS_ENABLED}/${SEARXNG_UWSGI_APP}
  957. disable: sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARXNG_UWSGI_APP}
  958. EOF
  959. ;;
  960. esac
  961. echo -e ".. END searxng uwsgi-description $DIST_NAME"
  962. echo -e "\n.. START searxng uwsgi-appini $DIST_NAME"
  963. echo ".. code:: bash"
  964. echo
  965. eval "echo \"$(< "${TEMPLATES}/${uWSGI_APPS_AVAILABLE}/${SEARXNG_UWSGI_APP}")\"" | prefix_stdout " "
  966. echo -e "\n.. END searxng uwsgi-appini $DIST_NAME"
  967. )
  968. done
  969. }
  970. # ----------------------------------------------------------------------------
  971. main "$@"
  972. # ----------------------------------------------------------------------------