전 직원 전환 전에 서버가 스스로 지키고 되살릴 수 있게 했다.
- 관리자 단단히(setup): 관리자 역할에서 impersonate 를 빼고 관리자 허용 IP 를 앱 네트워크로 — 관리자 비밀번호로 바깥 993 · JMAP 에서 직원 메일함에 대리 로그인되던 길을 막았다.
운영에서 처음 걸 때는 되돌릴 복구 관리자가 있을 때만 건다(관리자 잠김 방지).
- 휴지통 · 스팸 30일 정리를 KST 03:00 으로 명시. imapsync 로 옮긴 메일도 옮긴 때부터 센다(임시 엔진 실측).
- restic 백업(호스트 systemd 03:30 — 메일 볼륨 warm → 엔진 멈춤 9초 안팎 → final, pg_dump, 업로드, env) · 복원(새 서버 차례를 빈 클론에서 실측) · 15분 점검 · 부팅 되살리기, Healthchecks 하트비트.
- 메일 프로그램 자동 설정: frontend nginx 의 autoconfig · autodiscover 고정 응답(엔진 것은 POP3 를 알리고 입력을 되돌려 쓴다).
- 모든 서비스 docker 로그 보존, DB 이미지 판 · digest 고정.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
운영 메일 서버를 NCP 에 따로 두고, 포털의 TLS 는 기존 서버의 Nginx Proxy Manager(다른 사이트들과 80 · 443 을 함께 쓴다)가
같은 VPC 사설망으로 넘기기로 했다. 메일 엔진이 그 서버의 443 을 직접 써야 해서(ACME · MTA-STS) 프록시를 같은 호스트에 둘 수 없다.
- docker-compose.remote-proxy.yml: frontend 를 proxy 네트워크에서 빼고 8080 을 FRONTEND_PRIVATE_BIND(사설 IPv4:포트)에만 게시한다.
compose 의 ${…:?} 는 빈 값만 막아 포트뿐인 값이면 모든 주소에 열리므로, 한 번짜리 frontend-bind-check 가 값을 먼저 보고
아니면 frontend 를 띄우지 않는다(네트워크 없음 · 비-root · DB 이미지의 셸).
- .env.production 의 COMPOSE_FILE 로 켠다 — 운영 명령(--env-file .env.production)을 그대로 쓰고 -f 를 빠뜨려 기본 구성으로 도는 일이 없게.
- TRUST_PROXY 는 <EDGE_NETWORK_SUBNET>,<프록시 서버 사설 IP> 주소 목록, NPM 은 v2.16.0 소스로 기본값을 확인해 고급 칸 세 줄
(읽기 150s · 접근 로그 끔 · 사설 대역의 X-Real-IP 믿지 않기)과 Block Common Exploits 끄기(메일 검색이 403)를 적었다.
- NCP 는 공인 IP 를 사설 IP 로 NAT 하므로 게시 주소로는 바깥을 막지 못한다 — 8080 은 ACG 가 프록시 서버 사설 IP 에서만 받는다.
- CI infra 잡이 이 조합의 config 와 frontend-bind-check 의 받을 값 · 거절할 값을 본다.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>