morty.sh 11 KB

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