Files
AriWeb-Suite/modules/arimail/deploy/lib.sh
T

55 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# setup.sh / deploy.sh / tls-when-ready.sh 가 공유하는 함수(0.8.18~). 직접 실행하지 않고 source 합니다.
#
# load_site <파일> : 사이트 설정(deploy/sites/<이름>.env 또는 $APP_DIR/site.env)을 읽고 필수 값을 확인합니다.
# render <템플릿> <출력> : 템플릿의 @변수@ 자리를 사이트 설정 값으로 바꿔 씁니다(systemd·nginx·certbot 훅·환경 파일).
#
# 예전(0.8.17 까지)에는 모든 파일에 mail.arihakdang.com / arihakdang 계정 / /srv/arihakdang-mail 이 박혀 있어 다른 도메인에 설치할 수 없었습니다.
# 이제 사이트마다 변수 파일 하나로 서비스 이름·계정·경로·호스트·메일함을 정하고, 같은 템플릿으로 설정 파일을 만듭니다.
DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# 템플릿이 치환하는 변수 목록. 새 변수를 쓰려면 여기와 sites/*.env 에 함께 더합니다.
# 0.9.0: LOGIN_MODE(설치 옵션: standalone | www)와 시스템 제한 LIMIT_*(0 = 제한 없음, 크기는 500M/2G 같은 접미사 가능)을 더했습니다.
SITE_VARS=(SITE APP_NAME APP_USER APP_DIR ETC_DIR NODE_BIN PORT MAIL_HOST MAILBOX MAIL_FROM_NAME SITE_TITLE SITE_BRAND WWW_DB_FILE WEBMAKER_DIR WEBMAKER_USER WEBMAKER_SITE EXTRA_RW ACME_WEBROOT CF_CERT CF_KEY REPO_URL LOGIN_MODE LIMIT_ACCOUNTS LIMIT_TOTAL_BYTES LIMIT_MAILBOX_BYTES LIMIT_ATTACHMENT_BYTES LIMIT_RECIPIENTS LIMIT_MONTHLY_MESSAGES LIMIT_LARGE_FILE_BYTES LIMIT_LARGE_FILE_DAYS LIMIT_LARGE_FILE_DOWNLOADS)
load_site() {
local file="$1"
[ -f "$file" ] || { echo "사이트 설정 파일이 없습니다: $file" >&2; return 1; }
# shellcheck disable=SC1090
set -a; . "$file"; set +a
for v in SITE APP_NAME APP_USER APP_DIR ETC_DIR NODE_BIN PORT MAIL_HOST MAILBOX; do
[ -n "${!v:-}" ] || { echo "사이트 설정에 $v 가 없습니다: $file" >&2; return 1; }
done
: "${MAIL_FROM_NAME:=$SITE}" "${SITE_TITLE:=}" "${SITE_BRAND:=}" "${WWW_DB_FILE:=}" "${WEBMAKER_DIR:=}" "${WEBMAKER_USER:=}" "${WEBMAKER_SITE:=}" "${EXTRA_RW:=}" "${ACME_WEBROOT:=/var/www/letsencrypt}" "${CF_CERT:=}" "${CF_KEY:=}" "${REPO_URL:=https://source.ibit.kr/OZ-Group/AriMail.git}"
: "${LIMIT_ACCOUNTS:=0}" "${LIMIT_TOTAL_BYTES:=0}" "${LIMIT_MAILBOX_BYTES:=0}" "${LIMIT_ATTACHMENT_BYTES:=0}" "${LIMIT_RECIPIENTS:=0}" "${LIMIT_MONTHLY_MESSAGES:=0}"
# 대용량 첨부파일 시스템 상한(0.9.3): 무제한이 없으므로 기본값(1G / 30일 / 20회)을 둡니다.
: "${LIMIT_LARGE_FILE_BYTES:=1G}" "${LIMIT_LARGE_FILE_DAYS:=30}" "${LIMIT_LARGE_FILE_DOWNLOADS:=20}"
# 로그인 방식(0.9.0 설치 옵션). 비워 두면 WWW_DB_FILE 유무로 정합니다(0.8.x 사이트 파일 호환). standalone 이 기본 설치 형태입니다.
# standalone : www 사이트 없이 게이트웨이 계정만 씀(WWW_DB_FILE 은 비움) www : www 사이트 DB 로 관리자를 인증(WWW_DB_FILE 필수)
: "${LOGIN_MODE:=}"
if [ -z "$LOGIN_MODE" ]; then if [ -n "$WWW_DB_FILE" ]; then LOGIN_MODE=www; else LOGIN_MODE=standalone; fi; fi
# webmaker(1.0.8): 웹메이커 데이터 디렉터리(WEBMAKER_DIR)로 계정을 연동. WEBMAKER_USER(sudo 로 읽을 계정)·WEBMAKER_SITE(사이트 id)는 선택.
case "$LOGIN_MODE" in
standalone) WWW_DB_FILE=""; WEBMAKER_DIR="" ;;
www) WEBMAKER_DIR=""; [ -n "$WWW_DB_FILE" ] || { echo "LOGIN_MODE=www 이면 WWW_DB_FILE(www 사이트 DB 경로)이 필요합니다: $file" >&2; return 1; } ;;
webmaker) WWW_DB_FILE=""; [ -n "$WEBMAKER_DIR" ] || { echo "LOGIN_MODE=webmaker 이면 WEBMAKER_DIR(웹메이커 데이터 디렉터리)이 필요합니다: $file" >&2; return 1; } ;;
*) echo "LOGIN_MODE 는 standalone, www, webmaker 중 하나여야 합니다: $LOGIN_MODE ($file)" >&2; return 1 ;;
esac
export MAIL_FROM_NAME SITE_TITLE SITE_BRAND WWW_DB_FILE WEBMAKER_DIR WEBMAKER_USER WEBMAKER_SITE EXTRA_RW ACME_WEBROOT CF_CERT CF_KEY REPO_URL LOGIN_MODE LIMIT_ACCOUNTS LIMIT_TOTAL_BYTES LIMIT_MAILBOX_BYTES LIMIT_ATTACHMENT_BYTES LIMIT_RECIPIENTS LIMIT_MONTHLY_MESSAGES LIMIT_LARGE_FILE_BYTES LIMIT_LARGE_FILE_DAYS LIMIT_LARGE_FILE_DOWNLOADS
}
# sed 치환에서 특별한 뜻을 갖는 글자(구분자 | 와 &, \)를 피합니다.
_sed_escape() { local s="$1"; s="${s//\\/\\\\}"; s="${s//|/\\|}"; s="${s//&/\\&}"; printf '%s' "$s"; }
render() {
local template="$1" out="$2" expr=()
for v in "${SITE_VARS[@]}"; do expr+=(-e "s|@${v}@|$(_sed_escape "${!v:-}")|g"); done
sed "${expr[@]}" "$template" > "$out"
# 치환되지 않은 자리가 남으면 템플릿과 변수 목록이 어긋난 것이므로 바로 알립니다.
if grep -q '@[A-Z_]\{3,\}@' "$out"; then echo "템플릿에 알 수 없는 변수가 있습니다: $template → $(grep -o '@[A-Z_]\{3,\}@' "$out" | sort -u | tr '\n' ' ')" >&2; return 1; fi
}
# 실행 계정이 서비스를 재시작하고 nginx 를 다시 읽을 수 있게 하는 sudoers 규칙 한 줄.
# 1.0.0: 내장 Haraka 관리 서비스(<APP_NAME>-haraka)의 재시작도 허용합니다(deploy.sh 가 새 릴리스로 다시 띄움).
sudoers_line() { printf '%s ALL=(root) NOPASSWD: /usr/bin/systemctl restart %s, /usr/bin/systemctl restart %s-haraka, /usr/bin/systemctl reload nginx\n' "$APP_USER" "$APP_NAME" "$APP_NAME"; }