#!/usr/bin/env bash # 내장 Haraka 준비(1.0.0) — root 로 실행: sudo bash /repo/deploy/haraka-apply.sh [site.env 경로] # # 하는 일(환경 파일·데이터는 건드리지 않습니다) # 1) /haraka 디렉터리(실행 계정 소유)에 haraka/package.json 을 두고 npm 으로 Haraka 와 DKIM 플러그인을 설치합니다(인터넷 필요, 몇 분). # 2) systemd 서비스 -haraka 를 등록·시작합니다. 이 서비스(haraka/run.mjs)는 설정 파일(config.json)의 수·발신 방식이 haraka 일 때만 # Haraka 를 띄우므로, 지금 Resend 만 쓰고 있어도 켜 두어도 아무 포트를 열지 않습니다(설정 화면에서 바꾸는 순간 동작). # setup.sh 가 새 사이트에 자동으로 부르고, 기존 사이트는 한 번 직접 실행합니다. 다시 실행해도 안전합니다(설치된 버전이 같으면 npm 이 금방 끝남). set -euo pipefail [ "$(id -u)" = 0 ] || { echo 'sudo 로 실행하세요' >&2; exit 1; } . "$(dirname "$0")/lib.sh" SITE_FILE="${1:-}" # 사이트 파일: 인자 → /site.env(0.8.18 이후 setup.sh 가 둠) → deploy/sites/.env(0.8.17 이전에 설치한 서버는 site.env 사본이 없음, deploy.sh 와 같은 폴백). if [ -n "$SITE_FILE" ] && [ ! -f "$SITE_FILE" ]; then echo "사이트 설정 파일이 없어 저장소의 기본 파일을 씁니다: $SITE_FILE" >&2; SITE_FILE=""; fi if [ -z "$SITE_FILE" ]; then APP_GUESS="$(cd "$DEPLOY_DIR/../.." && pwd)"; if [ -f "$APP_GUESS/site.env" ]; then SITE_FILE="$APP_GUESS/site.env"; else SITE_FILE="$DEPLOY_DIR/sites/${SITE:-arihakdang}.env"; fi; fi load_site "$SITE_FILE" echo "▶ Haraka 준비: $SITE ($APP_DIR/haraka, 서비스 $APP_NAME-haraka)" [ -x "$NODE_BIN" ] || { echo "Node 실행 파일이 없습니다: $NODE_BIN" >&2; exit 1; } NPM_BIN="$(dirname "$NODE_BIN")/npm"; [ -x "$NPM_BIN" ] || NPM_BIN="$(command -v npm || true)" REPO_HARAKA="$APP_DIR/repo/haraka"; [ -f "$REPO_HARAKA/package.json" ] || REPO_HARAKA="$DEPLOY_DIR/../haraka" mkdir -p "$APP_DIR/haraka"; chown "$APP_USER:$APP_USER" "$APP_DIR/haraka" install -o "$APP_USER" -g "$APP_USER" -m 644 "$REPO_HARAKA/package.json" "$APP_DIR/haraka/package.json" if [ -x "$NPM_BIN" ]; then echo "▶ npm 설치 ($NPM_BIN) — 인터넷이 필요합니다" # 실행 계정으로 설치해 node_modules 소유자를 맞춥니다. 실패해도(오프라인 등) 서비스는 등록하고 안내만 남깁니다. if sudo -u "$APP_USER" env PATH="$(dirname "$NODE_BIN"):$PATH" HOME="$APP_DIR/haraka" "$NPM_BIN" install --omit=dev --no-audit --no-fund --no-package-lock --prefix "$APP_DIR/haraka" --loglevel=error; then echo " 설치됨: Haraka $("$NODE_BIN" -e "console.log(require('$APP_DIR/haraka/node_modules/Haraka/package.json').version)")" else echo " ⚠️ npm 설치 실패 — 인터넷 연결을 확인하고 다시 실행하세요: sudo bash $0 $SITE_FILE" >&2; fi else echo " ⚠️ npm 을 찾지 못했습니다($NODE_BIN 옆에 없음). Node 배포판의 npm 을 두고 다시 실행하세요." >&2; fi REPO_DEPLOY="$APP_DIR/repo/deploy"; [ -f "$REPO_DEPLOY/systemd/mail-haraka.service.in" ] || REPO_DEPLOY="$DEPLOY_DIR" render "$REPO_DEPLOY/systemd/mail-haraka.service.in" "/etc/systemd/system/$APP_NAME-haraka.service"; chmod 644 "/etc/systemd/system/$APP_NAME-haraka.service" # 실행 계정이 deploy.sh 에서 이 서비스를 재시작할 수 있게 sudoers 를 최신 규칙으로 다시 씁니다(setup.sh 와 같은 한 줄). sudoers_line > "/etc/sudoers.d/$APP_NAME"; chmod 440 "/etc/sudoers.d/$APP_NAME"; visudo -c -q systemctl daemon-reload # 첫 배포 전(current 없음)에는 시작하지 않고 등록만 합니다(deploy.sh 가 끝나면 다음 부팅·수동 시작 때 뜸). current 가 있으면 바로 (재)시작. systemctl enable -q "$APP_NAME-haraka" if [ -e "$APP_DIR/current/haraka/run.mjs" ]; then systemctl restart "$APP_NAME-haraka"; sleep 1; systemctl is-active --quiet "$APP_NAME-haraka" && echo " 서비스 실행 중: $APP_NAME-haraka" || echo " ⚠️ 서비스가 뜨지 않았습니다: journalctl -u $APP_NAME-haraka -n 50" >&2 else echo " (아직 배포된 릴리스가 없어 서비스는 등록만 했습니다. deploy.sh 뒤 자동으로 시작합니다)"; fi cat <