개발노트

고즐의 개발 및 서버 개발 노트

Postfix와 OpenDKIM으로 no-reply 메일을 구성하며 남긴 설정 기록

# postfix설정 # opendkim설정 # smtp메일서버 # dkim # dmarc

Server 2026.01.08 3일 전 29 회 읽음


메일 발송 환경을 직접 구성하기로 했을 때, 처음부터 대량 발송이나 완성된 메일 서버를 염두에 두었던 것은 아니었다. 필요했던 것은 시스템 알림이나 인증 메일처럼, 정해진 용도로 안정적으로 발송되는 no-reply 메일 하나였다.

그래서 선택된 방향은 단순했다. 외부 SMTP를 연동하지 않고, 서버 내부에서 Postfix를 사용해 메일을 보내되 최소한의 신뢰 요소만 갖추는 방식이었다.


Postfix를 메일 발송 주체로 두는 구조

기본적인 전제는 이 서버가 메일을 “받는” 역할이 아니라, “보내는” 역할만 수행한다는 점이었다. IMAP이나 POP3 설정은 제외했고, 계정 생성 대신 alias 방식으로 no-reply 주소를 처리했다.

Postfix는 Rocky Linux 기본 저장소에서 설치했다.

dnf install postfix -y
systemctl enable --now postfix

이 시점에서 중요한 것은 메일이 스팸함으로 가느냐가 아니라, 우선 정상적으로 외부로 전달되는지였다. CLI에서 간단한 테스트 메일을 보내며 기본 동작을 확인했다.


no-reply 주소는 계정이 아니라 alias로 처리했다

메일 계정을 실제로 만들지 않고, no-reply@도메인 주소를 alias로 처리하는 방식은 구조를 단순하게 유지하는 데 도움이 됐다.

Webmin 환경에서는 Mail Aliases 메뉴를 통해 no-reply 주소를 개인 메일로 포워딩하도록 설정했다. 이 방식은 발송 전용 주소를 만들기에 충분해 보였다.



DKIM 설정은 Postfix가 아니라 OpenDKIM의 역할이었다

메일이 정상적으로 도착하더라도, 헤더를 확인해보면 DKIM 서명이 없다는 점이 바로 드러났다. 이 지점에서 Postfix 자체에는 DKIM 기능이 없다는 사실을 다시 확인하게 된다.

DKIM은 OpenDKIM이라는 별도의 서비스로 처리했다.

dnf install opendkim opendkim-tools -y

Rocky Linux 9 환경에서는 CRB 저장소 활성화와 추가 라이브러리 설치가 필요했다. 이 부분을 지나지 않으면 OpenDKIM 설치 단계에서 멈추게 된다.



DKIM 키 생성과 DNS 등록 흐름

키는 도메인 단위로 생성했고, 관리 경로는 명확하게 구분했다.

mkdir -p /etc/opendkim/keys/goz.kr
opendkim-genkey -b 2048 -d goz.kr -s default -D /etc/opendkim/keys/goz.kr
chown -R opendkim:opendkim /etc/opendkim/keys
chmod 600 /etc/opendkim/keys/goz.kr/default.private

이 과정에서 생성된 default.txt 파일의 내용은 도메인 DNS 관리자 페이지에 TXT 레코드로 등록했다.

이름은 default._domainkey 형태로 입력했고, 값에는 공개키 문자열만 한 줄로 정리해 넣었다. 처음에는 다소 낯설게 느껴졌지만, 결국 이는 메일 인증을 위한 하나의 서브도메인일 뿐이었다.



OpenDKIM과 Postfix를 연결하는 단계

키와 DNS가 준비된 이후에는 OpenDKIM이 실제로 서명을 수행할 수 있도록 설정 파일을 정리했다.

Syslog                  yes
Canonicalization        relaxed/simple
Mode                    sv
Domain                  goz.kr
Selector                default
KeyFile                 /etc/opendkim/keys/goz.kr/default.private
Socket                  local:/run/opendkim/opendkim.sock
UserID                  opendkim:opendkim

소켓 디렉터리는 직접 생성해 권한을 맞췄다.

mkdir -p /run/opendkim
chown opendkim:opendkim /run/opendkim
chmod 755 /run/opendkim

Postfix 설정 파일에는 milter 항목을 추가해 OpenDKIM과의 연결을 명시했다.

milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/run/opendkim/opendkim.sock



정상 기동 여부는 헤더로 확인했다

서비스를 재시작한 뒤, 테스트 메일을 보내고 메일 헤더를 확인했다.

dkim=pass라는 결과가 표시되는 순간, 비로소 메일 서버가 신뢰 흐름에 편입되었다는 느낌이 들었다. 메일은 그 전에도 도착했지만, 이제는 “도착한 이유”가 설명되는 상태가 된 셈이다.



PHP에서는 mail 함수만으로 충분했다

외부 SMTP 라이브러리를 사용하지 않고, PHP의 기본 mail 함수를 그대로 사용했다. Postfix와 OpenDKIM이 이미 서버 단에서 처리하고 있었기 때문이다.

From 헤더에 표시명을 추가하면서, 받는 사람의 메일함에는 고즐 <no-reply@도메인> 형태로 표시되도록 했다.

이 구조는 대량 발송을 위한 것은 아니지만, 시스템 알림이나 인증 메일 용도로는 충분해 보인다.


귀찮아졌다는 감각의 정체

설정이 많아서라기 보다는, 메일이라는 매체가 요구하는 신뢰가 두텁다는 점이 이 작업을 귀찮게 느끼게 만드는 듯했다.

한 번 이 흐름을 따라가고 나니, 외부 SMTP를 선택하는 이유도, 직접 구성하는 선택의 의미도 조금 더 분명해진 느낌이다.

문의답변