morty.sh 10 KB

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