본 포스팅은 Rocky Linux 9 환경에서 1인 관리자 전용 기술 블로그와 프라이빗 메일 계정 관리 포털을 함께 구축하고, 트러블슈팅 및 성능·보안 고도화, 전 세계 도메인 전파까지 완료한 전 과정을 정리한 엔지니어링 일지입니다.
1. 인프라 아키텍처 및 목표
기존에 구축된 메일 서브시스템(Postfix, Dovecot, MariaDB)과 공존하면서, 단일 서버(Rocky Linux 9.8 AArch64) 자원을 효율적으로 활용하는 1인 폐쇄형 기술 블로그(mgklab.co.kr)를 배포하는 것을 목표로 하였습니다.
- OS: Rocky Linux 9.8 (Blue Onyx)
- 웹 서버: Nginx 1.20.1 (Reverse Proxy & FastCGI)
- 애플리케이션: PHP-FPM 8.3.36 (최신 업그레이드) + WordPress 6.7
- 데이터베이스: MariaDB 10.5 (메일 DB:
mailserver, 블로그 DB:blogdb) - 인증서: Let’s Encrypt Wildcard (
*.mgklab.co.kr,mgklab.co.kr)
2. 메일 포털 트러블슈팅: 패스워드 암호화 버그 해결
메일 계정 생성 포털(mail.mgklab.co.kr)에서 신규 계정 생성 후 탈퇴(삭제)를 시도할 때, 정확한 비밀번호를 입력해도 “비밀번호가 올바르지 않습니다”라는 오류가 발생하는 현상이 있었습니다.
원인 분석
데이터베이스(virtual_users)를 조회한 결과, 패스워드 컬럼에 정상 해시가 아닌 {SHA512-CRYPT}*0이라는 비정상 값이 저장되어 있었습니다.
// 기존 문제 코드 (index.php)
$raw_hash = crypt($password, "$6$rounds=5000$" . $salt . "$");
원인은 PHP의 문자열 평가 방식이었습니다. 큰따옴표("...") 내부의 $rounds가 미정의 변수로 평가되어 빈 문자열로 치환되었고, 이로 인해 crypt() 함수에 잘못된 솔트가 전달되어 실패 반환값인 *0이 저장되었던 것입니다.
조치 및 해결
솔트 문자열을 변수 해석이 발생하지 않는 작은따옴표('...')로 교체하고, 탈퇴 시 Maildir 디스크 데이터 영구 파기(sudo rm -rf)를 위한 Nginx 권한을 보완하였습니다.
// 수정 완료 코드
$raw_hash = crypt($password, '$6$rounds=5000$' . $salt . '$');
$dovecot_hash = "{SHA512-CRYPT}" . $raw_hash;
3. 메일 포털 UI/UX 현대화 (Gmail / 네이버 스타일)
기존 투박했던 메일 생성 및 탈퇴 폼을 상용 포털 수준의 세련된 인터페이스로 전면 리뉴얼하였습니다:
- 비밀번호 눈 아이콘 토글: 모든 암호 필드(초대 코드, 비밀번호, 확인란)에 표시/숨김 버튼 탑재
- 실시간 보안 피드백: 3단계 비밀번호 강도 컬러 게이지 및 실시간 일치 검증 피드백 적용
- 신뢰도 높은 탈퇴 프로세스: 네이버/구글 표준 약관 카드 스타일 적용 및 안전한 데이터 파기 동의 절차 구축
4. 티스토리형 기술 블로그 배포 및 1인 폐쇄 운영
서구형 풀페이지 블록 위주의 워드프레스 기본 테마 대신, 한국 개발자들에게 가장 익숙한 티스토리(북클럽/오디세이) 스타일로 환경을 구성하였습니다.
- 테마: 초경량 고속 테마인
GeneratePress적용 (중앙 피드 + 우측 프로필/카테고리 사이드바) - 코드 문법 강조: 개발자 필수 도구인
Enlighter활성화로 Python, Java, Shell, SQL 등 코드 하이라이팅 지원 - 자동 목차: 긴 기술 글 작성을 위한
LuckyWP Table of Contents연동 - 1인 폐쇄 정책: 일반 회원가입(
users_can_register: 0) 차단 및wp-config.php,xmlrpc.php접근 전면 차단
5. 성능 및 보안 스택 고도화
PHP 8.3 최신 엔진 업그레이드
Rocky Linux 기본 저장소의 EOL된 PHP 8.0 대신, 최신 취약점이 모두 해결된 PHP 8.3.36 (Remi 저장소)으로 무중단 업그레이드를 완료하였습니다.
Cloudflare DNS 연동 와일드카드 SSL 발급
기존 메일 전용 단일 인증서(mail.mgklab.co.kr)로 인해 발생하던 루트 도메인(mgklab.co.kr) SSL 도메인 불일치(주의 요함) 현상을 해결하기 위해, Cloudflare DNS-01 API를 연동하여 와일드카드(*.mgklab.co.kr 및 mgklab.co.kr) 인증서를 발급하고 HSTS 강력 보안 헤더를 Nginx에 적용하였습니다.
6. Cloudflare DNS 및 포트포워딩 트러블슈팅
도메인 연동 중 루트 도메인(mgklab.co.kr)으로의 외부 접속이 실패하던 현상을 추적한 결과, Cloudflare DNS 관리 대시보드에 mail 서브도메인만 등록되어 있고 루트 도메인(@)과 www의 A 레코드가 누락되어 있음을 확인하였습니다.
- Cloudflare API를 통한 레코드 자동 주입: 루트 도메인
A레코드 및wwwCNAME 레코드를 현재 공인 IP(183.107.199.88)로 전 세계 DNS에 즉시 전파 완료. - 공유기 포트포워딩 최적화: 보안상 매우 취약한 DMZ 전체 개방 대신, 정석대로 웹 서비스용 TCP 80(HTTP 자동 리다이렉트) 및 TCP 443(HTTPS 암호화) 포트만 핀포인트로 개방하여 외부 모바일(LTE/5G) 접속 완벽 검증 완료.
7. 향후 로드맵: Git 기반 블로그 연동
향후에는 로컬 VS Code에서 마크다운(.md)으로 글을 작성하고 git push 시 GitHub Actions를 통해 본 서버로 자동 배포되는 Astro / Hugo 기반 정적 기술 블로그 파이프라인 구축을 검토할 예정입니다.