morty.sh 12 KB

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