morty.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  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 source=utils/lib.sh
  5. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  6. # shellcheck source=utils/brand.env
  7. source "${REPO_ROOT}/utils/brand.env"
  8. source_dot_config
  9. SEARX_URL="${PUBLIC_URL:-http://$(uname -n)/searx}"
  10. source "${REPO_ROOT}/utils/lxc-searx.env"
  11. in_container && lxc_set_suite_env
  12. # ----------------------------------------------------------------------------
  13. # config
  14. # ----------------------------------------------------------------------------
  15. MORTY_LISTEN="${MORTY_LISTEN:-127.0.0.1:3000}"
  16. PUBLIC_URL_PATH_MORTY="${PUBLIC_URL_PATH_MORTY:-/morty/}"
  17. PUBLIC_URL_MORTY="${PUBLIC_URL_MORTY:-$(echo "$SEARX_URL" | sed -e's,^\(.*://[^/]*\).*,\1,g')${PUBLIC_URL_PATH_MORTY}}"
  18. # shellcheck disable=SC2034
  19. MORTY_TIMEOUT=5
  20. SERVICE_NAME="morty"
  21. SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
  22. SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}"
  23. SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}"
  24. SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
  25. # shellcheck disable=SC2034
  26. SERVICE_GROUP="${SERVICE_USER}"
  27. # shellcheck disable=SC2034
  28. SERVICE_ENV_DEBUG=false
  29. GO_ENV="${SERVICE_HOME}/.go_env"
  30. GO_PKG_URL="https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
  31. GO_TAR=$(basename "$GO_PKG_URL")
  32. # shellcheck disable=SC2034
  33. CONFIG_FILES=()
  34. # Apache Settings
  35. APACHE_MORTY_SITE="morty.conf"
  36. NGINX_MORTY_SITE="morty.conf"
  37. # ----------------------------------------------------------------------------
  38. usage() {
  39. # ----------------------------------------------------------------------------
  40. # shellcheck disable=SC1117
  41. cat <<EOF
  42. usage::
  43. $(basename "$0") shell
  44. $(basename "$0") install [all|user]
  45. $(basename "$0") update [morty]
  46. $(basename "$0") remove [all]
  47. $(basename "$0") activate [service]
  48. $(basename "$0") deactivate [service]
  49. $(basename "$0") inspect [service]
  50. $(basename "$0") option [debug-on|debug-off]
  51. $(basename "$0") apache [install|remove]
  52. $(basename "$0") nginx [install|remove]
  53. $(basename "$0") info [searx]
  54. shell
  55. start interactive shell from user ${SERVICE_USER}
  56. install / remove
  57. all: complete setup of morty service
  58. user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME)
  59. update morty
  60. Update morty installation ($SERVICE_HOME)
  61. activate service
  62. activate and start service daemon (systemd unit)
  63. deactivate service
  64. stop and deactivate service daemon (systemd unit)
  65. inspect service
  66. show service status and log
  67. option
  68. set one of the available options
  69. apache : ${PUBLIC_URL_MORTY}
  70. :install: apache site with a reverse proxy (ProxyPass)
  71. :remove: apache site ${APACHE_MORTY_SITE}
  72. nginx (${PUBLIC_URL_MORTY})
  73. :install: nginx site with a reverse proxy (ProxyPass)
  74. :remove: nginx site ${NGINX_MORTY_SITE}
  75. If needed, set the environment variables in the '${DOT_CONFIG#"$REPO_ROOT/"}' file::
  76. PUBLIC_URL_MORTY: ${PUBLIC_URL_MORTY}
  77. MORTY_LISTEN: ${MORTY_LISTEN}
  78. SERVICE_USER: ${SERVICE_USER}
  79. EOF
  80. if in_container; then
  81. # in containers the service is listening on 0.0.0.0 (see lxc-searx.env)
  82. for ip in $(global_IPs) ; do
  83. if [[ $ip =~ .*:.* ]]; then
  84. echo " container URL (IPv6): http://[${ip#*|}]:3000/"
  85. else
  86. # IPv4:
  87. echo " container URL (IPv4): http://${ip#*|}:3000/"
  88. fi
  89. done
  90. fi
  91. echo
  92. info_searx
  93. [[ -n ${1} ]] && err_msg "$1"
  94. }
  95. info_searx() {
  96. # shellcheck disable=SC1117
  97. cat <<EOF
  98. To activate result and image proxy in searx, edit settings.yml (read:
  99. ${DOCS_URL}/admin/morty.html)::
  100. result_proxy:
  101. url : ${PUBLIC_URL_MORTY}
  102. server:
  103. image_proxy : True
  104. EOF
  105. }
  106. main() {
  107. required_commands \
  108. sudo install git wget curl \
  109. || exit
  110. local _usage="ERROR: unknown or missing $1 command $2"
  111. case $1 in
  112. --getenv) var="$2"; echo "${!var}"; exit 0;;
  113. -h|--help) usage; exit 0;;
  114. shell)
  115. sudo_or_exit
  116. interactive_shell "${SERVICE_USER}"
  117. ;;
  118. inspect)
  119. case $2 in
  120. service)
  121. sudo_or_exit
  122. inspect_service
  123. ;;
  124. *) usage "$_usage"; exit 42;;
  125. esac ;;
  126. install)
  127. rst_title "$SERVICE_NAME" part
  128. sudo_or_exit
  129. case $2 in
  130. all) install_all ;;
  131. user) assert_user ;;
  132. *) usage "$_usage"; exit 42;;
  133. esac ;;
  134. update)
  135. sudo_or_exit
  136. case $2 in
  137. morty) update_morty ;;
  138. *) usage "$_usage"; exit 42;;
  139. esac ;;
  140. remove)
  141. sudo_or_exit
  142. case $2 in
  143. all) remove_all;;
  144. user) drop_service_account "${SERVICE_USER}" ;;
  145. *) usage "$_usage"; exit 42;;
  146. esac ;;
  147. activate)
  148. sudo_or_exit
  149. case $2 in
  150. service) systemd_activate_service "${SERVICE_NAME}" ;;
  151. *) usage "$_usage"; exit 42;;
  152. esac ;;
  153. deactivate)
  154. sudo_or_exit
  155. case $2 in
  156. service) systemd_deactivate_service "${SERVICE_NAME}" ;;
  157. *) usage "$_usage"; exit 42;;
  158. esac ;;
  159. apache)
  160. sudo_or_exit
  161. case $2 in
  162. install) install_apache_site ;;
  163. remove) remove_apache_site ;;
  164. *) usage "$_usage"; exit 42;;
  165. esac ;;
  166. nginx)
  167. sudo_or_exit
  168. case $2 in
  169. install) install_nginx_site ;;
  170. remove) remove_nginx_site ;;
  171. *) usage "$_usage"; exit 42;;
  172. esac ;;
  173. info)
  174. case $2 in
  175. searx) info_searx ;;
  176. *) usage "$_usage"; exit 42;;
  177. esac ;;
  178. option)
  179. sudo_or_exit
  180. case $2 in
  181. debug-on) enable_debug ;;
  182. debug-off) disable_debug ;;
  183. *) usage "$_usage"; exit 42;;
  184. esac ;;
  185. doc) rst-doc ;;
  186. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  187. esac
  188. }
  189. install_all() {
  190. rst_title "Install $SERVICE_NAME (service)"
  191. assert_user
  192. wait_key
  193. install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}"
  194. wait_key
  195. install_morty
  196. wait_key
  197. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  198. wait_key
  199. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  200. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  201. fi
  202. if apache_is_installed; then
  203. info_msg "Apache is installed on this host."
  204. if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then
  205. install_apache_site
  206. fi
  207. elif nginx_is_installed; then
  208. info_msg "nginx is installed on this host."
  209. if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then
  210. install_nginx_site
  211. fi
  212. fi
  213. info_searx
  214. if ask_yn "Add image and result proxy to searx settings.yml?" Yn; then
  215. "${REPO_ROOT}/utils/searx.sh" option result-proxy "${PUBLIC_URL_MORTY}"
  216. "${REPO_ROOT}/utils/searx.sh" option image-proxy-on
  217. fi
  218. if ask_yn "Do you want to inspect the installation?" Ny; then
  219. inspect_service
  220. fi
  221. }
  222. remove_all() {
  223. rst_title "De-Install $SERVICE_NAME (service)"
  224. rst_para "\
  225. It goes without saying that this script can only be used to remove
  226. installations that were installed with this script."
  227. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  228. drop_service_account "${SERVICE_USER}"
  229. fi
  230. }
  231. assert_user() {
  232. rst_title "user $SERVICE_USER" section
  233. echo
  234. tee_stderr 1 <<EOF | bash | prefix_stdout
  235. useradd --shell /bin/bash --system \
  236. --home-dir "$SERVICE_HOME" \
  237. --comment 'Web content sanitizer proxy' $SERVICE_USER
  238. mkdir "$SERVICE_HOME"
  239. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  240. groups $SERVICE_USER
  241. EOF
  242. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  243. export SERVICE_HOME
  244. echo "export SERVICE_HOME=$SERVICE_HOME"
  245. cat > "$GO_ENV" <<EOF
  246. export GOPATH=\$HOME/go-apps
  247. export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin
  248. EOF
  249. echo "Environment $GO_ENV has been setup."
  250. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER"
  251. grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile
  252. EOF
  253. }
  254. morty_is_installed() {
  255. [[ -f $SERVICE_HOME/go-apps/bin/morty ]]
  256. }
  257. _svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} "
  258. install_morty() {
  259. rst_title "Install morty in user's ~/go-apps" section
  260. echo
  261. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  262. go get -v -u github.com/asciimoo/morty
  263. EOF
  264. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  265. cd \$GOPATH/src/github.com/asciimoo/morty
  266. go test
  267. go test -benchmem -bench .
  268. EOF
  269. }
  270. update_morty() {
  271. rst_title "Update morty" section
  272. echo
  273. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  274. go get -v -u github.com/asciimoo/morty
  275. EOF
  276. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  277. cd \$GOPATH/src/github.com/asciimoo/morty
  278. go test
  279. go test -benchmem -bench .
  280. EOF
  281. }
  282. set_service_env_debug() {
  283. # usage: set_service_env_debug [false|true]
  284. # shellcheck disable=SC2034
  285. local SERVICE_ENV_DEBUG="${1:-false}"
  286. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  287. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  288. fi
  289. }
  290. inspect_service() {
  291. rst_title "service status & log"
  292. cat <<EOF
  293. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  294. MORTY_LISTEN : ${MORTY_LISTEN}
  295. EOF
  296. if service_account_is_available "$SERVICE_USER"; then
  297. info_msg "service account $SERVICE_USER available."
  298. else
  299. err_msg "service account $SERVICE_USER not available!"
  300. fi
  301. if go_is_available "$SERVICE_USER"; then
  302. info_msg "~$SERVICE_USER: go is installed"
  303. else
  304. err_msg "~$SERVICE_USER: go is not installed"
  305. fi
  306. if morty_is_installed; then
  307. info_msg "~$SERVICE_USER: morty app is installed"
  308. else
  309. err_msg "~$SERVICE_USER: morty app is not installed!"
  310. fi
  311. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  312. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  313. echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .."
  314. wait_key
  315. fi
  316. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  317. warn_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  318. if ! in_container; then
  319. warn_msg "Check if public name is correct and routed or use the public IP from above."
  320. fi
  321. fi
  322. if in_container; then
  323. lxc_suite_info
  324. else
  325. info_msg "public URL --> ${PUBLIC_URL_MORTY}"
  326. info_msg "morty URL --> http://${MORTY_LISTEN}"
  327. fi
  328. local _debug_on
  329. if ask_yn "Enable morty debug mode (needs reinstall of systemd service)?"; then
  330. enable_debug
  331. _debug_on=1
  332. else
  333. systemctl --no-pager -l status "${SERVICE_NAME}"
  334. fi
  335. echo
  336. # shellcheck disable=SC2059
  337. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  338. read -r -s -n1 -t 5
  339. echo
  340. while true; do
  341. trap break 2
  342. journalctl -f -u "${SERVICE_NAME}"
  343. done
  344. if [[ $_debug_on == 1 ]]; then
  345. FORCE_SELECTION=Y disable_debug
  346. fi
  347. return 0
  348. }
  349. enable_debug() {
  350. warn_msg "Do not enable debug in production enviroments!!"
  351. info_msg "Enabling debug option needs to reinstall systemd service!"
  352. set_service_env_debug true
  353. }
  354. disable_debug() {
  355. info_msg "Disabling debug option needs to reinstall systemd service!"
  356. set_service_env_debug false
  357. }
  358. install_apache_site() {
  359. rst_title "Install Apache site $APACHE_MORTY_SITE"
  360. rst_para "\
  361. This installs a reverse proxy (ProxyPass) into apache site (${APACHE_MORTY_SITE})"
  362. ! apache_is_installed && err_msg "Apache is not installed."
  363. if ! ask_yn "Do you really want to continue?" Yn; then
  364. return
  365. else
  366. install_apache
  367. fi
  368. apache_install_site "${APACHE_MORTY_SITE}"
  369. info_msg "testing public url .."
  370. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  371. err_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  372. fi
  373. }
  374. remove_apache_site() {
  375. rst_title "Remove Apache site $APACHE_MORTY_SITE"
  376. rst_para "\
  377. This removes apache site ${APACHE_MORTY_SITE}."
  378. ! apache_is_installed && err_msg "Apache is not installed."
  379. if ! ask_yn "Do you really want to continue?" Yn; then
  380. return
  381. fi
  382. apache_remove_site "$APACHE_MORTY_SITE"
  383. }
  384. install_nginx_site() {
  385. rst_title "Install nginx site $NGINX_MORTY_SITE"
  386. rst_para "\
  387. This installs a reverse proxy (ProxyPass) into nginx site (${NGINX_MORTY_SITE})"
  388. ! nginx_is_installed && err_msg "nginx is not installed."
  389. if ! ask_yn "Do you really want to continue?" Yn; then
  390. return
  391. else
  392. install_nginx
  393. fi
  394. "${REPO_ROOT}/utils/searx.sh" install uwsgi
  395. # shellcheck disable=SC2034
  396. SEARX_SRC=$("${REPO_ROOT}/utils/searx.sh" --getenv SEARX_SRC)
  397. # shellcheck disable=SC2034
  398. SEARX_URL_PATH=$("${REPO_ROOT}/utils/searx.sh" --getenv SEARX_URL_PATH)
  399. nginx_install_app "${NGINX_MORTY_SITE}"
  400. info_msg "testing public url .."
  401. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  402. err_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  403. fi
  404. }
  405. remove_nginx_site() {
  406. rst_title "Remove nginx site $NGINX_MORTY_SITE"
  407. rst_para "\
  408. This removes nginx site ${NGINX_MORTY_SITE}."
  409. ! nginx_is_installed && err_msg "nginx is not installed."
  410. if ! ask_yn "Do you really want to continue?" Yn; then
  411. return
  412. fi
  413. nginx_remove_site "$NGINX_MORTY_SITE"
  414. }
  415. rst-doc() {
  416. eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/morty.rst")\""
  417. echo -e "\n.. START install systemd unit"
  418. cat <<EOF
  419. .. tabs::
  420. .. group-tab:: systemd
  421. .. code:: bash
  422. EOF
  423. eval "echo \"$(< "${TEMPLATES}/${SERVICE_SYSTEMD_UNIT}")\"" | prefix_stdout " "
  424. echo -e "\n.. END install systemd unit"
  425. # for DIST_NAME in ubuntu-20.04 arch fedora; do
  426. # (
  427. # DIST_ID=${DIST_NAME%-*}
  428. # DIST_VERS=${DIST_NAME#*-}
  429. # [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=
  430. # # ...
  431. # )
  432. # done
  433. }
  434. # ----------------------------------------------------------------------------
  435. main "$@"
  436. # ----------------------------------------------------------------------------