morty.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. source_dot_config
  7. # ----------------------------------------------------------------------------
  8. # config
  9. # ----------------------------------------------------------------------------
  10. PUBLIC_URL_PATH_MORTY="/morty"
  11. PUBLIC_URL_MORTY="$(dirname "${PUBLIC_URL}")${PUBLIC_URL_PATH_MORTY}"
  12. MORTY_LISTEN="${MORTY_LISTEN:-127.0.0.1:3000}"
  13. # shellcheck disable=SC2034
  14. MORTY_TIMEOUT=5
  15. SERVICE_NAME="morty"
  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. SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
  20. # shellcheck disable=SC2034
  21. SERVICE_GROUP="${SERVICE_USER}"
  22. # shellcheck disable=SC2034
  23. SERVICE_ENV_DEBUG=false
  24. GO_ENV="${SERVICE_HOME}/.go_env"
  25. GO_PKG_URL="https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
  26. GO_TAR=$(basename "$GO_PKG_URL")
  27. # shellcheck disable=SC2034
  28. CONFIG_FILES=()
  29. # Apache Settings
  30. APACHE_MORTY_SITE="morty.conf"
  31. # ----------------------------------------------------------------------------
  32. usage() {
  33. # ----------------------------------------------------------------------------
  34. # shellcheck disable=SC1117
  35. cat <<EOF
  36. usage::
  37. $(basename "$0") shell
  38. $(basename "$0") install [all|user]
  39. $(basename "$0") update [morty]
  40. $(basename "$0") remove [all]
  41. $(basename "$0") activate [service]
  42. $(basename "$0") deactivate [service]
  43. $(basename "$0") inspect [service]
  44. $(basename "$0") option [debug-on|debug-off]
  45. $(basename "$0") apache [install|remove]
  46. $(basename "$0") info [searx]
  47. shell
  48. start interactive shell from user ${SERVICE_USER}
  49. install / remove
  50. all: complete setup of morty service
  51. user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME)
  52. update morty
  53. Update morty installation ($SERVICE_HOME)
  54. activate service
  55. activate and start service daemon (systemd unit)
  56. deactivate service
  57. stop and deactivate service daemon (systemd unit)
  58. inspect service
  59. show service status and log
  60. option
  61. set one of the available options
  62. apache : ${PUBLIC_URL_MORTY}
  63. :install: apache site with a reverse proxy (ProxyPass)
  64. :remove: apache site ${APACHE_MORTY_SITE}
  65. If needed, set the environment variable MORTY_LISTEN in the
  66. ${DOT_CONFIG#"$REPO_ROOT/"} file::
  67. MORTY_LISTEN : ${MORTY_LISTEN}
  68. SERVICE_USER : ${SERVICE_USER}
  69. EOF
  70. info_searx
  71. [[ -n ${1} ]] && err_msg "$1"
  72. }
  73. info_searx() {
  74. # shellcheck disable=SC1117
  75. cat <<EOF
  76. To activate morty in searx, add result_proxy to your settings.yml::
  77. result_proxy:
  78. url : ${PUBLIC_URL_MORTY}/
  79. further read: ${DOCS_URL}/admin/morty.html
  80. EOF
  81. }
  82. main() {
  83. rst_title "$SERVICE_NAME" part
  84. required_commands \
  85. sudo install git wget curl \
  86. || exit
  87. local _usage="ERROR: unknown or missing $1 command $2"
  88. case $1 in
  89. --source-only) ;;
  90. -h|--help) usage; exit 0;;
  91. shell)
  92. sudo_or_exit
  93. interactive_shell "${SERVICE_USER}"
  94. ;;
  95. inspect)
  96. case $2 in
  97. service)
  98. sudo_or_exit
  99. inspect_service
  100. ;;
  101. *) usage "$_usage"; exit 42;;
  102. esac ;;
  103. install)
  104. sudo_or_exit
  105. case $2 in
  106. all) install_all ;;
  107. user) assert_user ;;
  108. *) usage "$_usage"; exit 42;;
  109. esac ;;
  110. update)
  111. sudo_or_exit
  112. case $2 in
  113. morty) update_morty ;;
  114. *) usage "$_usage"; exit 42;;
  115. esac ;;
  116. remove)
  117. sudo_or_exit
  118. case $2 in
  119. all) remove_all;;
  120. user) drop_service_account "${SERVICE_USER}" ;;
  121. *) usage "$_usage"; exit 42;;
  122. esac ;;
  123. activate)
  124. sudo_or_exit
  125. case $2 in
  126. service) systemd_activate_service "${SERVICE_NAME}" ;;
  127. *) usage "$_usage"; exit 42;;
  128. esac ;;
  129. deactivate)
  130. sudo_or_exit
  131. case $2 in
  132. service) systemd_deactivate_service "${SERVICE_NAME}" ;;
  133. *) usage "$_usage"; exit 42;;
  134. esac ;;
  135. apache)
  136. sudo_or_exit
  137. case $2 in
  138. install) install_apache_site ;;
  139. remove) remove_apache_site ;;
  140. *) usage "$_usage"; exit 42;;
  141. esac ;;
  142. info)
  143. case $2 in
  144. searx) info_searx ;;
  145. *) usage "$_usage"; exit 42;;
  146. esac ;;
  147. option)
  148. sudo_or_exit
  149. case $2 in
  150. debug-on) enable_debug ;;
  151. debug-off) disable_debug ;;
  152. *) usage "$_usage"; exit 42;;
  153. esac ;;
  154. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  155. esac
  156. }
  157. install_all() {
  158. rst_title "Install $SERVICE_NAME (service)"
  159. assert_user
  160. wait_key
  161. install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}"
  162. wait_key
  163. install_morty
  164. wait_key
  165. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  166. wait_key
  167. info_searx
  168. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  169. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  170. fi
  171. if apache_is_installed; then
  172. info_msg "Apache is installed on this host."
  173. if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then
  174. install_apache_site
  175. fi
  176. fi
  177. if ask_yn "Do you want to inspect the installation?" Yn; then
  178. inspect_service
  179. fi
  180. }
  181. remove_all() {
  182. rst_title "De-Install $SERVICE_NAME (service)"
  183. rst_para "\
  184. It goes without saying that this script can only be used to remove
  185. installations that were installed with this script."
  186. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  187. drop_service_account "${SERVICE_USER}"
  188. fi
  189. }
  190. assert_user() {
  191. rst_title "user $SERVICE_USER" section
  192. echo
  193. tee_stderr 1 <<EOF | bash | prefix_stdout
  194. useradd --shell /bin/bash --system \
  195. --home-dir "$SERVICE_HOME" \
  196. --comment 'Web content sanitizer proxy' $SERVICE_USER
  197. mkdir "$SERVICE_HOME"
  198. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  199. groups $SERVICE_USER
  200. EOF
  201. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  202. export SERVICE_HOME
  203. echo "export SERVICE_HOME=$SERVICE_HOME"
  204. cat > "$GO_ENV" <<EOF
  205. export GOPATH=\$HOME/go-apps
  206. export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin
  207. EOF
  208. echo "Environment $GO_ENV has been setup."
  209. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER"
  210. grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile
  211. EOF
  212. }
  213. morty_is_installed() {
  214. [[ -f $SERVICE_HOME/go-apps/bin/morty ]]
  215. }
  216. _svcpr=" |${SERVICE_USER}| "
  217. install_morty() {
  218. rst_title "Install morty in user's ~/go-apps" section
  219. echo
  220. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  221. go get -v -u github.com/asciimoo/morty
  222. EOF
  223. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  224. cd \$GOPATH/src/github.com/asciimoo/morty
  225. go test
  226. go test -benchmem -bench .
  227. EOF
  228. }
  229. update_morty() {
  230. rst_title "Update morty" section
  231. echo
  232. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  233. go get -v -u github.com/asciimoo/morty
  234. EOF
  235. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  236. cd \$GOPATH/src/github.com/asciimoo/morty
  237. go test
  238. go test -benchmem -bench .
  239. EOF
  240. }
  241. set_service_env_debug() {
  242. # usage: set_service_env_debug [false|true]
  243. # shellcheck disable=SC2034
  244. local SERVICE_ENV_DEBUG="${1:-false}"
  245. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  246. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  247. fi
  248. }
  249. inspect_service() {
  250. rst_title "service status & log"
  251. cat <<EOF
  252. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  253. MORTY_LISTEN : ${MORTY_LISTEN}
  254. EOF
  255. if service_account_is_available "$SERVICE_USER"; then
  256. info_msg "service account $SERVICE_USER available."
  257. else
  258. err_msg "service account $SERVICE_USER not available!"
  259. fi
  260. if go_is_available "$SERVICE_USER"; then
  261. info_msg "~$SERVICE_USER: go is installed"
  262. else
  263. err_msg "~$SERVICE_USER: go is not installed"
  264. fi
  265. if morty_is_installed; then
  266. info_msg "~$SERVICE_USER: morty app is installed"
  267. else
  268. err_msg "~$SERVICE_USER: morty app is not installed!"
  269. fi
  270. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  271. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  272. echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .."
  273. wait_key
  274. fi
  275. local _debug_on
  276. if ask_yn "Enable filtron debug mode?"; then
  277. enable_debug
  278. _debug_on=1
  279. fi
  280. echo
  281. systemctl --no-pager -l status "${SERVICE_NAME}"
  282. echo
  283. info_msg "morty URL --> http://${MORTY_LISTEN}"
  284. info_msg "public URL --> ${PUBLIC_URL_MORTY}"
  285. # shellcheck disable=SC2059
  286. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  287. read -r -s -n1 -t 2
  288. echo
  289. while true; do
  290. trap break 2
  291. journalctl -f -u "${SERVICE_NAME}"
  292. done
  293. if [[ $_debug_on == 1 ]]; then
  294. FORCE_SELECTION=Y disable_debug
  295. fi
  296. return 0
  297. }
  298. enable_debug() {
  299. warn_msg "Do not enable debug in production enviroments!!"
  300. info_msg "Enabling debug option needs to reinstall systemd service!"
  301. set_service_env_debug true
  302. }
  303. disable_debug() {
  304. info_msg "Disabling debug option needs to reinstall systemd service!"
  305. set_service_env_debug false
  306. }
  307. install_apache_site() {
  308. rst_title "Install Apache site $APACHE_MORTY_SITE"
  309. rst_para "\
  310. This installs a reverse proxy (ProxyPass) into apache site (${APACHE_MORTY_SITE})"
  311. ! apache_is_installed && err_msg "Apache is not installed."
  312. if ! ask_yn "Do you really want to continue?"; then
  313. return
  314. fi
  315. a2enmod headers
  316. a2enmod proxy
  317. a2enmod proxy_http
  318. echo
  319. apache_install_site "${APACHE_MORTY_SITE}"
  320. info_msg "testing public url .."
  321. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  322. err_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  323. fi
  324. }
  325. remove_apache_site() {
  326. rst_title "Remove Apache site $APACHE_MORTY_SITE"
  327. rst_para "\
  328. This removes apache site ${APACHE_MORTY_SITE}."
  329. ! apache_is_installed && err_msg "Apache is not installed."
  330. if ! ask_yn "Do you really want to continue?"; then
  331. return
  332. fi
  333. apache_remove_site "$APACHE_MORTY_SITE"
  334. }
  335. # ----------------------------------------------------------------------------
  336. main "$@"
  337. # ----------------------------------------------------------------------------