Ghost Admin 로그인 안 될 때 — 기기 인증(2FA) 이메일 설정으로 해결하기
Docker로 셀프호스팅 중인 Ghost 블로그(ghost:6-alpine)에서 관리자(admin) 로그인이 막혀 원인을 추적하고 해결한 과정을 정리합니다.
증상
/ghost/관리자 페이지 접속 시 아래와 같은 에러가 노출됨
{
"errors": [
{
"message": "Authorization failed",
"context": "Unable to determine the authenticated user or integration. Check that cookies are being passed through if using session authentication.",
"type": "NoPermissionError"
}
]
}
- 시크릿 모드로 접속해도 동일한 메시지가 반복됨
원인 파악
- 이 에러 자체는 로그인 실패의 직접적인 원인이 아니었습니다. 컨테이너 로그(
docker compose logs ghost)를 실시간으로 확인해보니, 이 메시지는/ghost/페이지가 로드될 때 "현재 로그인된 사용자가 있는지" 확인하는 백그라운드 API(GET /ghost/api/admin/users/me/)가 세션 쿠키 없이 호출되며 발생하는 정상적인 사전 체크였습니다. - 진짜 원인은 두 가지였습니다.
- Ghost 5.118+ 에 추가된 Staff Device Verification(기기 인증) 보안 기능 — 새 기기/IP에서 로그인 시 등록된 이메일로 인증 코드를 보내는데, SMTP(메일 발송) 설정이 없어서 코드가 발송되지 않아 로그인이 끝까지 진행되지 못함
- 실제 로그 확인 결과 별도로
PASSWORD_INCORRECT(비밀번호 오류)도 함께 있었음 — 즉 기기 인증 이슈와 비밀번호 분실 이슈가 겹쳐 있던 상황
해결 단계
1. Gmail SMTP 연동
Gmail로 메일을 발송하려면 일반 비밀번호가 아닌 앱 비밀번호(App Password)가 필요합니다 (2단계 인증 활성화 후 발급).
민감 정보는 docker-compose.yml에 직접 적지 않고, 같은 디렉토리의 .env 파일로 분리해 Compose의 변수 치환(${VAR}) 기능을 사용했습니다. .env는 chmod 600으로 권한을 제한합니다.
.env (예시 — 실제 값은 비공개):
[email protected]
GHOST_MAIL_PASS=xxxxxxxxxxxxxxxx # Gmail 앱 비밀번호, 공백 제거
docker-compose.yml 일부:
services:
ghost:
image: ghost:6-alpine
restart: unless-stopped
ports:
- "2368:2368"
environment:
url: https://blog.example.com
database__client: sqlite3
database__connection__filename: /var/lib/ghost/content/data/ghost.db
mail__transport: SMTP
mail__from: '"My Blog" <[email protected]>'
mail__options__service: Gmail
mail__options__auth__user: ${GHOST_MAIL_USER}
mail__options__auth__pass: ${GHOST_MAIL_PASS}
volumes:
- ./content:/var/lib/ghost/content
2. 기기 인증 기능 임시 비활성화로 응급 처치 (선택)
SMTP 설정 전 급하게 로그인이 필요하다면 아래 옵션으로 기능을 잠시 끌 수 있습니다. 다만 프로덕션/외부 노출 사이트에는 비권장(보안 계층 약화).
environment:
security__staffDeviceVerification: "false"
SMTP 설정이 끝나면 이 줄을 제거해 기본값(true, 기능 활성화)으로 되돌립니다.
3. 트러블슈팅: 535-5.7.8 Username and Password not accepted
Gmail 앱 비밀번호 인증이 거부된 경우 점검 목록:
- 해당 Gmail 계정에 2단계 인증이 켜져 있는지 (꺼져 있으면 앱 비밀번호 자체가 무효)
- 앱 비밀번호를 다른 계정용으로 발급받아 잘못 전달하지 않았는지 (메일 발신 계정과 앱 비밀번호 발급 계정이 일치해야 함)
- 복사 시 공백/오타 여부
4. 비밀번호 재설정
SMTP가 정상화된 후 로그인 화면의 "Forgot password?" 로 재설정 메일을 받아 admin 비밀번호를 복구했습니다.
정리
| 항목 | 내용 |
|---|---|
| 증상 | Admin 로그인 실패, 쿠키/세션 에러 노출 |
| 1차 원인 | Staff Device Verification 기능에 필요한 SMTP 미설정 |
| 2차 원인 | Admin 비밀번호 분실 |
| 해결 | Gmail SMTP(앱 비밀번호) 연동 → 기기 인증 정상화 → 비밀번호 재설정 메일로 복구 |
| 보안 메모 | 자격증명은 docker-compose.yml이 아닌 .env(권한 600)로 분리 보관 |