Ghost Admin 로그인 안 될 때 — 기기 인증(2FA) 이메일 설정으로 해결하기

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"
    }
  ]
}
  • 시크릿 모드로 접속해도 동일한 메시지가 반복됨

원인 파악

  1. 이 에러 자체는 로그인 실패의 직접적인 원인이 아니었습니다. 컨테이너 로그(docker compose logs ghost)를 실시간으로 확인해보니, 이 메시지는 /ghost/ 페이지가 로드될 때 "현재 로그인된 사용자가 있는지" 확인하는 백그라운드 API(GET /ghost/api/admin/users/me/)가 세션 쿠키 없이 호출되며 발생하는 정상적인 사전 체크였습니다.
  2. 진짜 원인은 두 가지였습니다.
    • Ghost 5.118+ 에 추가된 Staff Device Verification(기기 인증) 보안 기능 — 새 기기/IP에서 로그인 시 등록된 이메일로 인증 코드를 보내는데, SMTP(메일 발송) 설정이 없어서 코드가 발송되지 않아 로그인이 끝까지 진행되지 못함
    • 실제 로그 확인 결과 별도로 PASSWORD_INCORRECT (비밀번호 오류)도 함께 있었음 — 즉 기기 인증 이슈와 비밀번호 분실 이슈가 겹쳐 있던 상황

해결 단계

1. Gmail SMTP 연동

Gmail로 메일을 발송하려면 일반 비밀번호가 아닌 앱 비밀번호(App Password)가 필요합니다 (2단계 인증 활성화 후 발급).

민감 정보는 docker-compose.yml에 직접 적지 않고, 같은 디렉토리의 .env 파일로 분리해 Compose의 변수 치환(${VAR}) 기능을 사용했습니다. .envchmod 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)로 분리 보관

Subscribe for daily recipes. No spam, just food.