# Mail Service Runbook

이 문서는 **공유기 포트포워딩이 이미 끝난 상태**에서 시작합니다.

포워딩 완료 전제:

- `80`
- `443`
- `25`
- `465`
- `587`
- `993`
- `4190`

선택:

- `110`
- `143`
- `995`

중요:

- 아래 커맨드는 **Apache 컨테이너 안에서 실행하는 것이 아닙니다**
- 반드시 **Docker 호스트 셸**에서 실행합니다
- 예: `root@kssoft:~#`

또 하나 중요:

- Mailcow는 **컨테이너 1개**가 아닙니다
- `postfix`, `dovecot`, `nginx-mailcow`, `mysql`, `redis`, `rspamd`, `sogo` 등으로 이루어진 **전용 Docker Compose 스택**입니다

즉 이 문서의 목적은:

1. Mailcow 전용 컨테이너 세트 생성
2. 호스트 nginx에 `mail.officialsite.kr` 연결
3. Cloudflare DNS 설정
4. 고객 도메인에 안내할 `mx1.officialsite.kr` 기준값 정리

---

## 이미 Mailcow가 떠 있으면

아래처럼 `docker ps` 에 `mailcowdockerized-*` 컨테이너들이 이미 `Up` 상태로 보이면:

- `mailcowdockerized-nginx-mailcow-1`
- `mailcowdockerized-postfix-mailcow-1`
- `mailcowdockerized-dovecot-mailcow-1`
- `mailcowdockerized-acme-mailcow-1`

그 상태는 이미 **3-2 설치/컨테이너 생성 단계가 끝난 상태**입니다.

즉 이 경우:

- `2번 설정 파일 준비`는 **건너뛰어도 됨**
- `3-1`, `3-2`는 **다시 할 필요 없음**
- `3-3 상태 확인`만 필요하면 참고
- 바로 **4번 호스트 nginx 연결**부터 진행하면 됨

정리:

```text
Mailcow 컨테이너가 이미 떠 있다
-> 3-2 다시 하지 말 것
-> 4번부터 진행
```

---

## 1. 호스트에서 작업하는지 먼저 확인

아래가 **호스트 셸**에서 나와야 합니다.

```bash
hostname
docker ps
```

예:

```bash
root@kssoft:~#
```

이런 프롬프트면 진행.

아래처럼 컨테이너 ID처럼 보이는 프롬프트면 중단:

```bash
root@f57ae796f207:/#
```

---

## 1-1. 완전 초기화 후 다시 시작하고 싶을 때

아래 커맨드는 **Mailcow 관련 컨테이너/볼륨/설치폴더만 삭제**합니다.

- 삭제 대상: `mailcowdockerized-*`
- 유지 대상: `apache_3000`, `apache_3001`, `apache_3002`, `DB`, `ftp`

완전 초기화:

```bash
cd /opt/mailcow-dockerized
docker compose down --volumes --remove-orphans
cd /
rm -rf /opt/mailcow-dockerized
```

확인:

```bash
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker volume ls | grep mailcow || true
docker network ls | grep mailcow || true
```

설명:

- 이 작업 후에는 Mailcow DB, 설정 데이터, 메일 데이터도 같이 지워집니다
- 즉 **완전 새 설치 상태**로 돌아갑니다
- 이후에는 이 문서의 **2번부터 다시 진행**하면 됩니다

주의:

- `docker system prune -a` 같은 전체 정리 명령은 쓰지 마세요
- 기존 Apache/DB/FTP 컨테이너까지 날릴 수 있습니다

---

## 2. 설정 파일 준비

여기부터는 **레포 경로에 의존하지 않아도 됩니다**.

즉:

- repo가 Apache 컨테이너 안에 있어도 상관없음
- 아래 내용만 **복사해서 호스트에 파일로 저장**하면 됨
- `deploy/ubuntu` 폴더는 템플릿 보관용으로 보면 됨

권장:

- 호스트에 `/root/mailcow-setup` 폴더를 만들고 거기에 저장

```bash
mkdir -p /root/mailcow-setup
cd /root/mailcow-setup
```

### 2-1. 변수 파일 만들기

아래 내용을 새 파일 `/root/mailcow-setup/00-vars.sh` 로 저장:

```bash
TIMEZONE="Asia/Seoul"

MAILCOW_DIR="/opt/mailcow-dockerized"
MAILCOW_BRANCH="master"
MAILCOW_SKIP_CLAMD="y"

MAIL_UI_HOSTNAME="mail.officialsite.kr"
MX_HOSTNAME="mx1.officialsite.kr"
MAIL_SERVER_PUBLIC_IP="221.155.112.97"

ACME_ACCOUNT_EMAIL="admin@officialsite.kr"
DMARC_REPORT_EMAIL="dmarc@officialsite.kr"

HOST_NGINX_PROXY_TARGET="127.0.0.1:8080"

CUSTOMER_SAMPLE_DOMAIN="customer.co.kr"
```

설명:

- `MAIL_UI_HOSTNAME`
  - 관리자/웹메일 접속 주소
  - 예: `https://mail.officialsite.kr/admin`
- `MX_HOSTNAME`
  - 고객이 MX로 넣을 값
  - 예: `mx1.officialsite.kr`

### 2-2. lib.sh 만들기

원본 템플릿:

- [lib.sh](/D:/works/kscompany/official-mail/deploy/ubuntu/lib.sh)

이 파일 내용을 복사해서 `/root/mailcow-setup/lib.sh` 로 저장.

### 2-3. 설치 스크립트 만들기

아래 파일들도 **내용을 그대로 복사해서 호스트에 저장**하면 됩니다.

원본:

- [01-install-prereqs.sh](/D:/works/kscompany/official-mail/deploy/ubuntu/01-install-prereqs.sh)
- [02-install-mailcow.sh](/D:/works/kscompany/official-mail/deploy/ubuntu/02-install-mailcow.sh)
- [03-check-mailcow.sh](/D:/works/kscompany/official-mail/deploy/ubuntu/03-check-mailcow.sh)

호스트 저장 위치 예:

- `/root/mailcow-setup/01-install-prereqs.sh`
- `/root/mailcow-setup/02-install-mailcow.sh`
- `/root/mailcow-setup/03-check-mailcow.sh`

실행권한:

```bash
chmod +x /root/mailcow-setup/*.sh
```

---

## 3. Docker 기반 Mailcow 컨테이너 세트 생성

### 3-1. 필수 패키지

```bash
cd /root/mailcow-setup
bash 01-install-prereqs.sh
```

이 스크립트가 하는 일:

- `git`, `curl`, `jq` 설치
- Docker 설치 확인
- `docker-compose-plugin` 설치

### 3-2. Mailcow 설치 및 컨테이너 생성

```bash
cd /root/mailcow-setup
bash 02-install-mailcow.sh
```

이 스크립트가 하는 일:

- `/opt/mailcow-dockerized` clone 또는 업데이트
- `mailcow.conf` 생성
- `MAIL_UI_HOSTNAME=mail.officialsite.kr` 기준 적용
- `ADDITIONAL_SAN=mx1.officialsite.kr` 적용
- Mailcow 컨테이너 세트 `docker compose up -d`

즉 이 단계가 곧 **메일카우 전용 컨테이너 세트 생성 단계**입니다.

### 3-3. 상태 확인

```bash
cd /root/mailcow-setup
bash 03-check-mailcow.sh
```

또는 직접:

```bash
cd /opt/mailcow-dockerized
docker compose ps
docker compose logs --tail=80 nginx-mailcow
docker compose logs --tail=80 postfix-mailcow
docker compose logs --tail=80 dovecot-mailcow
```

정상 기대 상태:

- `nginx-mailcow` 가 `Up`
- `postfix-mailcow` 가 `25`, `465`, `587` 바인딩
- `dovecot-mailcow` 가 `993`, `4190` 바인딩
- `nginx-mailcow` 가 `127.0.0.1:8080` 으로 바인딩

---

## 4. 호스트 nginx에 mail.officialsite.kr 연결

웹서비스는 이미 네가 운영 중이므로, **호스트 nginx에 mail vhost만 추가**하면 됩니다.

예시 파일:

- [04-host-nginx-mail.conf.example](/D:/works/kscompany/official-mail/deploy/ubuntu/04-host-nginx-mail.conf.example)

적용:

```bash
# 위 예시 파일 내용을 복사해서 아래 경로로 저장
# /etc/nginx/sites-available/mail.officialsite.kr

ln -sfn /etc/nginx/sites-available/mail.officialsite.kr /etc/nginx/sites-enabled/mail.officialsite.kr
nginx -t
systemctl reload nginx
```

이 설정의 의미:

- 외부 `mail.officialsite.kr`
- 내부 `127.0.0.1:8080`

즉 **호스트 nginx -> Mailcow UI** 연결입니다.

---

## 5. Cloudflare DNS 설정

먼저 `officialsite.kr`에서 Cloudflare Email Routing이 켜져 있으면 꺼야 합니다.

경로:

- Cloudflare Dashboard
- `officialsite.kr`
- `Compute`
- `Email Service`
- `Email Routing`
- `Disable Email Routing`

### 5-1. 서비스 도메인용 레코드

`officialsite.kr` 존에 아래를 넣습니다.

| Type | Name | Content | Priority | Proxy |
| --- | --- | --- | --- | --- |
| `A` | `mail` | `221.155.112.97` | - | `DNS only` |
| `A` | `mx1` | `221.155.112.97` | - | `DNS only` |
| `TXT` | `mx1` | `v=spf1 ip4:221.155.112.97 -all` | - | `DNS only` |
| `TXT` | `_dmarc` | `v=DMARC1; p=none; rua=mailto:dmarc@officialsite.kr` | - | `DNS only` |

선택:

| Type | Name | Content | Proxy |
| --- | --- | --- | --- |
| `CNAME` | `autodiscover` | `mail.officialsite.kr` | `DNS only` |
| `CNAME` | `autoconfig` | `mail.officialsite.kr` | `DNS only` |

주의:

- `mail` 과 `mx1` 은 **절대 Proxied 켜면 안 됩니다**
- 둘 다 반드시 `DNS only`

### 5-2. 고객에게 안내할 DNS 값

예시 고객 도메인 `abc.co.kr`

| Type | Name | Content | Priority |
| --- | --- | --- | --- |
| `MX` | `@` | `mx1.officialsite.kr.` | `10` |
| `TXT` | `@` | `v=spf1 include:mx1.officialsite.kr -all` | - |
| `TXT` | `selector._domainkey` | `Mailcow에서 발급한 고객별 DKIM 공개키` | - |
| `TXT` | `_dmarc` | `v=DMARC1; p=none; rua=mailto:dmarc@officialsite.kr` | - |

선택:

| Type | Name | Content |
| --- | --- | --- |
| `CNAME` | `autodiscover` | `mail.officialsite.kr` |
| `CNAME` | `autoconfig` | `mail.officialsite.kr` |

중요:

- 고객 메일 주소가 `대표@abc.co.kr` 라면 MX는 **고객 도메인 루트 `abc.co.kr`** 에 들어갑니다
- 고객은 자기 도메인의 `MX`를 `mx1.officialsite.kr` 로 가리키게 해야 합니다
- DKIM은 고객마다 다릅니다

---

## 6. Mailcow 관리자 접속 후 해야 할 것

접속:

- `https://mail.officialsite.kr/admin`

기본 계정:

- ID: `admin`
- Password: `moohoo`

로그인 직후:

1. 관리자 비밀번호 변경
2. `Configuration`
3. `Mail Setup`
4. `Domains`
5. 고객 도메인 추가
6. 고객 도메인의 DKIM 확인
7. `Mailboxes` 에서 고객 메일박스 생성

예:

- 도메인: `abc.co.kr`
- 메일박스: `대표@abc.co.kr`

---

## 7. 고객 도메인 추가 후 해야 할 것

Mailcow에서 고객 도메인을 추가한 뒤:

1. DKIM 공개키 복사
2. 고객에게 아래 4개 전달

- `MX`
- `SPF`
- `DKIM`
- `DMARC`

즉 고객 가이드 핵심은 항상 이 형식입니다.

```text
MX    @                  10 mx1.officialsite.kr.
TXT   @                     v=spf1 include:mx1.officialsite.kr -all
TXT   selector._domainkey   <발급된 DKIM 값>
TXT   _dmarc                v=DMARC1; p=none; rua=mailto:dmarc@officialsite.kr
```

---

## 8. 메일 서버 점검 커맨드

컨테이너 상태:

```bash
cd /opt/mailcow-dockerized
docker compose ps
```

로그:

```bash
docker compose logs --tail=100 nginx-mailcow
docker compose logs --tail=100 postfix-mailcow
docker compose logs --tail=100 dovecot-mailcow
docker compose logs --tail=100 acme-mailcow
```

포트:

```bash
ss -lntp | egrep ':(25|80|110|143|443|465|587|993|995|4190)\s'
```

---

## 9. 지금 네 상태에서 바로 다음 순서

이미 포트포워딩 완료라면 이 순서만 따르면 됩니다.

```bash
mkdir -p /root/mailcow-setup
cd /root/mailcow-setup
# 00-vars.sh, lib.sh, 01-install-prereqs.sh, 02-install-mailcow.sh, 03-check-mailcow.sh 를
# repo의 deploy/ubuntu 템플릿에서 복사해서 저장
chmod +x *.sh
bash 01-install-prereqs.sh
bash 02-install-mailcow.sh
bash 03-check-mailcow.sh
# 04-host-nginx-mail.conf.example 내용을 /etc/nginx/sites-available/mail.officialsite.kr 로 저장
ln -sfn /etc/nginx/sites-available/mail.officialsite.kr /etc/nginx/sites-enabled/mail.officialsite.kr
nginx -t
systemctl reload nginx
```

그 다음:

1. Cloudflare에 `mail`, `mx1`, `mx1 TXT` 추가
2. `https://mail.officialsite.kr/admin` 접속
3. 고객 도메인 추가
4. 고객에게 `mx1.officialsite.kr` 기준 DNS 안내
