searx.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. #!/usr/bin/env bash
  2. # -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
  3. # shellcheck disable=SC2119
  4. # shellcheck source=utils/lib.sh
  5. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  6. # ----------------------------------------------------------------------------
  7. # config
  8. # ----------------------------------------------------------------------------
  9. SERVICE_NAME="searx"
  10. SERVICE_USER="${SERVICE_NAME}"
  11. # shellcheck disable=SC2034
  12. SERVICE_GROUP="${SERVICE_USER}"
  13. SERVICE_HOME="/home/${SERVICE_USER}"
  14. SEARX_URL="127.0.0.1:8888"
  15. SEARX_GIT_URL="https://github.com/asciimoo/searx.git"
  16. SEARX_GIT_BRANCH="master"
  17. # FIXME: Arch Linux & RHEL should be added
  18. SEARX_APT_PACKAGES="\
  19. libapache2-mod-uwsgi uwsgi uwsgi-plugin-python3 \
  20. git build-essential libxslt-dev python3-dev python3-babel zlib1g-dev \
  21. libffi-dev libssl-dev"
  22. SEARX_PYENV="${SERVICE_HOME}/searx-pyenv"
  23. SEARX_SRC="${SERVICE_HOME}/searx-src"
  24. SEARX_SETTINGS="${SEARX_SRC}/searx/settings.yml"
  25. SEARX_INSTANCE_NAME="${SEARX_INSTANCE_NAME:-searx@$(uname -n)}"
  26. SEARX_UWSGI_APP="searx.ini"
  27. SEARX_UWSGI_SOCKET="/run/uwsgi/app/searx/socket"
  28. # Apache Settings
  29. SEARX_APACHE_URL="/searx"
  30. SEARX_APACHE_SITE="searx.conf"
  31. # shellcheck disable=SC2034
  32. CONFIG_FILES=(
  33. "${uWSGI_SETUP}/apps-available/${SEARX_UWSGI_APP}"
  34. )
  35. # shellcheck disable=SC2034
  36. CONFIG_BACKUP_ENCRYPTED=(
  37. "${SEARX_SETTINGS}"
  38. )
  39. # ----------------------------------------------------------------------------
  40. usage() {
  41. # ----------------------------------------------------------------------------
  42. # shellcheck disable=SC1117
  43. cat <<EOF
  44. usage:
  45. $(basename "$0") shell
  46. $(basename "$0") install [all|user|pyenv|searx-src|apache]
  47. $(basename "$0") update [searx]
  48. $(basename "$0") remove [all|user|pyenv|searx-src]
  49. $(basename "$0") activate [service]
  50. $(basename "$0") deactivate [service]
  51. $(basename "$0") show [service]
  52. $(basename "$0") option [debug-on|debug-off]
  53. shell
  54. start interactive shell from user ${SERVICE_USER}
  55. install / remove
  56. all: complete (de-) installation of searx service
  57. user: add/remove service user '$SERVICE_USER' at $SERVICE_HOME
  58. searx-src: clone $SEARX_GIT_URL
  59. pyenv: create/remove virtualenv (python) in $SEARX_PYENV
  60. apache: install apache site for searx-uwsgi app
  61. update searx
  62. Update searx installation of user ${SERVICE_USER}
  63. activate
  64. activate and start service daemon (systemd unit)
  65. deactivate service
  66. stop and deactivate service daemon (systemd unit)
  67. show service
  68. run some small tests and show service's status and log
  69. option
  70. set one of te available options
  71. EOF
  72. [ ! -z ${1+x} ] && echo -e "$1"
  73. }
  74. main() {
  75. rst_title "$SERVICE_NAME" part
  76. local _usage="ERROR: unknown or missing $1 command $2"
  77. case $1 in
  78. --source-only) ;;
  79. -h|--help) usage; exit 0;;
  80. shell)
  81. sudo_or_exit
  82. interactive_shell
  83. ;;
  84. show)
  85. case $2 in
  86. service)
  87. sudo_or_exit
  88. show_service
  89. ;;
  90. *) usage "$_usage"; exit 42;;
  91. esac ;;
  92. install)
  93. sudo_or_exit
  94. case $2 in
  95. all) install_all ;;
  96. user) assert_user ;;
  97. pyenv) create_pyenv ;;
  98. searx-src) clone_searx ;;
  99. apache) install_apache_site ;;
  100. *) usage "$_usage"; exit 42;;
  101. esac ;;
  102. update)
  103. sudo_or_exit
  104. case $2 in
  105. searx) update_searx;;
  106. *) usage "$_usage"; exit 42;;
  107. esac ;;
  108. remove)
  109. sudo_or_exit
  110. case $2 in
  111. all) remove_all;;
  112. user) remove_user ;;
  113. pyenv) remove_pyenv ;;
  114. searx-src) remove_searx ;;
  115. *) usage "$_usage"; exit 42;;
  116. esac ;;
  117. activate)
  118. sudo_or_exit
  119. case $2 in
  120. service)
  121. activate_service; uWSGI_restart ;;
  122. *) usage "$_usage"; exit 42;;
  123. esac ;;
  124. deactivate)
  125. sudo_or_exit
  126. case $2 in
  127. service) deactivate_service; uWSGI_restart ;;
  128. *) usage "$_usage"; exit 42;;
  129. esac ;;
  130. option)
  131. sudo_or_exit
  132. case $2 in
  133. debug-on) echo; enable_debug ;;
  134. debug-off) echo; disable_debug ;;
  135. *) usage "$_usage"; exit 42;;
  136. esac ;;
  137. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  138. esac
  139. }
  140. _service_prefix=" |$SERVICE_USER| "
  141. install_all() {
  142. rst_title "Install $SERVICE_NAME (service)"
  143. pkg_install "$SEARX_APT_PACKAGES"
  144. wait_key
  145. assert_user
  146. wait_key
  147. clone_searx
  148. wait_key
  149. create_pyenv
  150. wait_key
  151. configure_searx
  152. wait_key
  153. test_local_searx
  154. wait_key
  155. install_searx_uwsgi
  156. if service_is_available; then
  157. info_msg "URL http://$SEARX_URL is available."
  158. else
  159. err_msg "URL http://$SEARX_URL not available, check searx & uwsgi setup!"
  160. fi
  161. }
  162. update_searx() {
  163. rst_title "Update searx instance"
  164. echo
  165. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  166. cd ${SEARX_SRC}
  167. cp -f ${SEARX_SETTINGS} ${SEARX_SETTINGS}.backup
  168. git stash push -m "BACKUP -- 'update server' at ($(date))"
  169. git checkout -b $SEARX_GIT_BRANCH" --track "$SEARX_GIT_BRANCH"
  170. git pull "$SEARX_GIT_BRANCH"
  171. ${SEARX_SRC}/manage.sh update_packages
  172. EOF
  173. configure_searx
  174. rst_title "${SEARX_SETTINGS}" section
  175. rstBlock 'Diff between new setting file (<) and backup (>):'
  176. echo
  177. diff "$SEARX_SETTINGS}" "${SEARX_SETTINGS}.backup"
  178. local action
  179. choose_one action "What should happen to the settings file? " \
  180. "keep new configuration" \
  181. "revert to the old configuration (backup file)" \
  182. "start interactiv shell"
  183. case $action in
  184. "keep new configuration")
  185. info_msg "continue using new settings file"
  186. ;;
  187. "revert to the old configuration (backup file)")
  188. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  189. cp -f ${SEARX_SETTINGS}.backup ${SEARX_SETTINGS}
  190. EOF
  191. ;;
  192. "start interactiv shell")
  193. interactive_shell
  194. ;;
  195. esac
  196. chown "${SERVICE_USER}:${SERVICE_USER}" "${SEARX_SETTINGS}"
  197. # shellcheck disable=SC2016
  198. rst_para 'Diff between local modified settings (<) and $SEARX_GIT_BRANCH branch (>):'
  199. echo
  200. git_diff
  201. wait_key
  202. uWSGI_restart
  203. }
  204. remove_all() {
  205. rst_title "De-Install $SERVICE_NAME (service)"
  206. rst_para "\
  207. It goes without saying that this script can only be used to remove
  208. installations that were installed with this script."
  209. if ! ask_yn "Do you really want to deinstall $SERVICE_NAME?"; then
  210. return
  211. fi
  212. remove_searx_uwsgi
  213. wait_key
  214. remove_user
  215. }
  216. user_is_available() {
  217. sudo -i -u "$SERVICE_USER" echo \$HOME &>/dev/null
  218. }
  219. assert_user() {
  220. rst_title "user $SERVICE_USER" section
  221. echo
  222. tee_stderr 1 <<EOF | bash | prefix_stdout
  223. sudo -H adduser --shell /bin/bash --system --home "$SERVICE_HOME" \
  224. --disabled-password --group --gecos 'searx' $SERVICE_USER
  225. sudo -H usermod -a -G shadow $SERVICE_USER
  226. groups $SERVICE_USER
  227. EOF
  228. #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  229. #export SERVICE_HOME
  230. #echo "export SERVICE_HOME=$SERVICE_HOME"
  231. }
  232. remove_user() {
  233. rst_title "Drop $SERVICE_USER HOME" section
  234. if ask_yn "Do you really want to drop $SERVICE_USER home folder?"; then
  235. userdel -r -f "$SERVICE_USER" 2>&1 | prefix_stdout
  236. else
  237. rst_para "Leave HOME folder $(du -sh "$SERVICE_HOME") unchanged."
  238. fi
  239. }
  240. clone_is_available() {
  241. [[ -f "$SEARX_SETTINGS" ]]
  242. }
  243. # shellcheck disable=SC2164
  244. clone_searx() {
  245. rst_title "Clone searx sources" section
  246. echo
  247. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"
  248. if [[ ! "${SERVICE_HOME}" ]]; then
  249. err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"
  250. return 42
  251. fi
  252. export SERVICE_HOME
  253. git_clone "$SEARX_GIT_URL" "$SEARX_SRC" \
  254. "$SEARX_GIT_BRANCH" "$SERVICE_USER"
  255. pushd "${SEARX_SRC}" > /dev/null
  256. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  257. cd "${SEARX_SRC}"
  258. git config user.email "$ADMIN_EMAIL"
  259. git config user.name "$ADMIN_NAME"
  260. git config --list
  261. EOF
  262. popd > /dev/null
  263. }
  264. remove_searx() {
  265. rst_title "Drop searx sources" section
  266. if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then
  267. rm -rf "$SEARX_SRC"
  268. else
  269. rst_para "Leave searx sources unchanged."
  270. fi
  271. }
  272. pyenv_is_available() {
  273. [[ -f "${SEARX_PYENV}/bin/activate" ]]
  274. }
  275. create_pyenv() {
  276. rst_title "Create virtualenv (python)" section
  277. echo
  278. if [[ ! -f "${SEARX_SRC}/manage.sh" ]]; then
  279. err_msg "to create pyenv for searx, searx has to be cloned first"
  280. return 42
  281. fi
  282. info_msg "create pyenv in ${SEARX_PYENV}"
  283. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  284. rm -rf "${SEARX_PYENV}"
  285. python3 -m venv "${SEARX_PYENV}"
  286. grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \
  287. || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profile
  288. EOF
  289. info_msg "inspect python's virtual environment"
  290. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  291. command -v python && python --version
  292. EOF
  293. wait_key
  294. info_msg "install needed python packages"
  295. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  296. ${SEARX_SRC}/manage.sh update_packages
  297. EOF
  298. }
  299. remove_pyenv() {
  300. rst_title "Remove virtualenv (python)" section
  301. if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then
  302. return
  303. fi
  304. info_msg "remove pyenv activation from ~/.profile"
  305. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  306. grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##
  307. mv ~/.profile.## ~/.profile
  308. EOF
  309. rm -rf "${SEARX_PYENV}"
  310. }
  311. configure_searx() {
  312. rst_title "Configure searx" section
  313. rst_para "Setup searx config located at $SEARX_SETTINGS"
  314. echo
  315. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  316. cd ${SEARX_SRC}
  317. sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS"
  318. sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS"
  319. EOF
  320. }
  321. test_local_searx() {
  322. rst_title "Testing searx instance localy" section
  323. echo
  324. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  325. cd ${SEARX_SRC}
  326. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS"
  327. timeout 5 python3 searx/webapp.py &
  328. sleep 1
  329. curl --location --verbose --head --insecure $SEARX_URL
  330. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS"
  331. EOF
  332. }
  333. install_searx_uwsgi() {
  334. rst_title "Install searx's uWSGI app (searx.ini)" section
  335. echo
  336. uWSGI_install_app "$SEARX_UWSGI_APP"
  337. }
  338. remove_searx_uwsgi() {
  339. rst_title "Remove searx's uWSGI app (searx.ini)" section
  340. echo
  341. uWSGI_remove_app "$SEARX_UWSGI_APP"
  342. }
  343. activate_service() {
  344. rst_title "Activate $SERVICE_NAME (service)" section
  345. echo
  346. uWSGI_enable_app "$SEARX_UWSGI_APP"
  347. }
  348. deactivate_service() {
  349. rst_title "De-Activate $SERVICE_NAME (service)" section
  350. echo
  351. uWSGI_disable_app "$SEARX_UWSGI_APP"
  352. }
  353. interactive_shell() {
  354. echo "// exit with CTRL-D"
  355. sudo -H -u "${SERVICE_USER}" -i
  356. }
  357. git_diff() {
  358. sudo -H -u "${SERVICE_USER}" -i <<EOF
  359. cd ${SEARX_REPO_FOLDER}
  360. git --no-pager diff
  361. EOF
  362. }
  363. service_is_available() {
  364. curl --insecure "http://$SEARX_URL" &>/dev/null
  365. }
  366. enable_debug() {
  367. info_msg "try to enable debug mode ..."
  368. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  369. cd ${SEARX_SRC}
  370. sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS"
  371. EOF
  372. uWSGI_restart
  373. }
  374. disable_debug() {
  375. info_msg "try to disable debug mode ..."
  376. tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"
  377. cd ${SEARX_SRC}
  378. sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS"
  379. EOF
  380. uWSGI_restart
  381. }
  382. show_service() {
  383. rst_title "service status & log"
  384. echo
  385. apache_is_installed && info_msg "Apache is installed."
  386. if user_is_available; then
  387. info_msg "service account $SERVICE_USER available."
  388. else
  389. err_msg "service account $SERVICE_USER not available!"
  390. fi
  391. if service_is_available; then
  392. info_msg "URL http://$SEARX_URL is available."
  393. else
  394. err_msg "URL http://$SEARX_URL not available!"
  395. fi
  396. if pyenv_is_available; then
  397. info_msg "${SEARX_PYENV}/bin/activate is available."
  398. else
  399. err_msg "${SEARX_PYENV}/bin/activate not available!"
  400. fi
  401. if clone_is_available; then
  402. info_msg "Searx software is installed."
  403. else
  404. err_msg "Missing searx software!"
  405. fi
  406. uWSGI_app_available "$SEARX_UWSGI_APP" \
  407. || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"
  408. if uWSGI_app_enabled "$SEARX_UWSGI_APP"; then
  409. info_msg "uWSGI app $SEARX_UWSGI_APP is enabled."
  410. else
  411. err_msg "uWSGI app $SEARX_UWSGI_APP not enabled!"
  412. fi
  413. local _debug_on
  414. if ask_yn "Enable searx debug mode?"; then
  415. enable_debug
  416. _debug_on=1
  417. fi
  418. echo
  419. systemctl --no-pager -l status uwsgi.service
  420. echo
  421. read -r -s -n1 -t 2 -p "// use CTRL-C to stop monitoring the log"
  422. echo
  423. while true; do
  424. trap break 2
  425. #journalctl -f -u uwsgi.service
  426. tail -f /var/log/uwsgi/app/searx.log
  427. done
  428. if [[ $_debug_on == 1 ]]; then
  429. disable_debug
  430. fi
  431. return 0
  432. }
  433. install_apache_site() {
  434. rst_title "Install Apache site $SEARX_APACHE_SITE"
  435. rst_para "\
  436. This installs the searx uwsgi app as apache site. If your server ist public to
  437. the internet you should instead use a reverse proxy (filtron) to block
  438. excessively bot queries."
  439. ! apache_is_installed && err_msg "Apache is not installed."
  440. if ! ask_yn "Do you really want to install apache site for searx-uwsgi?"; then
  441. return
  442. fi
  443. echo
  444. apache_install_site --variant=uwsgi "${SEARX_APACHE_SITE}"
  445. }
  446. # ----------------------------------------------------------------------------
  447. main "$@"
  448. # ----------------------------------------------------------------------------