View raw

1 #!/usr/bin/env bash 2 3 set -eEuo pipefail 4 5 readonly REPO_DIR="/opt/fapg/fapg-daq" 6 readonly DASHBOARD_SCRIPT="${REPO_DIR}/roles/dashboard/script/dashboard" 7 readonly WEATHER_SCRIPT="${REPO_DIR}/roles/dashboard/script/fetch-weather" 8 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 9 readonly SCRIPT_DIR 10 11 readonly SERVICE_NAME="fapg-daq-dashboard.service" 12 readonly WEATHER_SERVICE_NAME="fapg-daq-dashboard-weather.service" 13 readonly WEATHER_TIMER_NAME="fapg-daq-dashboard-weather.timer" 14 readonly SERVICE_SOURCE="${SCRIPT_DIR}/etc/systemd/system/${SERVICE_NAME}" 15 readonly WEATHER_SERVICE_SOURCE="${SCRIPT_DIR}/etc/systemd/system/${WEATHER_SERVICE_NAME}" 16 readonly WEATHER_TIMER_SOURCE="${SCRIPT_DIR}/etc/systemd/system/${WEATHER_TIMER_NAME}" 17 readonly SYSTEMD_DIR="/etc/systemd/system" 18 readonly NGINX_GZIP_SOURCE="${SCRIPT_DIR}/etc/nginx/conf.d/fapg-daq-dashboard-gzip.conf" 19 readonly NGINX_GZIP_FILE="/etc/nginx/conf.d/fapg-daq-dashboard-gzip.conf" 20 21 readonly STATE_DIR="/var/lib/fapg-daq" 22 readonly SECRET_FILE="${STATE_DIR}/dashboard.secret" 23 readonly LEGACY_SECRET_FILE="${REPO_DIR}/roles/dashboard/.mojo-secrets" 24 readonly RUN_USER="fapg-daq" 25 readonly RUN_GROUP="fapg-daq" 26 27 function die() { 28 echo "ERROR: $*" >&2 29 exit 1 30 } 31 32 function require_root() { 33 if [[ "$(id -u)" -ne 0 ]]; then 34 die "$0 requires superuser privileges." 35 fi 36 } 37 38 function install_os_dependencies() { 39 apt-get update 40 apt-get install -y \ 41 perl \ 42 nginx \ 43 libdbd-sqlite3-perl \ 44 libexcel-writer-xlsx-perl \ 45 libmojolicious-perl \ 46 libmojo-sqlite-perl 47 } 48 49 function create_runtime_user() { 50 if ! getent group "${RUN_GROUP}" > /dev/null; then 51 addgroup --system "${RUN_GROUP}" 52 fi 53 54 if ! id "${RUN_USER}" > /dev/null 2>&1; then 55 adduser \ 56 --system \ 57 --ingroup "${RUN_GROUP}" \ 58 --home "${STATE_DIR}" \ 59 --no-create-home \ 60 --disabled-login \ 61 "${RUN_USER}" 62 fi 63 64 mkdir -p "${STATE_DIR}" 65 chown "${RUN_USER}:${RUN_GROUP}" "${STATE_DIR}" 66 } 67 68 function migrate_application_secret() { 69 if [[ ! -e "${SECRET_FILE}" && -f "${LEGACY_SECRET_FILE}" ]]; then 70 install -m 0600 -o "${RUN_USER}" -g "${RUN_GROUP}" \ 71 "${LEGACY_SECRET_FILE}" \ 72 "${SECRET_FILE}" 73 fi 74 } 75 76 function check_repo_layout() { 77 [[ -d "${REPO_DIR}" ]] || die "Repo not found at ${REPO_DIR}." 78 [[ -f "${DASHBOARD_SCRIPT}" ]] || die "${DASHBOARD_SCRIPT} does not exist." 79 [[ -x "${WEATHER_SCRIPT}" ]] || die "${WEATHER_SCRIPT} is not executable." 80 [[ -f "${SERVICE_SOURCE}" ]] || die "${SERVICE_SOURCE} does not exist." 81 [[ -f "${WEATHER_SERVICE_SOURCE}" ]] || die "${WEATHER_SERVICE_SOURCE} does not exist." 82 [[ -f "${WEATHER_TIMER_SOURCE}" ]] || die "${WEATHER_TIMER_SOURCE} does not exist." 83 [[ -f "${NGINX_GZIP_SOURCE}" ]] || die "${NGINX_GZIP_SOURCE} does not exist." 84 } 85 86 function write_systemd_services() { 87 install -m 0644 -o root -g root \ 88 "${SERVICE_SOURCE}" \ 89 "${WEATHER_SERVICE_SOURCE}" \ 90 "${WEATHER_TIMER_SOURCE}" \ 91 "${SYSTEMD_DIR}/" 92 } 93 94 function configure_nginx_compression() { 95 install -m 0644 -o root -g root \ 96 "${NGINX_GZIP_SOURCE}" \ 97 "${NGINX_GZIP_FILE}" 98 99 sudo nginx -t 100 systemctl enable --now nginx 101 systemctl reload nginx 102 } 103 104 function enable_services() { 105 systemctl daemon-reload 106 systemctl enable "${SERVICE_NAME}" 107 systemctl enable --now "${WEATHER_TIMER_NAME}" 108 systemctl restart "${SERVICE_NAME}" 109 } 110 111 function show_status() { 112 cat <<"EOF" 113 Deployment complete. 114 Current service state: 115 EOF 116 systemctl --no-pager --full status \ 117 "${SERVICE_NAME}" \ 118 "${WEATHER_TIMER_NAME}" 119 } 120 121 function main() { 122 require_root 123 install_os_dependencies 124 create_runtime_user 125 check_repo_layout 126 migrate_application_secret 127 write_systemd_services 128 configure_nginx_compression 129 enable_services 130 show_status 131 } 132 133 main "$@" 134