Files
tk-factory-services/ntfy/README.md
Hyungi Ahn e50ff3fb63 feat(ntfy): 푸시 알림 서버 Phase 1 인프라 구축
- docker-compose.yml에 ntfy 서비스 추가 (포트 30750)
- ntfy/etc/server.yml 서버 설정 (인증 deny-all, 72h 캐시)
- ntfy/README.md 운영 매뉴얼

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 10:24:09 +09:00

5.2 KiB

ntfy 푸시 알림 서버 — 운영 매뉴얼

개요

ntfy는 Web Push(VAPID)의 iOS 제한, 전송 보장 부재 등을 보완하는 푸시 알림 채널이다. 모바일 ntfy 앱으로 알림을 수신하고, 탭하면 딥링크로 해당 페이지로 이동한다.

  • Docker 서비스명: ntfy
  • 내부 URL: http://ntfy:80 (Docker 네트워크)
  • 외부 URL: https://ntfy.technicalkorea.net (Cloudflare Tunnel)
  • 호스트 포트: 30750
  • 설정 파일: ntfy/etc/server.yml
  • 데이터: ntfy_cache Docker 볼륨 (/var/cache/ntfy)

초기 설정 (최초 1회)

1. Cloudflare Tunnel 설정

Zero Trust 대시보드 → Tunnels → Public Hostname 추가:

Subdomain Domain Service
ntfy technicalkorea.net http://ntfy:80

2. 컨테이너 기동

docker compose up -d ntfy

3. 관리자 계정 + 토큰 발급

# 관리자 계정 생성 (비밀번호 입력 프롬프트)
docker exec -it tk-ntfy ntfy user add --role=admin admin

# API 토큰 발급
docker exec -it tk-ntfy ntfy token add admin
# 출력 예: tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2

4. .env에 토큰 설정

NTFY_PUBLISH_TOKEN=<위에서 발급받은 토큰>

메시지 발행 (서버 → 사용자)

curl로 테스트

# 기본 메시지
curl -H "Authorization: Bearer $NTFY_PUBLISH_TOKEN" \
     -d "테스트 메시지입니다." \
     http://localhost:30750/tkfactory-test

# 제목 + 딥링크 포함
curl -H "Authorization: Bearer $NTFY_PUBLISH_TOKEN" \
     -H "Title: 설비수리 요청" \
     -H "Tags: wrench" \
     -H "Click: https://tkfb.technicalkorea.net/pages/admin/repair-management.html" \
     -d "A동 CNC 설비 수리 요청이 접수되었습니다." \
     http://localhost:30750/tkfactory-user-1

# 우선순위 높은 알림 (5=max, 3=default, 1=min)
curl -H "Authorization: Bearer $NTFY_PUBLISH_TOKEN" \
     -H "Title: 긴급 안전 알림" \
     -H "Priority: 5" \
     -H "Tags: warning" \
     -d "즉시 확인이 필요합니다." \
     http://localhost:30750/tkfactory-user-1

토픽 네이밍 규칙

토픽 용도
tkfactory-user-{userId} 사용자별 개인 알림 (Phase 2에서 사용)
tkfactory-test 테스트용

주요 헤더

헤더 설명 예시
Title 알림 제목 설비수리 요청
Click 탭 시 열릴 URL (딥링크) https://tkfb.technicalkorea.net/pages/work/tbm.html
Tags 이모지 태그 (목록) wrench, warning, white_check_mark
Priority 1(min) ~ 5(max) 5
Authorization 인증 토큰 Bearer tk_...

사용자 관리

# 사용자 목록
docker exec tk-ntfy ntfy user list

# 일반 사용자 추가
docker exec -it tk-ntfy ntfy user add username

# 사용자 삭제
docker exec tk-ntfy ntfy user del username

# 특정 토픽 접근 권한 부여 (read-write / read-only / write-only)
docker exec tk-ntfy ntfy access username 'tkfactory-user-*' read-only

# 토큰 발급
docker exec tk-ntfy ntfy token add username

# 토큰 목록
docker exec tk-ntfy ntfy token list

# 토큰 삭제
docker exec tk-ntfy ntfy token remove username tk_...

모바일 앱 설정 (수신자용)

Android

  1. Play Store에서 ntfy 설치
  2. 설정(⚙️) → Default serverhttps://ntfy.technicalkorea.net 입력
  3. 우측 상단 사용자 아이콘 → 로그인 (발급받은 계정/비밀번호 또는 토큰)
  4. + → 토픽 tkfactory-user-{본인userId} 구독

iOS

  1. App Store에서 ntfy 설치
  2. Settings → Default serverhttps://ntfy.technicalkorea.net 입력
  3. 로그인 후 토픽 구독 (Android와 동일)

서버 설정 (server.yml)

항목 현재 값 설명
auth-default-access deny-all 인증 없이 접근 불가
cache-duration 72h 메시지 보관 기간 (주말 포함 3일)
visitor-request-limit-burst 60 버스트 요청 한도
visitor-request-limit-replenish 5s 요청 한도 보충 주기

설정 변경 후 컨테이너 재시작:

docker compose restart ntfy

트러블슈팅

401 Unauthorized

  • 토큰이 맞는지 확인: docker exec tk-ntfy ntfy token list
  • auth-default-access: deny-all 상태에서 토큰 없이 요청하면 발생

모바일 앱에서 알림이 안 옴

  • Cloudflare Tunnel Public Hostname에 ntfy.technicalkorea.net 등록되었는지 확인
  • 앱의 Default server URL이 https://ntfy.technicalkorea.net인지 확인
  • 앱에서 로그인했는지, 토픽을 구독했는지 확인
  • 폰 설정에서 ntfy 앱 알림 권한이 켜져 있는지 확인

컨테이너 로그 확인

docker logs tk-ntfy --tail 50
docker logs tk-ntfy -f  # 실시간

Phase 2 예정 사항 (참고)

  • system1-factory/api/models/notificationModel.jssendPushToUsers()에서 ntfy 발송 연동
  • push_subscriptions 테이블에 channel 컬럼 추가 (web_push | ntfy)
  • ntfy 구독 사용자에게는 Web Push 미발송 (중복 방지)
  • notification-bell.js에서 ntfy 구독 토글 UI 추가