From 3b59497d5955a8ee6d70662973adfa947bc95116 Mon Sep 17 00:00:00 2001 From: ttipo Date: Tue, 3 Nov 2026 18:54:35 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=9A=B4=EC=98=81=20imapsync=20?= =?UTF-8?q?=EC=9D=98=20=ED=81=B0=20=EB=A9=94=EC=9D=BC=20=E2=80=94=20?= =?UTF-8?q?=EC=97=94=EC=A7=84=20=ED=81=AC=EA=B8=B0=20=ED=95=9C=EB=8F=84=20?= =?UTF-8?q?110=20MiB=20=C2=B7=201g=20=EC=97=90=EC=84=9C=20OOM=20=C2=B7=20?= =?UTF-8?q?=EC=98=AE=EA=B8=B0=EC=A7=80=20=EB=AA=BB=ED=95=9C=20=EC=B4=88?= =?UTF-8?q?=EC=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2026-11-03 운영 1 · 2차에서 겪은 것을 imapsync 절에 남긴다. 한도보다 큰 메일은 APPEND 에서 빠지고(114), 100MB 남짓 한 통은 엔진 1g 를 넘겨 OOM 으로 다시 떴다 (그동안 다른 계정은 Connection refused). docker update 2g 는 컨테이너를 다시 만들면 사라지고, 한도를 올린 채 두면 메모리 예산의 합이 바뀐다 — 이전 뒤 어떻게 둘지는 아직 정하지 않았다. Co-Authored-By: Claude Opus 5.5 --- mail/README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/mail/README.md b/mail/README.md index a237ab0..86ab36e 100644 --- a/mail/README.md +++ b/mail/README.md @@ -787,7 +787,7 @@ sudo docker exec "${PROJECT_NAME}-backend" node -e "const s=require('net').conne | --- | --- | --- | --- | | clamav (clamd) | 2g | 0.95GB — 서명 363만 개를 읽은 뒤 | 서명을 다시 읽을 때 1.0GB(두 벌을 들지 않는다), 2GB 검사 중 1.0~1.2GB + 받은 파일의 페이지 캐시(한도 안에서 줄여 쓴다) | | clamav-updater (freshclam) | 1g | 수십 MB | 처음 기동(서명 전체를 받아 읽어 봄) 0.7GB, 평소 갱신은 daily 만 | -| mail | 1g | 0.1~0.3GB | | +| mail | 1g | 0.1~0.3GB | 100MB 남짓 메일 한 통을 넣을 때 1g 를 넘었다(2026-11-03 — 서버 B 는 이전하는 동안 2g, [큰 메일](#큰-메일-운영-2026-11-03)) | | backend | 1g | 0.3~0.5GB | 조각 · 받기는 스트림이라 파일 크기와 상관없다 | | db · frontend · mail-resolver | 512m · 512m · 128m | 작다 | | | **합** | **6.15GB** | 2.5~3GB | 나머지 1.8GB 남짓을 커널 · dockerd · 페이지 캐시가 쓴다 | @@ -1502,7 +1502,7 @@ mailcow 를 거친 메일은 SPF · DMARC 결과가 없고(`Authentication-Resul 이전 중인 계정은 운영 도구 메뉴 `11. 메일 이전` 이 다룬다 — `1. 이전 현황` · `2. 이전용 비밀번호 다시 만들기` · `3. 이전 마치기`(2 · 3 은 `주소 (빈 값이면 이전 중인 계정 모두): `). "이전 중"은 엔진 비밀번호 만료가 미래(30일 안)이면서 운영 도구의 실행 기록에서 마지막으로 건 비밀번호가 이전용인 계정이다(계약 6절 "메일 이전"). 엔진의 **비밀번호 기본 만료**(`x:Authentication` 의 `passwordDefaultExpiry` — 관리 화면의 인증 설정)는 켜지 않는다 — 켜면 직원 비밀번호가 주기적으로 만료되고, 끈 뒤에도 그동안 바꾼 비밀번호의 만료가 남는다. 운영 도구는 켜져 있으면 첫 화면에 알린다. -- 근거는 아래 [개발에서 확인한 것](#개발에서-확인한-것-imapsync--2026-11-02) — mailcow 를 흉내 낸 Dovecot → 개발 엔진. **운영 mailcow · 서버 B 에서는 아직 돌려 보지 않았다** — 준비의 "원본 로그인만"과 단계 5 의 첫 사람으로 확인한다. +- 근거는 아래 [개발에서 확인한 것](#개발에서-확인한-것-imapsync--2026-11-02) — mailcow 를 흉내 낸 Dovecot → 개발 엔진. 운영(mailcow → 서버 B)은 2026-11-03 에 원본 로그인만 · 1차 · 2차를 15계정으로 돌렸다 — 운영에서만 나온 것은 아래 [큰 메일](#큰-메일-운영-2026-11-03)(엔진의 크기 한도 · 메모리). #### 차례 (단계 번호는 [전환 절차](#arasystemitkr-전환-절차-mailcow--stalwart)의 것) @@ -1668,6 +1668,19 @@ sudo rm -f /root/imapsync/mailcow-master.pass /root/imapsync/migration.pass 한 사람에서 실패하면 멈추고 고친다. mailcow 쪽은 Fail2ban 이 막지 않지만(서버 B 도 사설 `10.9.0.1` 로 보인다) Dovecot 이 그 주소 — 바깥 직원 모두 — 의 로그인을 늦춘다(위 "원본"의 접속 주소). - 한쪽 로그인이 실패해도 imapsync 는 다른 쪽 로그인을 해 본 뒤 끝난다(`--justlogin` 에서 봤다) — 출력의 `Err 1/2` 처럼 실패가 둘로 보이면 먼저 나온 것부터 본다. +#### 큰 메일 (운영 2026-11-03) + +엔진의 크기 한도보다 큰 메일은 APPEND 에서 거절되고, 한도 안이어도 100MB 남짓이면 엔진이 메모리 한도 1g 를 넘는다 — 운영 1 · 2차에서 둘 다 겪었다. + +| imapsync 출력 (종료 코드) | 까닭 | 한 일 | +| --- | --- | --- | +| 그 메일에서 `literal exceeds …`, 끝에 `Detected N errors` (114 `EXIT_ERR_APPEND`) | 엔진 한도(IMAP 요청 · 메일 · 첨부 크기)보다 크다 — 그 메일만 빠지고 나머지는 옮긴다 | 관리 화면에서 세 값을 110 MiB(`115343360`)로 — Email 의 E-mail Size · Attachment Size, IMAP 의 `maxRequestSize`. setup 은 이 값을 맞추지 않는다(올린 값이 그대로 남는다) | +| 100MB 남짓 한 통에서 `socket closed`, 그 뒤 몇 사람이 `Connection refused` (`EXIT_CONNECTION_FAILURE_HOST2`) | 엔진이 1g 를 넘어 커널에 죽고(OOM — `dmesg` 에 stalwart) 다시 뜨는 동안이다 | `sudo docker update --memory 2g --memory-swap 2g -mail` 뒤 그 사람들만 다시 — 모두 통과 | + +- `docker update` 는 재시작 · 멈춤에도 남지만 **컨테이너를 다시 만들면 compose 의 1g 로 돌아간다** — 다시 만들었으면 다시 건다. 확인 `sudo docker inspect -f '{{.HostConfig.Memory}} {{.RestartCount}}' -mail`(2147483648 이면 2g). +- 110 MiB 보다 큰 메일은 옮기지 못한다 — 운영에서는 보내지 못한 초안 두 통(244 · 135 MiB)이었고, 사용자가 따로 보관하기로 했다(그 사람만 끝까지 `Detected 2 errors` · 114). +- 이전이 끝난 뒤 한도 · 메모리를 어떻게 둘지는 아직 정하지 않았다 — 한도를 올린 채 두면 엔진에 2g 가 들고, [메모리 예산](#메모리-예산)의 합이 7.15GB(백업이 도는 동안 8.15GB)가 된다. + #### 개발에서 확인한 것 (imapsync — 2026-11-02) mailcow 를 흉내 낸 Dovecot(`dovecot/dovecot:2.3.21.1@sha256:547d28f9a893c93a1d2f6dc164880cd7bfa74009106dfa46b36a6a2ee636d921` — mailcow 와 같은 2.3 줄기, 비-root 로 띄움, 시험 CA 의 인증서)에 @@ -1695,7 +1708,8 @@ mailcow 를 흉내 낸 Dovecot(`dovecot/dovecot:2.3.21.1@sha256:547d28f9a893c93a - **개발과 운영이 다른 점** — 대상 인증서가 자체 서명이라 `--sslargs2 SSL_verify_mode=0` 으로 돌렸고, imapsync 를 잠시 앱 네트워크에 붙여 `mail:993` 으로 갔다(엔진은 신뢰 대역 주소로 본다 — 운영에서는 하지 않는다). 원본은 시험 CA 로 `SSL_verify_mode=1` 이었다. -- **확인하지 않은 것** — 운영 mailcow(2026-05-12 판)의 마스터 계정과 서버 B 도 `10.9.0.1` 로 보이는지(준비의 "원본 로그인만"으로 본다) · Allowed protocols, 서버 B 의 길(`--network host` + `--add-host` 와 엔진이 보는 주소), 운영의 양 · 시간, 직원이 만든 실제 폴더 이름. +- **개발에서 확인하지 않은 것** — 운영 mailcow(2026-05-12 판)의 마스터 계정 · Allowed protocols · 서버 B 의 길(`--network host` + `--add-host`)은 2026-11-03 운영에서 됐다(원본 로그인만 → 1차 · 2차 15계정). 아직 보지 않은 것은 엔진이 보는 서버 B 의 주소다. + 운영의 양 · 시간 · 직원이 만든 폴더 이름은 사람마다의 imapsync 로그(서버 B `/root/imapsync/log/` — 주소 · 폴더 이름이 들어 있어 한 주쯤 뒤 지운다)에 있다. ---