morty.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. [ ! -z ${1+x} ] && 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. dpkg apt-get 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 ask_yn "Do you want to inspect the installation?" Yn; then
  172. inspect_service
  173. fi
  174. }
  175. remove_all() {
  176. rst_title "De-Install $SERVICE_NAME (service)"
  177. rst_para "\
  178. It goes without saying that this script can only be used to remove
  179. installations that were installed with this script."
  180. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  181. drop_service_account "${SERVICE_USER}"
  182. fi
  183. }
  184. assert_user() {
  185. rst_title "user $SERVICE_USER" section
  186. echo
  187. tee_stderr 1 <<EOF | bash | prefix_stdout
  188. sudo -H adduser --shell /bin/bash --system --home $SERVICE_HOME \
  189. --disabled-password --group --gecos 'Morty' $SERVICE_USER
  190. sudo -H usermod -a -G shadow $SERVICE_USER
  191. groups $SERVICE_USER
  192. EOF
  193. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  194. export SERVICE_HOME
  195. echo "export SERVICE_HOME=$SERVICE_HOME"
  196. cat > "$GO_ENV" <<EOF
  197. export GOPATH=\$HOME/go-apps
  198. export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin
  199. EOF
  200. echo "Environment $GO_ENV has been setup."
  201. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER"
  202. grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile
  203. EOF
  204. }
  205. morty_is_installed() {
  206. [[ -f $SERVICE_HOME/go-apps/bin/morty ]]
  207. }
  208. _svcpr=" |${SERVICE_USER}| "
  209. install_morty() {
  210. rst_title "Install morty in user's ~/go-apps" section
  211. echo
  212. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  213. go get -v -u github.com/asciimoo/morty
  214. EOF
  215. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  216. cd \$GOPATH/src/github.com/asciimoo/morty
  217. go test
  218. go test -benchmem -bench .
  219. EOF
  220. }
  221. update_morty() {
  222. rst_title "Update morty" section
  223. echo
  224. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  225. go get -v -u github.com/asciimoo/morty
  226. EOF
  227. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  228. cd \$GOPATH/src/github.com/asciimoo/morty
  229. go test
  230. go test -benchmem -bench .
  231. EOF
  232. }
  233. set_service_env_debug() {
  234. # usage: set_service_env_debug [false|true]
  235. # shellcheck disable=SC2034
  236. local SERVICE_ENV_DEBUG="${1:-false}"
  237. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  238. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  239. fi
  240. }
  241. inspect_service() {
  242. rst_title "service status & log"
  243. cat <<EOF
  244. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  245. MORTY_LISTEN : ${MORTY_LISTEN}
  246. EOF
  247. if service_account_is_available "$SERVICE_USER"; then
  248. info_msg "service account $SERVICE_USER available."
  249. else
  250. err_msg "service account $SERVICE_USER not available!"
  251. fi
  252. if go_is_available "$SERVICE_USER"; then
  253. info_msg "~$SERVICE_USER: go is installed"
  254. else
  255. err_msg "~$SERVICE_USER: go is not installed"
  256. fi
  257. if morty_is_installed; then
  258. info_msg "~$SERVICE_USER: morty app is installed"
  259. else
  260. err_msg "~$SERVICE_USER: morty app is not installed!"
  261. fi
  262. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  263. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  264. echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .."
  265. wait_key
  266. fi
  267. local _debug_on
  268. if ask_yn "Enable filtron debug mode?"; then
  269. enable_debug
  270. _debug_on=1
  271. fi
  272. echo
  273. systemctl --no-pager -l status "${SERVICE_NAME}"
  274. echo
  275. info_msg "morty URL --> http://${MORTY_LISTEN}"
  276. info_msg "public URL --> ${PUBLIC_URL_MORTY}"
  277. # shellcheck disable=SC2059
  278. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  279. read -r -s -n1 -t 2
  280. echo
  281. while true; do
  282. trap break 2
  283. journalctl -f -u "${SERVICE_NAME}"
  284. done
  285. if [[ $_debug_on == 1 ]]; then
  286. FORCE_SELECTION=Y disable_debug
  287. fi
  288. return 0
  289. }
  290. enable_debug() {
  291. warn_msg "Do not enable debug in production enviroments!!"
  292. info_msg "Enabling debug option needs to reinstall systemd service!"
  293. set_service_env_debug true
  294. }
  295. disable_debug() {
  296. info_msg "Disabling debug option needs to reinstall systemd service!"
  297. set_service_env_debug false
  298. }
  299. install_apache_site() {
  300. rst_title "Install Apache site $APACHE_MORTY_SITE"
  301. rst_para "\
  302. This installs a reverse proxy (ProxyPass) into apache site (${APACHE_MORTY_SITE})"
  303. ! apache_is_installed && err_msg "Apache is not installed."
  304. if ! ask_yn "Do you really want to continue?"; then
  305. return
  306. fi
  307. a2enmod headers
  308. a2enmod proxy
  309. a2enmod proxy_http
  310. echo
  311. apache_install_site "${APACHE_MORTY_SITE}"
  312. info_msg "testing public url .."
  313. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  314. err_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  315. fi
  316. }
  317. remove_apache_site() {
  318. rst_title "Remove Apache site $APACHE_MORTY_SITE"
  319. rst_para "\
  320. This removes apache site ${APACHE_MORTY_SITE}."
  321. ! apache_is_installed && err_msg "Apache is not installed."
  322. if ! ask_yn "Do you really want to continue?"; then
  323. return
  324. fi
  325. apache_remove_site "$APACHE_MORTY_SITE"
  326. }
  327. # ----------------------------------------------------------------------------
  328. main "$@"
  329. # ----------------------------------------------------------------------------