searx.sh 31 KB

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