IT 관련/우분투(Ubuntu) 이것저것

[왕초보] Banana Pi M5 메일 서버 호스팅 A to Z: 2단계 Postfix 설치 및 첫 메일 발송

islet2 2025. 5. 20. 22:11

 

[왕초보] Banana Pi M5 메일 서버 호스팅 A to Z: 2단계 - Postfix와 SMTP, 이메일 발송의 시작 1부에서 DNS 설정과 서버 기본 준비를 마쳤습니다. 이제 실제로 이메일을 주고받는 시스템의 심장, 메일 전송 에이전트(MTA)인 Postfix를 설치하고 SMTP 프로토콜을 통해 이메일을 발송하는 첫걸음을 내디뎌 봅니다!

지난 1부에서는 메일 서버 구축의 큰 그림을 그리고, 도메인 DNS 설정과 Banana Pi의 기본 환경을 준비했습니다. 기억나시죠? 못 보셨다면 1부 가이드를 먼저 보고 오시는 것을 추천합니다! 이제부터는 조금 더 기술적인 내용이 포함되지만, 차근차근 따라오시면 충분히 하실 수 있습니다. 자, 그럼 시작해볼까요? 🚀

 

Postfix와 SMTP: 이메일은 어떻게 전달될까요? 🤔

우리가 이메일을 보내면 어떤 과정을 거쳐 상대방에게 전달될까요? 이때 등장하는 핵심 기술이 바로 SMTP (Simple Mail Transfer Protocol)Postfix입니다.

  • SMTP: 이름처럼 이메일을 인터넷을 통해 주고받기 위한 간단한 통신 규약(프로토콜)입니다. 우리가 편지를 우체통에 넣으면 우체국 시스템을 통해 배달되는 것처럼, SMTP는 이메일이 서버 간에 전송되는 규칙과 방법을 정의합니다.
  • Postfix: 바로 이 SMTP 프로토콜을 사용하여 이메일을 실제로 전송하고 수신하는 역할을 하는 소프트웨어가 MTA(Mail Transfer Agent)입니다. Postfix는 보안성과 안정성이 뛰어나 널리 사용되는 오픈소스 MTA 중 하나입니다. 우리가 구축할 메일 서버의 핵심 엔진이라고 생각하시면 됩니다.

오늘은 이 Postfix를 Docker를 이용해 우리 Banana Pi M5에 설치하고, 이메일을 외부로 발송할 수 있도록 기본 설정을 진행할 거예요.

 

`docker-mailserver` 이미지 선택 이유 🐳

Postfix, Dovecot(메일 수신 및 보관용), 스팸 필터, 바이러스 검사 등 메일 서버를 제대로 운영하려면 생각보다 많은 구성 요소가 필요합니다. 각 요소를 개별적으로 설치하고 연동하는 것은 초보자에게 매우 복잡하고 시간이 많이 소요될 수 있습니다.

다행히도, 이러한 구성 요소들을 하나로 묶어 편리하게 관리할 수 있도록 미리 만들어진 Docker 이미지가 있습니다. 그중에서도 `docker-mailserver/docker-mailserver` 이미지는 매우 인기가 많고 기능이 풍부하며, 지속적으로 관리되고 있어 추천할 만합니다. (Docker Hub에서는 `mailserver/docker-mailserver` 로 검색될 수 있습니다.)

💡 `docker-mailserver`의 장점
  • 올인원(All-in-One): Postfix (SMTP), Dovecot (IMAP/POP3), SpamAssassin (스팸 필터), ClamAV (바이러스 백신), OpenDKIM, OpenDMARC 등 필요한 대부분의 기능이 포함되어 있습니다.
  • 간편한 설정: 복잡한 설정을 환경 변수나 설정 파일을 통해 비교적 쉽게 관리할 수 있습니다.
  • 활발한 커뮤니티 및 문서: 사용자가 많아 문제 해결에 필요한 정보를 얻기 쉽고, 공식 문서도 잘 되어 있습니다.

이 시리즈에서는 `docker-mailserver` 이미지를 사용하여 단계별로 기능을 활성화하고 설정하는 방법을 알아볼 것입니다. 오늘은 Postfix를 이용한 메일 발송에 초점을 맞춥니다.

 

`docker-mailserver` 설치 및 기본 설정 🛠️

이제 Banana Pi에 SSH로 접속하여 `docker-mailserver`를 설정하고 실행해 보겠습니다.

1. 설정 파일 및 데이터 저장 디렉토리 생성:

Docker 컨테이너가 종료되거나 업데이트되어도 설정과 메일 데이터가 유지되도록 호스트 시스템에 디렉토리를 만들고 볼륨으로 연결합니다.


# 홈 디렉토리 아래에 mailserver 디렉토리 생성 (원하는 경로로 변경 가능)
mkdir -p ~/mailserver/config
mkdir -p ~/mailserver/data
mkdir -p ~/mailserver/state
# 예시 경로: /mnt/mydisk/mailserver 와 같이 별도 디스크에 생성하는 것도 좋은 방법입니다.
# 이 가이드에서는 사용자 홈 디렉토리 밑에 생성하는 것으로 가정합니다.
# 실제 경로를 기억해두세요.
# 예를 들어, /home/사용자계정명/mailserver/ 일 수 있습니다.
# pwd 명령어로 현재 경로를 확인하고 전체 경로를 docker-compose.yml에 적어주세요.
# 예: export DMS_CONFIG=/home/your_user/mailserver/config
# export DMS_DATA=/home/your_user/mailserver/data
# export DMS_STATE=/home/your_user/mailserver/state

주의: 위 경로 예시에서 `~/mailserver`는 현재 로그인한 사용자의 홈 디렉토리 아래를 의미합니다. `docker-compose.yml` 파일에는 이 경로의 절대 경로를 사용해야 합니다 (예: `/home/pi/mailserver`).

2. `docker-compose.yml` 파일 작성:

`docker-compose`를 사용하면 여러 옵션과 설정을 파일로 관리할 수 있어 편리합니다. `~/mailserver` 디렉토리 안에 `docker-compose.yml` 파일을 생성하고 다음 내용을 작성합니다. (예: `nano ~/mailserver/docker-compose.yml`)


version: '3.8'

services:
  mailserver:
    image: mailserver/docker-mailserver:latest
    container_name: mailserver_instance  # 컨테이너 이름을 원하는 대로 지정
    hostname: mail.aaaaa.org             # 1부에서 설정한 A 레코드의 호스트명
    domainname: aaaaa.org                # 여러분의 도메인 이름
    ports:
      - "25:25"      # SMTP
      - "143:143"    # IMAP (3부에서 사용)
      - "587:587"    # SMTP Submission (보안 연결용)
      - "993:993"    # IMAPS (3부에서 사용)
    volumes:
      - ./config:/tmp/docker-mailserver/  # 실제 절대 경로로 수정 필요
      - ./data:/var/mail/                 # 실제 절대 경로로 수정 필요
      - ./state:/var/mail-state/          # 실제 절대 경로로 수정 필요
      - /etc/localtime:/etc/localtime:ro
    environment:
      - ENABLE_SPAMASSASSIN=0            # 우선 비활성화 (4부에서 설정)
      - ENABLE_CLAMAV=0                  # 우선 비활성화 (4부에서 설정)
      - ENABLE_POSTGREY=0                # 우선 비활성화
      - ENABLE_FAIL2BAN=0                # 우선 비활성화
      - ONE_DIR=1
      - DMS_DEBUG=0                      # 디버그 로그 (0 또는 1)
      - TZ=Asia/Seoul                    # 타임존 설정
      # SSL 관련 설정은 초기에는 비워두거나 Let's Encrypt 설정을 비활성화합니다. (SSL_TYPE=manual, CERT_DOMAIN="")
      # 이 부분은 4부에서 자세히 다룹니다. 우선은 SSL 없이 테스트합니다.
      - SSL_TYPE=manual
      # - PERMIT_DOCKER=network # 필요시 내부 도커 네트워크에서 릴레이 허용
    cap_add:
      - NET_ADMIN # Fail2Ban 등에 필요할 수 있음 (우선 보류)
    restart: always

중요: `volumes` 항목의 `./config`, `./data`, `./state`는 `docker-compose.yml` 파일이 위치한 디렉토리 기준 상대 경로입니다. 만약 `~/mailserver` 디렉토리에서 `docker-compose up -d (에러시 docker compose up -d)` 를 실행한다면, 각각 `~/mailserver/config`, `~/mailserver/data`, `~/mailserver/state`를 의미합니다. 혼란을 피하려면 절대 경로로 명시하는 것이 좋습니다 (예: `/home/사용자명/mailserver/config`).

초기에는 스팸 필터, 바이러스 백신 등의 부가 기능은 `ENABLE_...=0`으로 설정하여 최소한의 기능으로 시작하고, 점차적으로 활성화하는 것이 문제 해결에 용이합니다. SSL 설정도 우선은 `manual`로 두고, 인증서 없이 시작하여 이후에 Let's Encrypt 등을 통해 설정할 것입니다.

3. 첫 번째 이메일 계정 생성:

컨테이너를 처음 실행하기 전에 메일 계정을 생성해야 합니다. `~/mailserver/config` 디렉토리에 `postfix-accounts.cf` 파일을 만들고 다음 형식으로 계정 정보를 추가합니다.


# nano ~/mailserver/config/postfix-accounts.cf

# 형식: user@domain.com|암호
user1@aaaaa.org|여러분의강력한비밀번호
admin@aaaaa.org|다른강력한비밀번호

`|` (파이프 문자)로 사용자명과 암호를 구분합니다. 암호는 반드시 강력한 것으로 설정하세요! 이 파일은 컨테이너가 시작될 때 읽어서 계정을 생성합니다.

⚠️ 주의하세요! 암호화되지 않은 비밀번호
`postfix-accounts.cf` 파일에 저장되는 비밀번호는 일반 텍스트입니다. `docker-mailserver`는 이 파일을 읽어 해시된 형태로 변환하여 사용하지만, 초기 설정 파일 자체는 일반 텍스트이므로 파일 권한 관리에 유의해야 합니다. 컨테이너 실행 후에는 이 파일의 내용을 직접 수정하기보다는 `setup.sh` 스크립트를 사용하는 것이 권장됩니다. (예: `docker exec -ti mailserver_instance setup email add user1@aaaaa.org new_password`)

4. Docker 컨테이너 실행:

`docker-compose.yml` 파일이 있는 `~/mailserver` 디렉토리로 이동한 후 다음 명령어로 컨테이너를 실행합니다.


cd ~/mailserver
docker-compose up -d (에러시 docker compose up -d)

`-d` 옵션은 백그라운드에서 실행하라는 의미입니다. 처음 실행 시에는 이미지를 다운로드하므로 시간이 다소 걸릴 수 있습니다.

5. 로그 확인:

컨테이너가 정상적으로 실행되고 있는지 로그를 확인합니다.


docker logs mailserver_instance
# 실시간 로그 확인:
# docker logs -f mailserver_instance

로그에 "Postfix is started" 와 같은 메시지가 보이고 특별한 에러가 없다면 성공입니다.

 

방화벽 및 포트 포워딩 설정 확인 🛡️

1부에서 언급했듯이, 외부에서 메일 서버로 접속하려면 공유기의 포트 포워딩 설정이 올바르게 되어 있어야 합니다. `docker-compose.yml`에서 설정한 포트들이 Banana Pi (192.168.0.60)로 전달되도록 공유기 설정을 다시 한번 확인해주세요.

  • 25번 포트: 다른 메일 서버와 통신(SMTP)
  • 587번 포트: 메일 클라이언트에서 메일 발송 시 사용 (SMTP Submission)

만약 Banana Pi에서 `ufw` 방화벽을 사용 중이라면, 이 포트들을 허용해야 합니다.


sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
# 3부에서 사용할 IMAP 포트도 미리 열어둘 수 있습니다.
# sudo ufw allow 143/tcp
# sudo ufw allow 993/tcp
sudo ufw enable # 방화벽 활성화 (이미 활성화 상태면 생략)
sudo ufw status

 

첫 이메일 발송 테스트! 📨

이제 설정한 메일 서버에서 외부로 이메일을 보내는 테스트를 해봅시다. Banana Pi에 `mailutils`를 설치하여 간단히 테스트할 수 있습니다.


sudo apt update
sudo apt install mailutils -y

다음 명령어로 테스트 메일을 발송합니다. `여러분의외부메일주소@example.com` 부분은 실제 사용하는 Gmail, Naver 등의 외부 메일 주소로 변경하고, `user1@aaaaa.org`는 위에서 생성한 계정으로 변경합니다.


echo "Banana Pi에서 보내는 테스트 메일입니다. 성공!" | mail -s "Banana Pi 메일 서버 테스트" -a "From: user1@aaaaa.org" 여러분의외부메일주소@example.com

발송 후, `docker logs mailserver_instance` 명령으로 로그를 확인하여 메일이 정상적으로 발송되었는지 (status=sent) 확인하고, 실제 외부 메일 계정에서 메일이 수신되었는지 확인합니다.

만약 메일이 도착하지 않는다면, 다음 사항들을 점검해보세요:

  • Cloudflare DNS 설정 (A, MX 레코드, 프록시 상태)
  • 공유기 포트 포워딩 설정 (특히 25번 포트)
  • Banana Pi 방화벽 설정 (`ufw status`)
  • `docker logs mailserver_instance` 로그의 에러 메시지
  • ISP에서 25번 포트를 차단했는지 여부 (이 경우 587번 포트를 사용하도록 설정을 변경해야 하며, 이는 다음 편에서 더 자세히 다룰 수 있습니다.)
  • 수신 측 메일 서비스의 스팸 필터 (스팸함 확인)
💡 `swaks`를 이용한 고급 테스트
`swaks` (Swiss Army Knife for SMTP)는 SMTP 테스트를 위한 강력한 도구입니다. `sudo apt install swaks`로 설치 후, 다음과 같이 테스트할 수 있습니다:
`swaks --to 여러분의외부메일주소@example.com --from user1@aaaaa.org --server mail.aaaaa.org` (또는 localhost) `-p 25` (또는 587)
인증이 필요하다면 `--auth PLAIN --auth-user user1@aaaaa.org --auth-password 여러분의강력한비밀번호` 옵션을 추가할 수 있습니다. `docker-mailserver`는 기본적으로 로컬 네트워크(Docker 내부 네트워크 포함)에서의 릴레이는 인증 없이 허용할 수 있습니다.

 

2부 마무리 및 다음 단계 예고 📝

축하드립니다! 이제 여러분의 Banana Pi M5는 이메일을 발송할 수 있는 기본적인 Postfix SMTP 서버를 갖추게 되었습니다. 아직 갈 길이 멀지만, 가장 큰 산 중 하나를 넘으셨어요. 😄

3부에서는 이메일을 수신하고, 사용자가 Outlook, Thunderbird 같은 메일 클라이언트나 웹메일을 통해 메일을 확인하고 관리할 수 있도록 해주는 Dovecot (IMAP/POP3 서버)을 `docker-mailserver` 환경 내에서 설정하고 연동하는 방법을 자세히 알아보겠습니다.

오늘 내용 중 어렵거나 궁금한 점이 있다면 주저 말고 댓글로 남겨주세요. 다음 편에서 뵙겠습니다! 👋

💡

2부 핵심 요약: Postfix & SMTP 설정

🤔 Postfix & SMTP: 이메일 전송 프로토콜(SMTP)과 메일 전송 에이전트(Postfix)의 역할 이해.
🐳 `docker-mailserver`: 올인원 Docker 이미지 선택 이유와 장점.
🛠️ 설치 및 설정: Docker 볼륨용 디렉토리 생성, `docker-compose.yml` 작성 (호스트명, 도메인명, 포트, 볼륨, 기본 환경변수 설정), `postfix-accounts.cf`로 계정 생성.
🚀 실행 및 테스트: `docker-compose up -d (에러시 docker compose up -d)`로 실행, 로그 확인, 방화벽/포트포워딩 (25, 587) 확인, `mailutils`로 발송 테스트.

자주 묻는 질문 (FAQ) ❓

Q: `docker-compose.yml` 파일에서 `hostname`과 `domainname`은 정확히 어떻게 설정해야 하나요?
A: 👉 `hostname`은 메일 서버의 전체 주소(FQDN)로, 1부에서 설정한 A 레코드의 이름(예: `mail.aaaaa.org`)을 사용합니다. `domainname`은 여러분의 도메인(예: `aaaaa.org`)을 사용합니다. 이 설정은 Postfix가 자신을 식별하는 데 사용됩니다.
Q: 메일 발송 테스트 시 "Relay access denied" 에러가 발생합니다.
A: 👉 이 에러는 Postfix가 해당 메일을 중계(relay)할 권한이 없다고 판단할 때 발생합니다. `docker-mailserver`는 기본적으로 인증된 사용자나 특정 네트워크에서의 발송을 허용합니다. 발신자 주소가 `postfix-accounts.cf`에 정의된 계정인지, 또는 `PERMIT_DOCKER` 환경변수 등을 올바르게 설정했는지 확인해보세요. 또한, 메일 클라이언트에서 587번 포트를 통해 SMTP 인증을 사용하는지 확인이 필요합니다. (이 부분은 추후 자세히 다룹니다)
Q: SSL/TLS 설정 없이 시작해도 괜찮나요?
A: 👉 초기 테스트 단계에서는 SSL/TLS 없이 시작하여 기본적인 메일 송수신 기능을 먼저 확인하는 것이 좋습니다. SSL/TLS 설정은 다소 복잡할 수 있으므로, 기본 기능이 정상 작동하는 것을 확인한 후 4부에서 Let's Encrypt를 이용해 안전한 암호화 통신을 설정할 예정입니다. 당장은 외부 메일 서버와 통신 시 암호화되지 않을 수 있다는 점만 인지해주세요.