Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
15 KiB
외부 서비스 연동 모듈 — Arimail(메일)·Gitea(소스 보관) — v1.5.7
AI Webmaker v1.5.7 · 2026-10-14 · 대상: 운영자·개발자
1. 연동 모듈 (요구 5·6)
웹메이커가 다른 제품으로 바꿔 쓸 수 있는 외부 서비스는 종류(kind)마다 연동 모듈 하나를 고른다. 모듈은 lib/connectors/ 에 있고 등록소 lib/connectors/index.js 가 설정 파일(source.provider, mail.provider)에 따라 고른다.
| 종류 | 모듈 | 하는 일 | 쓰는 쪽 |
|---|---|---|---|
source 소스 보관 |
gitea.js |
푸시 주소·웹 주소·브랜치 접두어, git/ssh 오류 해석, 연결 확인(git ls-remote + API), API 토큰이 있으면 저장소 만들기·공개키 등록 |
lib/gitstore.js (git 명령은 그대로, 접속 정보만 모듈에서) |
mail 메일 서버 |
arimail.js |
관리자 API 로그인, 계정 목록·생성·비밀번호 재설정·삭제, 상태(/api/health), 웹메일 주소·메일 프로그램 설정값 | lib/mailsys.js (받는 메일 백엔드: 사이트 관리자 계정의 메일 사용 켜기/끄기, 웹메일 연결) |
모듈의 공통 모양: id, label, kind, settings(), configured(), status(). 다른 제품(GitLab, 다른 메일 서버)으로 바꾸려면 같은 모양의 모듈을 만들고 index.js 의 MODULES 와 lib/config.js 의 provider 선택지에 넣는다. 접속 정보(주소·계정)는 설정 파일, 비밀값은 보관소(lib/vault.js 종류 gitea, arimail)에 둔다.
2. Arimail 이란
OZ-Group 의 메일 게이트웨이 mail-gateway 가 0.9.x 에서 AriMail(Arimail) 로 이름이 바뀐다. Resend 로 받은 메일을 보관하고 웹메일(/), 관리자 페이지(/admin), IMAP(993/143)·POP3(995/110)·SMTP 제출(465/587) 서버를 연다. 한 설치는 한 메일 도메인(환경 파일 MAILBOX=admin@도메인)의 계정 로그인ID@도메인 을 다룬다. 설치·운영 문서는 그 저장소의 docs/SETUP.md.
웹메이커와의 관계
- 보내기는 지금처럼 웹메이커의 Resend 키(관리자 콘솔 › 설정 › 메일 발송)로 한다. Arimail 도 같은 Resend 로 보내므로 발신 인증(DKIM) 레코드는 공통이다.
- 받기·웹메일·메일 계정은 Arimail 이 맡는다. 사이트 관리자 계정의 "메일 사용" 을 켜면 웹메이커가 Arimail 관리자 API 로 같은 로그인 ID 의 계정을 만들고, 끄면 지운다. 웹메이커는 사이트 관리자 비밀번호의 원문을 갖고 있지 않으므로(scrypt 해시만) 켤 때 메일 비밀번호를 정한다 — 웹메일·IMAP·POP·SMTP 가 그 비밀번호를 쓴다.
- 사이트의
/webmail진입 파일 → 웹메이커/webmail/<사이트ID>/→ 메일 서버가 연결된 사이트면 Arimail 웹메일로 302. 사이트 관리자 페이지 › 메일의 "웹메일 열기" 도 그 주소. - 도메인 일치 조건: 사이트의 메일 도메인(관리자 콘솔 › 메일 시스템에서 켠 도메인)이
mail.domain과 같을 때만 받는 메일이 연결된다. 다른 도메인 사이트는 "메일 서버는 X 도메인만 다룬다" 안내와 함께 보내기만 가능하다. 도메인마다 Arimail 을 하나씩 설치한다(여러 설치를 한 설정에 담는 것은 다음 단계).
3. 설치·등록 (deploy/install-arimail.sh, 요구 4)
서비스 서버에서 웹메이커 실행 계정으로(비밀번호 없는 sudo 필요):
# 새로 설치 + 등록 (소스: ~/work/mail-gateway 체크아웃을 번들로 묶거나 --repo 로 복제)
deploy/install-arimail.sh --host mail.example.com --mailbox admin@example.com [--source ~/work/mail-gateway | --bundle <번들> | --repo <URL>]
[--user arimail] [--app-name arimail] [--port 8790] [--node <node 22.13+>] [--from-name "이름"] [--limit-accounts 50 --limit-mailbox 500M …]
# 이미 설치된(또는 다른 서버의) Arimail 등록만
deploy/install-arimail.sh --register-only --url https://mail.example.com --domain example.com --admin-login webmaker-admin --admin-password '…' [--api-url http://127.0.0.1:8790]
# 이 서버에 설치된 Arimail 을 찾아 등록 (install-services.sh --check / remote-update.sh 가 부른다)
deploy/install-arimail.sh --check
하는 일: ① 소스 확보(git bundle — 서버에 저장소 자격 증명을 두지 않음) ② 실행 계정(시스템 계정)과 Node 22.13+(시스템 node 가 맞으면 그것, 아니면 /opt/<app>-node) ③ Arimail 표준 절차 deploy/new-site.sh(standalone) → setup.sh(root: 디렉터리·/etc/<app>/gateway.env·systemd·sudoers·nginx vhost·certbot 훅) → deploy.sh(실행 계정: 테스트·릴리스·DB 마이그레이션·재시작). nginx 가 없는 서버(Caddy 등)는 nginx 를 뺀 같은 준비를 하고 프록시 설정 예시를 알려 준다 ④ gateway.env 의 RESEND_API_KEY 가 비어 있으면 웹메이커 보관소의 메일 발송 키를 넣는다 ⑤ 웹메이커 전용 Arimail 관리자 계정 webmaker-admin(무작위 비밀번호)을 만들고 설정 파일에 등록: mail.provider=arimail, mail.url=https://<host>, mail.apiUrl=http://127.0.0.1:<port>, mail.domain, mail.adminLogin, mail.adminPassword(보관소) ⑥ 남은 수동 작업 안내.
남는 수동 작업
- DNS:
mail.<도메인>A 레코드 → 서버 공인 IP(프록시 없이). 바뀌면 Arimail 의<app>-tls.timer가 certbot 으로 인증서를 받아 443·메일 포트 TLS 를 켠다. - Resend: 도메인을 수신·발신 도메인으로 등록하고 Webhooks →
https://mail.<도메인>/api/webhooks/resend(email.received) 의 Signing Secret 을/etc/<app>/gateway.env의RESEND_WEBHOOK_SECRET에 넣고 서비스 재시작. 받는 메일 MX 는 Resend 안내값(관리자 콘솔 › 메일 시스템 › 기본값의 "메일 서버 주소" 에 그 값을 넣으면 DNS 안내 표에 나온다). - 초기 관리자
admin / adminpasswd로/admin에 들어가 비밀번호를 바꾼다(웹메이커는 별도 계정webmaker-admin을 쓴다).
deploy/install-services.sh --gitea | --arimail … | --check 가 Gitea 와 Arimail 을 한 번에 다루며, deploy/install.sh·remote-install.sh(끝에 Gitea 설치, ARIMAIL_HOST·ARIMAIL_MAILBOX 환경 변수가 있으면 Arimail 도)·remote-update.sh(--check)가 부른다.
4. 동작 확인
- 초기 설정 페이지 / 관리자 콘솔 › 시스템 설정 › "메일 서버 — Arimail" 카드 → 연결 확인:
연결 성공 — Arimail 0.9.9 · 도메인 example.com · 계정 N개. - 관리자 콘솔 › 메일 시스템 상단: "받는 메일·웹메일: Arimail … 연결됨 — 메일 도메인이 example.com 인 사이트에 적용".
- 사이트 관리자 페이지 › 메일 › 메일 계정 스위치 켜기 → 메일 비밀번호 입력 →
메일 서버에 계정을 만들었습니다: id@example.com …안내. Arimail 관리자 페이지 계정 목록에 같은 계정이 보인다. 끄면 계정이 지워진다(메일은 Arimail 저장소에 남아 관리자 페이지에서 정리). - 보관소 항목
arimail·gitea의 "연결 확인" 도 같은 모듈 status() 를 쓴다.
5. 자주 나는 메시지
| 메시지 | 원인 | 해결 |
|---|---|---|
메일 서버(Arimail) 연동이 꺼져 있어 받을 수 없습니다 |
mail.provider=none |
설정 페이지 › 메일 연동에서 Arimail 로 바꾸고 주소·도메인·관리자 계정 입력, 또는 install-arimail.sh |
Arimail 주소는 있지만 도메인 또는 관리자 비밀번호가 없습니다 |
설정 미완 | mail.domain, mail.adminPassword 입력 |
Arimail 응답 없음 — 연결 실패: ECONNREFUSED |
서비스가 꺼짐·내부 API 주소 틀림 | systemctl status <app>, mail.apiUrl 확인 |
Arimail 관리자 로그인에 실패했습니다 |
비밀번호 틀림·계정이 관리자 역할 아님 | Arimail /admin 에서 계정 확인, install-arimail.sh --check 로 webmaker-admin 비밀번호 재설정·재등록 |
메일 비밀번호를 입력하세요 (메일 사용 켜기) |
Arimail 이 연결된 사이트는 비밀번호가 필요 | 사이트 관리자 페이지의 입력 창에서 정함 |
메일 비밀번호가 Arimail 의 비밀번호 정책에 맞지 않습니다 |
Arimail 관리자 페이지 › 비밀번호 정책 | 정책에 맞는 비밀번호 |
Arimail 의 계정 수 제한(LIMIT_ACCOUNTS)에 이르렀습니다 |
설치 때 정한 시스템 제한 | /etc/<app>/gateway.env 의 LIMIT_ACCOUNTS 조정 후 재시작 |
메일 서버(Arimail)는 X 도메인만 다루는데 이 사이트의 메일 도메인은 Y 입니다 |
도메인 불일치 | 같은 도메인으로 메일 시스템을 켜거나 그 도메인용 Arimail 설치 |
Arimail 로그인 시도가 너무 많아 잠시 막혔습니다 (15분 뒤 다시) / 표의 "Arimail 로그인 잠금 · HH:MM 까지" |
틀린 비밀번호로 로그인을 반복 (Arimail 15분 10회 제한) | 1.6.39: 해제 시각까지 "연결 확인" 이 비활성. 그 사이 "수정"/"이전 비밀번호로" 로 맞는 값을 저장해 두고 해제 뒤 한 번만 확인 |
Arimail 관리자 계정 "…" 은(는) 웹메이커에서 지울 수 없습니다 — … 보호됩니다 |
연동 관리자·관리자 역할 계정 삭제·역할 하향 시도 | 1.6.39: 설계상 막음. 필요하면 Arimail /admin 에서 직접 |
사이트 관리자 비밀번호와 다릅니다 — 메일 비밀번호는 이 계정의 비밀번호와 같게 유지되므로… (메일 사용 켜기) |
본인 계정에 다른 메일 비밀번호를 넣음 | 1.6.39: 지금 로그인한 비밀번호를 입력 |
| 사이트 관리자 페이지 메일 계정 표 "비밀번호 동기화: 실패 — … 비밀번호 정책" | Arimail 비밀번호 정책이 웹메이커 규칙보다 엄격 | 관리자 비밀번호를 정책에 맞게 바꾸면 다음 로그인 때 다시 맞춰진다 |
Arimail 로그인 실패 — … (저장된 비밀번호가 틀리면 "다른 관리자 계정으로 재설정" 을 쓰세요) (비밀번호 초기화) |
보관소의 연동 계정 비밀번호가 틀림 | 열리는 폼에 Arimail 의 다른 관리자(초기 admin 등) 아이디·비밀번호 입력 → 연동 계정 비밀번호 재생성 |
6. 여러 메일 서버 — 다른 서버에 설치된 Arimail (v1.6.38, 요구 2)
웹메이커와 Arimail 을 다른 서버에 나눠 설치할 수 있고(예: webmaker.ibit.kr 121.152.149.45 ↔ webmail.ibit.kr 115.68.194.192), 메일 도메인마다 다른 Arimail 을 붙일 수 있다.
- 등록부
lib/mailservers.js→data/mail-servers.json(id·닉네임·IP·공개 주소·API 주소·메일 도메인·관리자 ID·연결 확인). 관리자 비밀번호는 보관소(lib/vault.js) 종류arimail, 식별자arimail-<id>. - 기본 서버(설정 파일):
mail.url / mail.apiUrl / mail.domain / mail.adminLogin / mail.adminPassword의 서버는 idprimary로 등록부에 함께 보인다.install-arimail.sh --register-only는 여기에 쓴다. 닉네임·IP 는mail.nickname·mail.ip. - 관리자 콘솔 › 메일 시스템 › 메일 서버 (Arimail) 연동: 추가(닉네임·서버 IP·Arimail 주소·API 주소·메일 도메인·관리자 ID·비밀번호) · 연결 확인(health → 관리자 로그인 → 계정 수) · 수정 · 기본으로 · 삭제. 비밀번호는 화면·작업 기록에 나오지 않는다.
- 사이트가 쓰는 서버: 사이트 메일 설정의 "메일 서버" 에서 고른 서버 → 없으면 사이트 메일 도메인과 같은 도메인을 다루는 서버 → 없으면 기본 서버. 도메인이 맞지 않으면 사이트 메일 상태가 그 이유를 말한다.
- MX 기본값: 사이트·전역 MX 호스트가 비어 있으면 고른 메일 서버의 호스트(예: webmail.ibit.kr)를 MX 로 안내한다.
- API:
GET/POST /api/admin/mail-servers,PUT/DELETE /api/admin/mail-servers/<id>,POST /api/admin/mail-servers/<id>/test,POST /api/admin/mail-servers/<id>/default. - 연동 모듈:
require('./lib/connectors/arimail').forServer(server)가 서버에 묶인 동작(로그인·계정·상태)을 돌려준다. 최상위 함수는 기본 서버에 묶여 있다.
7. 비밀번호 — 보관·되돌리기·잠금·보기·초기화·동기화 (v1.6.39, 요구 2·3·4)
2026-10-21 webmaker.ibit.kr 에서 기본 메일 서버를 수정하다 비밀번호 칸에 값을 넣어 동작하던 Arimail 관리자 비밀번호를 덮어쓰고, "연결 확인" 을 반복해 15분 잠금까지 걸린 사고에서 나온 설계다.
- 연동 관리자 비밀번호의 자리: 기본 서버는 설정 파일
mail.adminPassword(보관소arimail), 추가 서버는 보관소arimail-<id>. 이전 값은prev-arimail/prev-arimail-<id>(비밀번호를 바꾸기 직전 자동 보관). 모두data/credentials.json(0600, AES-256-GCM) 이고 1.6.39 부터.bak이 함께 남는다(config.json·mail-servers.json도). - 관리자 콘솔 › 메일 시스템 › 메일 서버 연동 표
- 관리자 ID 칸 [보기]/[숨기기]·[복사] —
GET /api/admin/mail-servers/<id>/password(관리자 전용). 60초 뒤 자동 숨김. 작업 기록mailserver.reveal(비밀번호 없음). 초기 설정 뒤 Arimail/admin로그인에 쓴다. - 수정 때 비밀번호 칸에 값이 있으면 확인 창 — 그대로 두려면 칸을 비운다.
- 이전 비밀번호로 —
POST …/revert-password. 이전 값 ↔ 현재 값을 맞바꾼다(다시 되돌릴 수 있음). - 비밀번호 초기화 —
POST …/reset-password. 16자 무작위(대·소문자·숫자·기호) 비밀번호를 Arimail 계정에 설정하고 보관. 저장된 비밀번호로 로그인이 안 되면 "다른 관리자 계정으로 재설정" 폼({via:{login,password}}, 저장하지 않음; 연동 계정이 없으면 관리자 역할로 생성). - 잠금 — Arimail 이
rate_limited를 돌려주면 등록부에lockedUntil(15분). 그동안 "연결 확인" 비활성 + 남은 시간 표시, 서버의mailservers.test()도 Arimail 을 부르지 않는다. 해제 뒤 성공하면 기록이 지워진다.
- 관리자 ID 칸 [보기]/[숨기기]·[복사] —
- 관리자 계정 보호(
protectAdmin): 연동 관리자 계정과 Arimail 관리자 역할 계정은 웹메이커의 DELETE·역할 하향·비활성화가 403. 비밀번호·이름 변경과 admin 으로 올리기는 허용. - 사이트 관리자 비밀번호 ↔ 메일 비밀번호 동기화(
mailsys.syncPassword): 웹메이커는 관리자 비밀번호를 해시로만 가지므로, 원문을 아는 순간(사이트 관리자 페이지·웹메일 로그인 성공)마다 등록부data/mail-accounts.json의pwSyncHash와 지금 해시를 비교해 다르면 Arimail 계정 비밀번호를 PATCH 로 맞춘다. 결과는pwSyncAt / pwSyncError와 작업 기록mail.account.sync(원문 없음). "메일 사용 켜기" 는 본인 계정이면 관리자 비밀번호 그대로(다르면 400), 소유자·운영자가 대신 켤 때는 임시 비밀번호 → 다음 로그인 때 자동으로 맞춰진다. 사이트 관리자 페이지 메일 계정 표의 "비밀번호 동기화" 열에서 상태를 본다. - API 정리:
GET …/<id>/password·POST …/<id>/revert-password·POST …/<id>/reset-password· 연결 확인 응답locked / lockedUntil / code· 서버 객체hasPrevPassword / prevPasswordAt / lockedUntil / adminUrl.