fix(docker): mail setup 받는 메일 크기 한도 50MiB · 전환 준비 문서 (mailcow 확인 · 서버 B 배포 · 백업 · 큰 메일) #12

Merged
ttipo merged 14 commits from feat/mail-migration-password into main 2026-11-04 07:59:25 +09:00
Showing only changes of commit 3b59497d59 - Show all commits
+17 -3
View File
@@ -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 <PROJECT_NAME>-mail` 뒤 그 사람들만 다시 — 모두 통과 |
- `docker update` 는 재시작 · 멈춤에도 남지만 **컨테이너를 다시 만들면 compose 의 1g 로 돌아간다** — 다시 만들었으면 다시 건다. 확인 `sudo docker inspect -f '{{.HostConfig.Memory}} {{.RestartCount}}' <PROJECT_NAME>-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/` — 주소 · 폴더 이름이 들어 있어 한 주쯤 뒤 지운다)에 있다.
---