Moving from Synology Reverse Proxy to Nginx Proxy Manager

Moving from Synology Reverse Proxy to Nginx Proxy Manager

πŸ“‹ κ°œμš”

기쑴에 μ‹œλ†€λ‘œμ§€ NAS의 λ‚΄μž₯ μ—­λ°©ν–₯ ν”„λ‘μ‹œμ™€ Let's Encrypt μΈμ¦μ„œλ‘œ μš΄μ˜ν•˜λ˜ μ„œλΉ„μŠ€λ“€μ„ λ³„λ„μ˜ NPM(Nginx Proxy Manager)으둜 톡합 κ΄€λ¦¬ν•˜λŠ” 과정을 κΈ°λ‘ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ—οΈ κΈ°μ‘΄ ν™˜κ²½

  • NAS1 (192.168.1.13): μ‹œλ†€λ‘œμ§€ 메인 μ„œλ²„
  • Let's Encrypt SSL μΈμ¦μ„œ 관리
  • μ‹œλ†€λ‘œμ§€ λ‚΄μž₯ μ—­λ°©ν–₯ ν”„λ‘μ‹œλ‘œ μ„œλΈŒλ„λ©”μΈ 관리
  • 곡유기 ν¬νŠΈν¬μ›Œλ”©: 80/443 β†’ NAS1
  • NAS2 (192.168.1.158): μƒˆλ‘œμš΄ NPM μ „μš© μ„œλ²„

🎯 λͺ©ν‘œ ν™˜κ²½

  • NAS1: λ‚΄λΆ€ μ„œλΉ„μŠ€λ§Œ λ‹΄λ‹Ή
  • NAS2: NPM으둜 λͺ¨λ“  μ™ΈλΆ€ νŠΈλž˜ν”½ 처리 및 SSL 관리
μ™€μΌλ“œμΉ΄λ“œ * μ‚¬μš©ν•˜μ‹ λ‹€λ©΄ κΌ­ μ•„λž˜ ν•„μˆ˜ 섀정을 ν•˜μ„Έμš”.

πŸš€ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ κ³Όμ •

1단계: κΈ°μ‘΄ μ„€μ • λ°±μ—…

NAS1μ—μ„œ λ°±μ—…ν•œ 정보:

  • κΈ°μ‘΄ μ—­λ°©ν–₯ ν”„λ‘μ‹œ κ·œμΉ™ 전체 λͺ©λ‘
  • 각 μ„œλΈŒλ„λ©”μΈλ³„ μ—°κ²° 정보 (포트, μ„œλΉ„μŠ€)
  • Let's Encrypt μΈμ¦μ„œ λͺ©λ‘

2단계: NPM μ„€μΉ˜ 및 μ„€μ •

Portainer Stack을 μ΄μš©ν•œ NPM μ„€μΉ˜:

version: "3.8"
services:
  npm:
    container_name: npm
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '380:80'    # HTTP (κΈ°λ³Έ 80μ—μ„œ λ³€κ²½)
      - '3443:443'  # HTTPS (κΈ°λ³Έ 443μ—μ„œ λ³€κ²½)  
      - '381:81'    # 관리 νŽ˜μ΄μ§€
    environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"
      DISABLE_IPV6: 'true'
    volumes:
      - /volume1/docker/npm/data:/data
      - /volume1/docker/npm/letsencrypt:/etc/letsencrypt
    depends_on:
      - db
    networks:
      - npm-network

  db:
    container_name: npm-db
    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
      TZ: 'Asia/Seoul'
    volumes:
      - /volume1/docker/npm/db:/var/lib/mysql
    networks:
      - npm-network

networks:
  npm-network:
    driver: bridge

포트 λ³€κ²½ 이유:

  • μ‹œλ†€λ‘œμ§€ μ›Ή μ„œλ²„μ™€ 포트 좩돌 λ°©μ§€
  • 380/3443 포트둜 λ³€κ²½ν•˜μ—¬ μ•ˆμ •μ„± 확보

3단계: Cloudflare APIλ₯Ό μ΄μš©ν•œ μ™€μΌλ“œμΉ΄λ“œ SSL μΈμ¦μ„œ λ°œκΈ‰

Cloudflare API 토큰 생성:

  • Zone:Zone:Read + Zone:DNS:Edit κΆŒν•œ
  • ν•΄λ‹Ή λ„λ©”μΈμ—λ§Œ μ œν•œ

DNS에 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” cnameλ ˆμ½”λ“œλŠ” μ „λΆ€ μ§€μš΄λ‹€.

NPMμ—μ„œ μ™€μΌλ“œμΉ΄λ“œ μΈμ¦μ„œ λ°œκΈ‰:

  • Domain: *.abc.com, abc.com
  • DNS Challenge: Cloudflare
  • API 토큰 μž…λ ₯으둜 μžλ™ 인증

4단계: 곡유기 ν¬νŠΈν¬μ›Œλ”© λ³€κ²½

κΈ°μ‘΄: μ™ΈλΆ€ 80 β†’ 192.168.1.13:80 μ™ΈλΆ€ 443 β†’ 192.168.1.13:443

λ³€κ²½ ν›„: μ™ΈλΆ€ 80 β†’ 192.168.1.158:380 μ™ΈλΆ€ 443 β†’ 192.168.1.158:3443

5단계: SSL λ¦¬λ‹€μ΄λ ‰μ…˜ 루프 문제 ν•΄κ²°

문제점:

  • Cloudflare ν”„λ‘μ‹œ(🟠)와 NPM Force SSL이 λ™μ‹œμ— μž‘λ™ν•˜λ©΄ λ¬΄ν•œ λ¦¬λ‹€μ΄λ ‰μ…˜ λ°œμƒ

해결방법:

  • Cloudflare DNS λ ˆμ½”λ“œλ₯Ό λͺ¨λ‘ DNS만(πŸ”˜) μ„€μ •μœΌλ‘œ λ³€κ²½
  • NPMμ—μ„œ Force SSL ν™œμ„±ν™”ν•˜μ—¬ SSL λ¦¬λ‹€μ΄λ ‰μ…˜ 처리

6단계: κΈ°μ‘΄ ν™˜κ²½ 정리

NAS1μ—μ„œ μ œκ±°ν•œ ν•­λͺ©:

  • Let's Encrypt μΈμ¦μ„œ μ‚­μ œ
  • λͺ¨λ“  μ—­λ°©ν–₯ ν”„λ‘μ‹œ κ·œμΉ™ μ‚­μ œ
  • μ‹œλ†€λ‘œμ§€ κΈ°λ³Έ μΈμ¦μ„œλ‘œ μž¬λ°œκΈ‰ (λ‚΄λΆ€ μ ‘μ†μš©)

βš™οΈ μ„œλΉ„μŠ€λ³„ NPM μ„€μ • ꢌμž₯사항

NAS1 (192.168.1.13) μ„œλΉ„μŠ€

μ„œλΉ„μŠ€ Cache Assets Block Common Exploits WebSocket Support λΉ„κ³ 
Nextcloud βœ… βœ… βœ… 파일 동기화 + μ‹€μ‹œκ°„ μ•Œλ¦Ό
Memos βœ… βœ… βœ… λ…ΈνŠΈ μ•±, μ‹€μ‹œκ°„ 동기화
Transmission βœ… ❌ βœ… ν† λ ŒνŠΈ μ›ΉUI, API 호좜 많음
Vaultwarden ❌ βœ… βœ… λ³΄μ•ˆ μ€‘μš”, 캐싱 μœ„ν—˜
Watchtower ❌ ❌ ❌ μ»¨ν…Œμ΄λ„ˆ μžλ™ μ—…λ°μ΄νŠΈ 도ꡬ

μ‹œλ†€λ‘œμ§€ λ‚΄μž₯ μ„œλΉ„μŠ€

μ„œλΉ„μŠ€ Cache Assets Block Common Exploits WebSocket Support λΉ„κ³ 
Synology Drive βœ… ❌ βœ… 파일 동기화, API 호좜 많음
Synology Chat ❌ βœ… βœ… μ‹€μ‹œκ°„ λ©”μ‹œμ§•, 캐싱 μœ„ν—˜
Synology Mail ❌ βœ… βœ… 이메일 λ³΄μ•ˆ μ€‘μš”
Synology Photos βœ… βœ… βœ… 이미지 썸넀일 캐싱 효과적
WebDAV ❌ ❌ ❌ 파일 무결성 μš°μ„ 
μ‹œλ†€λ‘œμ§€ DSM βœ… ❌ βœ… 관리 μΈν„°νŽ˜μ΄μŠ€

NAS2 (192.168.1.158) μ„œλΉ„μŠ€

μ„œλΉ„μŠ€ Cache Assets Block Common Exploits WebSocket Support λΉ„κ³ 
μ‹œλ†€λ‘œμ§€ DSM βœ… ❌ βœ… 관리 μΈν„°νŽ˜μ΄μŠ€
Jellyfin βœ… ❌ βœ… λ―Έλ””μ–΄ 슀트리밍
Kavita βœ… βœ… βœ… λ§Œν™”/μ±… 리더
MinIO ❌ ❌ βœ… S3 ν˜Έν™˜ μŠ€ν† λ¦¬μ§€
PicoShare βœ… βœ… ❌ 파일 곡유 μ„œλΉ„μŠ€
Calibre-web βœ… βœ… βœ… μ „μžμ±… 관리
Uptime Kuma βœ… βœ… βœ… μ„œλΉ„μŠ€ λͺ¨λ‹ˆν„°λ§
Outline βœ… βœ… βœ… νŒ€ μœ„ν‚€/λ¬Έμ„œ
Mazanoke βœ… βœ… βœ… λ§Œν™” 관리 도ꡬ

πŸŽ‰ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ μ™„λ£Œ ν›„ μž₯점

톡합 관리

  • λͺ¨λ“  SSL μΈμ¦μ„œλ₯Ό NPMμ—μ„œ 쀑앙 관리
  • μ™€μΌλ“œμΉ΄λ“œ μΈμ¦μ„œλ‘œ μƒˆ μ„œλΈŒλ„λ©”μΈ μΆ”κ°€ μ‹œ μΈμ¦μ„œ μž¬λ°œκΈ‰ λΆˆν•„μš”

κ³ κΈ‰ κΈ°λŠ₯

  • 더 λ§Žμ€ ν”„λ‘μ‹œ μ„€μ • μ˜΅μ…˜
  • μ‹€μ‹œκ°„ 둜그 λͺ¨λ‹ˆν„°λ§
  • 더 λ‚˜μ€ μ›Ή μΈν„°νŽ˜μ΄μŠ€

μ•ˆμ •μ„±

  • μ‹œλ†€λ‘œμ§€ μ—…λ°μ΄νŠΈμ™€ λ¬΄κ΄€ν•˜κ²Œ 독립적 운영
  • 포트 좩돌 μ—†λŠ” μ•ˆμ •μ μΈ μ„œλΉ„μŠ€

πŸ”§ 문제 ν•΄κ²°

NPM μ»¨ν…Œμ΄λ„ˆ μƒνƒœκ°€ "inactive"둜 ν‘œμ‹œλ˜λŠ” 경우

# μ‹€μ œ μƒνƒœ 확인
docker ps -a

# 둜그 확인
docker-compose logs -f npm

# μž¬μ‹œμž‘
docker-compose restart npm

SSL μΈμ¦μ„œ μžλ™ κ°±μ‹  확인

  • NPM 관리 νŽ˜μ΄μ§€μ—μ„œ μΈμ¦μ„œ 만료일 확인
  • 90μΌλ§ˆλ‹€ μžλ™ κ°±μ‹ λ˜λ―€λ‘œ 별도 관리 λΆˆν•„μš”

πŸ“ κ²°λ‘ 

κΈ°μ‘΄ μ‹œλ†€λ‘œμ§€ λ‚΄μž₯ κΈ°λŠ₯μ—μ„œ NPM으둜 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ν•¨μœΌλ‘œμ¨ 더 전문적이고 μ•ˆμ •μ μΈ λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ ν™˜κ²½μ„ ꡬ좕할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 특히 μ™€μΌλ“œμΉ΄λ“œ SSL μΈμ¦μ„œλ₯Ό ν†΅ν•œ 톡합 관리와 Cloudflareμ™€μ˜ μ›ν™œν•œ 연동이 큰 μž₯점으둜 μž‘μš©ν–ˆμŠ΅λ‹ˆλ‹€.


μ°Έκ³ : 이 κ°€μ΄λ“œλŠ” μ‹€μ œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ κ²½ν—˜μ„ λ°”νƒ•μœΌλ‘œ μž‘μ„±λ˜μ—ˆμœΌλ©°, ν™˜κ²½μ— 따라 μ„ΈλΆ€ 섀정이 λ‹¬λΌμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

μΆ”κ°€ ν•„μˆ˜ μ„€μ •

만일!! μ™€μΌλ“œμΉ΄λ“œκ°€ cloudflare  dns에 등둝 λ˜μ–΄μžˆλ‹€λ©΄,

κΌ­ μ•„λž˜ μ„€μ • ν•˜μ„Έμš”. μ•„λž˜ μ„€μ • μ•ˆν•˜λ©΄,
λžœλ€μ„œλΈŒλ„λ©”μΈ.도메인 으둜 μ ‘μ†ν•˜λ©΄ npm ν™˜μ˜νŽ˜μ΄μ§€λ‘œ κ°€λ²„λ¦½λ‹ˆλ‹€
μ‘°μ‹¬ν•˜μ„Έμš”!!
Wildcard DNS Security Risks and How to Mitigate Them
μ™€μΌλ“œμΉ΄λ“œ DNS의 μˆ¨κ²¨μ§„ λ³΄μ•ˆ μœ„ν—˜κ³Ό ν•΄κ²°μ±… 😱 좩격적인 발견: 랜덀 μ„œλΈŒλ„λ©”μΈμœΌλ‘œλ„ 접속이 λœλ‹€κ³ ? ν™ˆλž©μ„ μš΄μ˜ν•˜λ©΄μ„œ **β€μ„œλ²„ μ’€ μ•ˆλ‹€β€**κ³  μƒκ°ν–ˆλŠ”λ°, 이걸 μ•Œκ³  λ‚˜λ‹ˆ λ„ˆλ¬΄ ν™©λ‹Ήν–ˆμŠ΅λ‹ˆλ‹€. ν˜Ήμ‹œ μ—¬λŸ¬λΆ„λ„ 이런 상황은 μ•„λ‹Œμ§€ ν™•μΈν•΄λ³΄μ„Έμš”! πŸ” 문제 상황 체크리슀트 이런 섀정을 μ‚¬μš©ν•˜κ³  κ³„μ‹ κ°€μš”? 일반적인 ν™ˆλž© μ„€μ • 1. 도메인 μ‚¬μš©: example.com, *.example.com 2. Cloudflare DNS:


NPM SSL λͺ¨λ‹ˆν„°λ§ 슀크립트 μ„€μ • κ°€μ΄λ“œ

ν…”λ ˆκ·Έλž¨μœΌλ‘œ NPM의 상황을 전달받을 수 μžˆμŠ΅λ‹ˆλ‹€.

μ••μΆ•νŒŒμΌμ„ ν’€κ³ , sh νŒŒμΌμ„ μ—΄λ©΄ μ•„λž˜μ˜ μ‚¬μš©μž μˆ˜μ • ν•„μˆ˜ ν•­λͺ©μ„ μˆ˜μ •ν•΄μ•Όν•©λ‹ˆλ‹€.

πŸ”§ μ‚¬μš©μž μˆ˜μ • ν•„μˆ˜ ν•­λͺ©

1. ν…”λ ˆκ·Έλž¨ μ„€μ • (ν•„μˆ˜ ⭐⭐⭐)

# 라인 7-8: 본인의 ν…”λ ˆκ·Έλž¨ μ •λ³΄λ‘œ λ³€κ²½
TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN_HERE"        # ← μ‹€μ œ 봇 ν† ν°μœΌλ‘œ λ³€κ²½
TELEGRAM_CHAT_ID="YOUR_CHAT_ID_HERE"           # ← μ‹€μ œ μ±— ID둜 λ³€κ²½

2. NPM μ»¨ν…Œμ΄λ„ˆ 이름 (ν™˜κ²½μ— 따라)

# 라인 11: NPM μ»¨ν…Œμ΄λ„ˆ 이름 확인/λ³€κ²½
NPM_CONTAINER="npm"                            # ← docker ps둜 확인 ν›„ λ³€κ²½

3. ν˜ΈμŠ€νŠΈ 경둜 (ν•„μˆ˜ ⭐⭐⭐)

# 라인 46: Let's Encrypt 마운트 경둜 확인/λ³€κ²½
local host_letsencrypt_path="/volume1/docker/npm/letsencrypt"  # ← μ‹€μ œ 경둜둜 λ³€κ²½

4. μ„œλ²„ 정보 (선택사항)

# 라인 102, 147, 195, 233: IP μ£Όμ†Œ λ³€κ²½
message+="🏠 <b>μ„œλ²„</b>: NPM (192.168.1.158)"   # ← μ‹€μ œ NPM μ„œλ²„ IP둜 λ³€κ²½

πŸ“‹ 확인 방법

ν…”λ ˆκ·Έλž¨ 정보 확인

1. ν…”λ ˆκ·Έλž¨ 봇 생성 및 Chat ID 확인

μ—¬λŸ¬ λΈ”λ‘œκ·Έμ—μ„œ μ†Œκ°œ λœκ²ƒμ΄ 많이 μžˆμŠ΅λ‹ˆλ‹€. μ•„λ‹ˆλ©΄ κΈ°μ‘΄ μ†Œμœ ν•œκ²ƒμ„ ν™œμš©ν•΄λ„λ©λ‹ˆλ‹€.

Docker 정보 확인

# NPM μ»¨ν…Œμ΄λ„ˆ 이름 확인
docker ps | grep nginx-proxy-manager

# 마운트 경둜 확인
docker inspect npm | grep -A5 -B5 letsencrypt

경둜 확인

# Let's Encrypt μΈμ¦μ„œ 파일 쑴재 확인
ls -la /volume1/docker/npm/letsencrypt/archive/npm-*/

# μ‹€μ œ 경둜 ꡬ쑰 확인
find /volume1/docker/npm/letsencrypt -name "*.pem" -type f

⚠️ μ£Όμ˜μ‚¬ν•­

  • ν•„μˆ˜ ν•­λͺ©μ„ μˆ˜μ •ν•˜μ§€ μ•ŠμœΌλ©΄ μŠ€ν¬λ¦½νŠΈκ°€ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€
  • κ²½λ‘œκ°€ 틀리면 "μΈμ¦μ„œ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€" μ—λŸ¬ λ°œμƒ
  • μ»¨ν…Œμ΄λ„ˆ 이름이 틀리면 μˆ˜λ™ κ°±μ‹  κΈ°λŠ₯이 μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€
  • ν…”λ ˆκ·Έλž¨ 정보가 틀리면 λ©”μ‹œμ§€ 전솑 μ‹€νŒ¨

πŸ§ͺ μ„€μ • μ™„λ£Œ ν›„ ν…ŒμŠ€νŠΈ

1. κΆŒν•œ μ„€μ •

chmod 700 npm_ssl_telegram_monitor.sh

755λ₯Ό κΆŒν•œμ„ ν•˜μ—¬λ„ μƒκ΄€μ—†μŠ΅λ‹ˆλ‹€.

2. ν…ŒμŠ€νŠΈ μ‹€ν–‰

# μΈμ¦μ„œ μƒνƒœ 확인 및 전솑
./npm_ssl_telegram_monitor.sh -s

# μˆ˜λ™ κ°±μ‹  μ‹œλ„ (주의: μ‹€μ œ κ°±μ‹  싀행됨)
./npm_ssl_telegram_monitor.sh -r

# μ‚¬μš©λ²• 확인
./npm_ssl_telegram_monitor.sh -h

πŸ“± 정상 μž‘λ™ μ‹œ ν…”λ ˆκ·Έλž¨ λ©”μ‹œμ§€ μ˜ˆμ‹œ

πŸ“‹ NPM SSL μΈμ¦μ„œ μƒνƒœ 보고

πŸ“… 확인 μ‹œκ°„: 2025-06-17 15:30:00
🏠 μ„œλ²„: NPM (192.168.1.158)

πŸ“œ μΈμ¦μ„œ: npm-1 (v2)
🌐 도메인: *.example.com
   β”” μ™€μΌλ“œμΉ΄λ“œ 포함 2개 도메인
πŸ“… 만료일: 2025-09-14 23:54
⏰ 남은 일수: βœ… 89일 (μ•ˆμ „)
πŸ”„ κ°±μ‹  μ‹œκΈ°: 59일 ν›„
πŸ“‚ 파일: fullchain2.pem

πŸ’‘ μ°Έκ³ : 만료 30일 μ „λΆ€ν„° μžλ™ κ°±μ‹ λ©λ‹ˆλ‹€.

πŸ”„ μžλ™ μ‹€ν–‰ μ„€μ • (선택사항)

Cron μ„€μ • λ³΄λ‹€λŠ” μ‹œλ†€λ‘œμ§€ μž‘μ—…μŠ€μΌ€μ€„μ—μ„œ root μž‘μ—…μ„ λ§Œλ“œμ„Έμš”

🚨 문제 ν•΄κ²°

일반적인 였λ₯˜μ™€ ν•΄κ²°μ±…

  1. "μΈμ¦μ„œ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€"
  2. 경둜 확인: ls -la /volume1/docker/npm/letsencrypt/
  3. Docker 마운트 확인: docker inspect npm
  4. ν…”λ ˆκ·Έλž¨ 전솑 μ‹€νŒ¨
  5. 봇 토큰 μž¬ν™•μΈ
  6. Chat ID μž¬ν™•μΈ
  7. λ„€νŠΈμ›Œν¬ μ—°κ²° 확인
  8. κΆŒν•œ 였λ₯˜
  9. 슀크립트 κΆŒν•œ: chmod 700 npm_ssl_telegram_monitor.sh
  10. 파일 μ†Œμœ κΆŒ 확인

이 4κ°€μ§€ ν•­λͺ©λ§Œ μ˜¬λ°”λ₯΄κ²Œ μˆ˜μ •ν•˜λ©΄ μŠ€ν¬λ¦½νŠΈκ°€ 정상 μž‘λ™ν•©λ‹ˆλ‹€! 🎯