블로그를 인터넷에 공개한 뒤 가장 먼저 든 생각은 관리자 화면이었다. 글은 누구나 읽어야 하지만 로그인 화면까지 같은 입구에 둘 필요는 없었다. 공개 블로그와 관리 경로를 나누는 일을 이번 구성의 기본 보안선으로 잡았다.
공개 주소는 Cloudflare Tunnel로 연결했다
Cloudflare Tunnel은 NAS에서 Cloudflare 쪽으로 연결을 시작한다. 공유기에 포트 포워딩을 추가하지 않아도 도메인 요청을 WordPress 컨테이너로 보낼 수 있었다. 외부에서 NAS의 80번과 443번 포트를 직접 찾을 수 없게 하고, 도메인과 인증서 관리는 Cloudflare에 맡겼다.
처음에는 임시 상태 페이지도 별도 컨테이너로 띄워 두었다. 블로그가 정상적으로 열리는 것만으로 NAS와 Tunnel의 상태를 어느 정도 확인할 수 있게 된 뒤에는 status 페이지와 관련 컨테이너를 정리했다. 서비스를 하나 줄이면 업데이트하고 감시할 대상도 하나 줄어든다.
관리자 화면은 Tailscale 안으로 옮겼다
공개 도메인에서 WordPress 관리자 경로로 들어오는 요청은 막고, 집 안의 네트워크나 Tailscale로 NAS에 연결했을 때만 로그인할 수 있게 했다. 외부에서 글을 읽는 경로와 내가 관리하는 경로가 분리된 셈이다.
Tailscale 주소로 접속하면 NAS와 같은 사설 환경에서 WordPress 관리자 화면을 열 수 있다. 별도의 인증 키를 환경 파일에 계속 보관하는 방식은 쓰지 않았다. 일반적인 사용에서는 기기 로그인 상태로 충분했고, 재인증이 필요해지면 그때 다시 승인하는 편이 장기 키를 남겨 두는 것보다 단순했다.
인사이트 전달 경로는 별도로 확인했다
관리자 화면을 막으면 끝이라고 생각했지만 Hermes가 정리한 인사이트를 WordPress 작업 화면에서 참고하려면 API 경로는 동작해야 했다. 사람의 로그인 화면과 자동화가 쓰는 요청을 같은 규칙으로 막으면 참고 자료를 전달하는 과정도 실패한다. 실제로 공개 처리 과정에서 서버의 올바른 응답을 받지 못했다는 오류를 만났다.
이 문제를 풀 때는 차단 규칙을 무작정 풀지 않았다. WordPress가 요구하는 API 요청과 인증 방식을 확인하고, 자동화 계정에는 필요한 권한만 줬다. 브라우저 관리자 접근은 계속 Tailscale 안에 두고 자동화가 쓰는 좁은 경로만 점검했다.
SSH는 상시 관리 통로로 두지 않았다
설정 중에는 SSH가 필요했다. 컨테이너 로그와 파일 권한을 확인하고, 사용자를 Docker 그룹에 넣고, 구성 파일이 실제로 반영됐는지 봐야 했다. 작업이 끝난 뒤에는 SSH를 다시 껐다. 필요할 때 잠깐 여는 방식이 조금 번거롭지만 지금 규모의 개인 NAS에는 잘 맞았다.
이 구성에서 가장 마음에 드는 건 공개 범위를 쉽게 설명할 수 있다는 점이다. 방문자는 Cloudflare를 거쳐 블로그를 보고, 나는 Tailscale 안에서 관리한다. Hermes는 별도 자격 증명으로 참고할 인사이트만 전달한다. 역할이 나뉘니 문제가 생겼을 때 확인할 지점도 선명해졌다.