morty.sh 14 KB

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