금. 8월 8th, 2025

안녕하세요! 🚀 수많은 웹 서비스를 운영하면서 매번 Nginx 설정 파일을 직접 수정하고, SSL 인증서를 갱신하느라 번거로움을 겪으셨나요? 더 이상 걱정하지 마세요! 오늘은 이 모든 과정을 마법처럼 쉽고 직관적으로 만들어주는 Nginx Proxy Manager(NPM)를 Docker Compose를 이용해 설치하고 활용하는 방법에 대해 자세히 알아보겠습니다.


💡 1. Nginx Proxy Manager(NPM)란 무엇인가요?

Nginx Proxy Manager는 이름에서 알 수 있듯이, Nginx를 기반으로 하는 리버스 프록시(Reverse Proxy) 관리 도구입니다. 하지만 단순히 프록시 기능만 제공하는 것이 아닙니다. 웹 기반의 직관적인 사용자 인터페이스(GUI)를 통해 다음과 같은 강력한 기능들을 제공합니다.

  • 리버스 프록시 설정: 외부에서 들어오는 요청을 내부의 특정 서버(예: 웹 서버, 애플리케이션 서버)로 전달하는 기능을 쉽게 설정할 수 있습니다. 예를 들어, blog.example.com으로 들어온 요청을 내부의 192.168.1.100:2368 포트에서 실행 중인 Ghost 블로그로 연결하는 식이죠.
  • SSL 인증서 관리 (Let’s Encrypt 자동화): 가장 큰 장점 중 하나입니다! Let’s Encrypt를 통해 무료 SSL/TLS 인증서를 손쉽게 발급받고, 자동으로 갱신할 수 있습니다. 웹사이트 보안을 강화하고 HTTPS를 활성화하는 데 필수적인 작업이죠. 🔒
  • 사용자 정의 Nginx 지시문: 고급 사용자를 위해 특정 프록시 호스트에 커스텀 Nginx 설정(예: 캐싱, 보안 헤더 추가)을 추가할 수 있습니다.
  • 리다이렉션 및 404 페이지 설정: 특정 URL을 다른 URL로 리다이렉션하거나, 존재하지 않는 페이지에 대한 404 에러 페이지를 설정할 수 있습니다.
  • 접근 제어 (Basic Auth): 특정 프록시 호스트에 접근할 때 사용자 이름과 비밀번호를 요구하도록 설정할 수 있습니다.

한마디로, NPM은 Nginx 설정과 SSL 인증서 관리를 위한 복잡한 명령어나 설정 파일 편집 없이 웹 브라우저만으로 모든 작업을 처리할 수 있게 해주는 도구입니다.

🤔 2. 왜 Nginx Proxy Manager를 사용해야 할까요?

기존에 Nginx를 직접 설정해 보신 분이라면, nginx.conf 파일을 수정하고, systemctl reload nginx 명령어를 입력하며, Let’s Encrypt certbot을 수동으로 실행했던 경험이 있을 겁니다. 이 과정은 다음과 같은 문제점을 가지고 있습니다.

  • 복잡한 설정 파일: Nginx 설정은 문법이 까다롭고, 오타 하나에도 서비스가 중단될 수 있습니다.
  • SSL 인증서 갱신: Let’s Encrypt 인증서는 90일마다 갱신해야 하는데, 이를 수동으로 관리하면 놓치기 쉽습니다.
  • 다수의 서비스 관리: 여러 개의 웹 서비스(워드프레스, Nextcloud, Home Assistant 등)를 운영할 경우, 각각의 Nginx 설정을 관리하는 것이 매우 번거롭습니다.

NPM은 이러한 문제들을 해결해 줍니다.

  • 직관적인 GUI: 복잡한 Nginx 문법을 몰라도 몇 번의 클릭만으로 프록시 호스트를 생성하고 SSL을 적용할 수 있습니다.
  • 자동화된 SSL: Let’s Encrypt 인증서 발급 및 갱신이 완전히 자동화되어, 잊어버릴 걱정이 없습니다.
  • 중앙 집중식 관리: 모든 웹 서비스의 리버스 프록시 설정을 NPM 대시보드 한 곳에서 관리할 수 있습니다.
  • 시간 절약: 설정에 드는 시간을 줄여 핵심 서비스 개발 및 운영에 집중할 수 있습니다.

🛠️ 3. Docker Compose를 이용한 NPM 설치

Nginx Proxy Manager는 Docker 환경에서 가장 쉽게 배포할 수 있습니다. 특히 Docker Compose를 사용하면 몇 줄의 설정만으로 NPM과 필요한 데이터베이스를 한 번에 구성할 수 있습니다.

3.1. 준비물

  • Docker 및 Docker Compose 설치: 서버에 Docker와 Docker Compose가 설치되어 있어야 합니다. 설치되어 있지 않다면, 공식 문서를 참고하여 설치해 주세요. (예: sudo apt-get install docker.io docker-compose)
  • 도메인: 프록시할 서비스에 연결할 도메인 (예: your-app.com, blog.your-domain.com)이 필요하며, 이 도메인의 DNS 설정에서 서버의 공인 IP를 가리키도록 A 레코드 또는 CNAME 레코드가 구성되어 있어야 합니다.

3.2. Docker Compose 파일 작성

NPM은 설정 정보를 저장하기 위한 데이터베이스(MariaDB 또는 MySQL)를 필요로 합니다. 따라서 docker-compose.yml 파일에는 NPM 컨테이너와 데이터베이스 컨테이너 두 가지가 정의됩니다.

# docker-compose.yml
version: '3.8'

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    ports:
      # 웹 트래픽(HTTP)
      - '80:80'
      # 보안 웹 트래픽(HTTPS)
      - '443:443'
      # NPM 관리 페이지 (HTTP)
      - '81:81'
    environment:
      DB_MYSQL_HOST: db
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: 'npmuser'
      DB_MYSQL_PASSWORD: 'your_db_password' # 강력한 비밀번호로 변경하세요!
      DB_MYSQL_DATABASE: 'npm'
    volumes:
      # NPM 설정 및 인증서 데이터 (영구 저장)
      - npm_data:/data
      - npm_letsencrypt:/etc/letsencrypt
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: 'jc21/mariadb-aria:latest' # 또는 'mysql:8.0'
    container_name: nginx-proxy-manager-db
    environment:
      MYSQL_ROOT_PASSWORD: 'your_root_password' # 강력한 비밀번호로 변경하세요!
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npmuser'
      MYSQL_PASSWORD: 'your_db_password' # app 서비스의 DB_MYSQL_PASSWORD와 동일하게 설정
    volumes:
      # DB 데이터 (영구 저장)
      - npm_db:/var/lib/mysql
    restart: unless-stopped

volumes:
  npm_data:
  npm_letsencrypt:
  npm_db:

🤔 각 설정의 의미는?

  • version: '3.8': Docker Compose 파일의 버전을 명시합니다. 최신 버전을 사용하는 것이 좋습니다.
  • services: 실행할 컨테이너들을 정의합니다.
    • app (NPM 컨테이너):
      • image: 'jc21/nginx-proxy-manager:latest': Nginx Proxy Manager 공식 이미지를 사용합니다.
      • container_name: nginx-proxy-manager: 컨테이너 이름을 지정하여 쉽게 식별할 수 있게 합니다.
      • ports:
        • 80:80: 외부의 80번 포트를 컨테이너의 80번 포트에 연결 (HTTP).
        • 443:443: 외부의 443번 포트를 컨테이너의 443번 포트에 연결 (HTTPS).
        • 81:81: 외부의 81번 포트를 컨테이너의 81번 포트에 연결 (NPM 관리 UI).
        • ⚠️ 중요: 서버의 80, 443, 81 포트가 다른 서비스에 의해 사용 중이지 않아야 합니다.
      • environment: 데이터베이스 연결 정보를 정의합니다. DB_MYSQL_HOSTdb 서비스의 이름을 사용합니다.
      • volumes: 컨테이너 내부의 데이터를 호스트 머신에 영구적으로 저장하기 위한 볼륨을 연결합니다. npm_data는 NPM의 설정 파일과 로그, npm_letsencrypt는 Let’s Encrypt 인증서 파일을 저장합니다.
      • depends_on: - db: app 컨테이너가 db 컨테이너가 먼저 시작된 후에 실행되도록 지정합니다.
      • restart: unless-stopped: 컨테이너가 종료되더라도 자동으로 재시작하도록 설정합니다.
    • db (데이터베이스 컨테이너):
      • image: 'jc21/mariadb-aria:latest': MariaDB 이미지를 사용합니다. MySQL을 원하면 mysql:8.0 등으로 변경할 수 있습니다.
      • container_name: nginx-proxy-manager-db: 데이터베이스 컨테이너의 이름입니다.
      • environment: 데이터베이스의 루트 비밀번호, 데이터베이스 이름, 사용자 이름, 사용자 비밀번호를 설정합니다. 반드시 강력한 비밀번호로 변경하세요! (MYSQL_USERMYSQL_PASSWORDapp 컨테이너의 DB_MYSQL_USERDB_MYSQL_PASSWORD와 동일해야 합니다.)
      • volumes: - npm_db:/var/lib/mysql: 데이터베이스 데이터를 영구적으로 저장하기 위한 볼륨입니다.
  • volumes: services 섹션에서 사용될 명명된 볼륨(Named Volume)을 정의합니다. Docker가 자동으로 생성하고 관리합니다.

3.3. NPM 실행

  1. docker-compose.yml 파일을 서버의 원하는 디렉토리(예: ~/npm)에 생성합니다.
  2. 해당 디렉토리로 이동합니다.
    cd ~/npm
  3. Docker Compose를 이용하여 컨테이너를 실행합니다.
    docker compose up -d

    up은 컨테이너를 생성하고 시작하며, -d 옵션은 백그라운드에서 실행하도록 합니다.

모든 과정이 정상적으로 완료되면, docker compose ps 명령어로 컨테이너들이 잘 실행되고 있는지 확인할 수 있습니다.

docker compose ps

출력에서 nginx-proxy-managernginx-proxy-manager-db 컨테이너의 상태가 Up으로 표시되어야 합니다.

🌐 4. Nginx Proxy Manager 기본 설정 및 활용

컨테이너가 성공적으로 실행되었다면, 이제 웹 브라우저를 통해 NPM 관리 페이지에 접속해 설정을 시작할 수 있습니다.

4.1. NPM 관리 페이지 접속

웹 브라우저를 열고 서버의 IP 주소와 81번 포트를 이용하여 접속합니다. http://서버_IP_주소:81 (예: http://192.168.1.100:81)

4.2. 초기 로그인 정보

최초 로그인 시 다음 기본 계정 정보를 사용합니다.

  • Email: admin@example.com
  • Password: changeme

로그인 후에는 보안을 위해 반드시 이메일 주소와 비밀번호를 변경하라는 메시지가 나타납니다. 즉시 변경해 주세요. 🔒

4.3. 프록시 호스트 추가 (Proxy Hosts)

이제 NPM의 핵심 기능인 ‘프록시 호스트’를 추가해 보겠습니다.

  1. NPM 대시보드에서 좌측 메뉴의 ‘Hosts’ -> ‘Proxy Hosts’를 클릭합니다.

  2. 우측 상단의 ‘Add Proxy Host’ 버튼을 클릭합니다.

  3. Details 탭 설정:

    • Domain Names: 이 프록시 호스트로 접근할 도메인 이름을 입력합니다. (예: blog.your-domain.com) 여러 개를 추가할 수 있습니다.
    • Scheme: 내부 서비스의 프로토콜 (HTTP 또는 HTTPS)을 선택합니다. 대부분 http를 사용합니다.
    • Forward Hostname / IP: 내부 서비스가 실행 중인 서버의 IP 주소 또는 호스트 이름을 입력합니다. (예: 192.168.1.10 또는 my-app-server)
    • Forward Port: 내부 서비스가 사용 중인 포트 번호를 입력합니다. (예: 2368 for Ghost, 8000 for Django)
    • Block Common Exploits: 일반적인 웹 공격을 차단하는 옵션입니다. 활성화하는 것을 권장합니다.
    • Websockets Support: 웹소켓을 사용하는 서비스 (예: Home Assistant, 채팅 앱)라면 활성화합니다.

    NPM Proxy Host Details Example (예시: blog.your-domain.com -> http://192.168.1.10:2368)

  4. SSL 탭 설정:

    • SSL Certificate: Request a new SSL Certificate를 선택합니다.
    • Force SSL: HTTP 요청을 HTTPS로 강제 리다이렉션합니다. 보안을 위해 반드시 활성화하세요.
    • HTTP/2 Support: 최신 HTTP/2 프로토콜을 사용합니다. 성능 향상을 위해 활성화하는 것이 좋습니다.
    • I Agree to the Let's Encrypt Terms of Service: 약관 동의를 체크합니다.
    • Email Address for Let's Encrypt: Let’s Encrypt 관련 알림을 받을 이메일 주소를 입력합니다.

    NPM Proxy Host SSL Example

  5. Advanced 탭 (선택 사항):

    • Nginx 설정 파일에 직접 추가하고 싶은 지시문이 있다면 이곳에 입력합니다. 예를 들어, 특정 캐싱 규칙이나 보안 헤더를 추가할 수 있습니다.
    • 예시:
      add_header X-Frame-Options "SAMEORIGIN";
      add_header X-Content-Type-Options "nosniff";
  6. 모든 설정을 마쳤다면 ‘Save’ 버튼을 클릭합니다.

잠시 후, NPM이 Let’s Encrypt를 통해 SSL 인증서를 자동으로 발급받고 Nginx 설정을 적용합니다. 모든 과정이 성공적으로 완료되면, 이제 https://blog.your-domain.com과 같이 설정한 도메인으로 접속하여 서비스를 확인할 수 있습니다! ✨

4.4. 기타 활용 기능

  • Redirection Hosts: 특정 도메인을 다른 URL로 리다이렉션할 때 사용합니다. (예: old-site.com -> new-site.com)
  • 404 Hosts: 존재하지 않는 페이지에 대한 기본 404 에러 페이지를 설정합니다.
  • Streams: TCP/UDP 포트 포워딩을 설정할 때 사용합니다. (HTTP/HTTPS가 아닌 다른 프로토콜의 트래픽을 전달할 때 유용)
  • Users: NPM 관리 페이지에 접근할 수 있는 추가 사용자를 관리합니다.
  • Audit Log: NPM에서 발생한 모든 설정 변경 및 이벤트 기록을 확인할 수 있습니다. 문제 발생 시 디버깅에 유용합니다.

⚠️ 5. 팁 및 주의사항

  • DNS 설정 필수! NPM이 Let’s Encrypt 인증서를 성공적으로 발급받고, 외부에서 서비스에 접근하려면 설정하려는 도메인이 반드시 NPM이 설치된 서버의 공인 IP 주소를 가리키고 있어야 합니다. 도메인 등록 업체나 DNS 관리 서비스에서 A 레코드(your-domain.com -> 서버_IP_주소) 또는 CNAME 레코드(sub.your-domain.com -> your-domain.com 또는 다른 도메인)를 올바르게 설정해야 합니다.
  • 방화벽 설정 서버의 방화벽(예: ufw 또는 클라우드 서비스의 보안 그룹)에서 80번 (HTTP), 443번 (HTTPS), 81번 (NPM 관리 페이지) 포트를 외부에서 접근할 수 있도록 열어주어야 합니다.
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow 81/tcp
    sudo ufw reload
  • 데이터 백업 💾 docker-compose.yml 파일에서 정의한 npm_data, npm_letsencrypt, npm_db 볼륨에는 NPM의 모든 설정, 인증서, 데이터베이스 정보가 저장됩니다. 서버에 문제가 발생할 경우를 대비하여 이 볼륨들을 정기적으로 백업하는 것이 중요합니다. (예: docker cp nginx-proxy-manager:/data ./npm_data_backup)
  • 포트 충돌 해결 만약 서버의 80번 또는 443번 포트가 이미 다른 웹 서버(Apache, Nginx 등)에 의해 사용 중이라면, Docker Compose 파일을 수정하여 NPM의 호스트 포트를 변경할 수 있습니다.
    ports:
      - '8080:80' # 호스트의 8080 포트를 NPM의 80 포트에 연결
      - '8443:443' # 호스트의 8443 포트를 NPM의 443 포트에 연결
      - '81:81'

    이렇게 변경하면 외부에서 http://your-domain.com:8080 또는 https://your-domain.com:8443으로 접속해야 합니다. 이는 추천하지 않는 방법이며, 가급적 80/443 포트를 NPM이 단독으로 사용하도록 하는 것이 좋습니다. 기존 웹 서버를 중단하거나 NPM이 기존 웹 서버 앞에 위치하도록 구성하는 방법을 고려해 보세요.

  • 보안 강화
    • NPM 관리자 계정의 비밀번호를 강력하고 유추하기 어려운 것으로 설정하세요.
    • NPM 및 기반 Docker 이미지를 최신 상태로 유지하여 보안 취약점을 패치하세요. (docker compose pulldocker compose up -d)
  • 내부 서비스는 HTTP로! NPM은 리버스 프록시로 동작하기 때문에, 내부 서비스(예: Node.js 앱, Apache 서버)는 굳이 HTTPS로 구성할 필요가 없습니다. NPM이 외부의 HTTPS 요청을 받아 내부 서비스로 HTTP로 전달하고, 내부 서비스의 응답을 다시 HTTPS로 외부로 전달하는 방식으로 동작합니다. 이는 관리 복잡도를 줄여줍니다.

✅ 결론

Nginx Proxy Manager는 웹 서비스 운영에 있어 번거로운 Nginx 설정과 SSL 인증서 관리를 획기적으로 단순화시켜주는 강력한 도구입니다. Docker Compose를 활용하면 단 몇 분 만에 완벽하게 동작하는 NPM 환경을 구축할 수 있으며, 직관적인 웹 UI를 통해 모든 서비스를 손쉽게 관리할 수 있습니다.

이제 여러분도 Nginx Proxy Manager와 함께 웹 서비스 관리에 들이는 시간을 절약하고, 더 중요한 작업에 집중할 수 있을 것입니다. 궁금한 점이 있다면 언제든지 댓글로 질문해주세요! 행복한 서버 운영 되세요! 💻✨

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다