morty.sh 11 KB

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