Transmission-OpenVPN 컨테이너의 편리한 설정, 다른 서비스들을 VPN과 함께 나누어 쓰는 방법!

Transmission-OpenVPN 컨테이너의 편리한 설정, 다른 서비스들을 VPN과 함께 나누어 쓰는 방법!

목차

VPN 관련 도커 프로젝트 중 transmission-openvpn 컨테이너는 OpenVPN 서버를 품고 있어 트랜스미션을 VPN 안에서 안전하게 이용할 수 있도록 도와주는 편리한 이미지입니다.

그러나 VPN 의 아이디라는 것은 한번 결제해서 무한정 나누어 쓸 수는 없으니 제한 없이 여러대를 사용할 수는 없습니다.

그렇다면 자연스럽게 다른 도커 컨테이너들 역시 함께 한번의 VPN을 연동하고 싶은 목표가 생깁니다.

제 경우는 현재 NordVPN같은 VPN 서비스를 쓰고 있으며 사이트에서 확인해보니 최대 6대의 장치까지 중복 로그인을 허용하고 있었습니다.

비용을 들여 구매한 계정이니 개인용 태블릿이나 PC 등 다양한 장치에서 사용을 하게 될 예정인데 가능하면 장치의 갯수를 줄이는 것이 좋겠습니다.

Tips & Tricks - docker-transmission-openvpn

그렇다면 도커 컨테이너인 transmission-openvpn 을 어떻게 하면 다른 도커 이미지들과 함께 사용이 가능한지 위 가이드에서도 간단하게 설명하고 있습니다.

좀 더 자세하게 실제 예시로 사용 방법을 알아보겠습니다.

1. 대상 컨테이너 확인 및 테스트 후기

먼저 사용 중인 서비스들 중 VPN 을 통해서 사용할 대상을 준비해봅니다.

먼저 토렌트 인덱서인 Torznab 을 제공하는 Jackett 의 경우 일부 제공자들이 IPS에서 직접 연결을 차단 당하기도 하기 때문에 후보군에 올렸습니다.

동일한 이유로 유사하게 동작하게 될 Radarr,Sonarr,Bazarr 도 대상에 포함됩니다.

마지막으로 딱히 추가할 필요는 없지만 Overseerr 까지 VPN 망내에서 관리해보도록 하겠습니다.

기존 컨테이너는 종료, trans-vpn 그룹으로 VPN을 통해 연결되어 동작하고 있습니다.

최종적으로는 위 사진과 같이 원하는 서비스만 Stack으로 VPN 그룹에 포함해서 구동이 가능해집니다.

빅뱅이론 전 시즌을 토렌트를 이용해 테스트를 진행해보았더니 8월 2일부터 현 포스팅 작성 시점인 8월 9일까지 약 일주일동안 다운로드 작업을 진행해보았습니다.

가능한 쉬지 않고 사용하면서 NordVPN 의 연결 끊김 현상을 총 세번 경험했습니다.

그러나 이때는 의도했던 설정과는 다르게 트랜스미션 컨테이너가 죽어버린 채로 유지가 되는 모습입니다.

몹시 아쉽게도 아직 자동으로 복구된다는 개념이 아닌 포테이너에서 Stack을 한번 수동으로 배포해줘야만 다시 모든 서비스가 정상적으로 동작하는 것으로 이해했습니다.

다른 더 좋은 방법을 발견한다면 따로 내용을 추가하도록 하겠습니다.

https://opencourse.kr/transmission-openvpn-review/

지금부터 진행할 내용은 앞서 지난 포스팅에서 소개드린 transmission-openvpn 도커 컨테이너를 사용하는 경우에만 유효한 설정이 되겠습니다.

2. 포테이너 기존 Stack 수정으로 타 컨테이너 연동

먼저 작업 방식은 기존 Transmission-openvpn 컨테이너 배포와 같이 포테이너의 Stacks 기능을 이용해 Docker Compose 스타일로 배포되어 있습니다.

기존에 이미 도커 compose 스타일의 YAML 형태로 배포하신 경우라면 쉽게 확장이 가능합니다.

이해를 돕기 위해 예제는 공식 가이드와 마찬가지로 Jackett 컨테이너를 추가하고 VPN을 적용하는 것으로 진행해보겠습니다.

먼저 JackettSonarr, Radarr 등의 자동 라이브러리 관리용 컨테이너들과 궁합이 좋은 토렌트 Indexer (인덱서)입니다.

국내 토렌트 사이트들도 서너개 정도 있기 때문에 직접 웹 스크래핑이라도 하지 않는 이상 단순히 RSS 생성용으로만 써도 유용한 컨테이너라고 할 수 있습니다.

그러나 Jackett의 진가는 역시 토렌트 검색엔진처럼 사용이 가능한 구조의 편리한 Torznab 형식을 제공한다는 점에 있습니다.

해외 드라마등을 관리하는 Sonarr 와 만나면 손댈 것 없이 간단하게 세팅이 가능한 정도이지만 국내에선 인지도가 몹시 낮습니다.

그도 그럴 것이 대부분의 국내 자료는 OTT 계통이 아닌 이상 아예 없다고 생각하는게 편할 정도로 부실하기 때문에 해외자료 전용으로 사용할게 아니면 큰 장점이 없습니다.

Jakett에 대해 진지하게 소개하고 싶지만 그렇게 되면 포스팅을 비공개 글로 바꾸어야할 판이니 간단하게 추가로 배포하는 방법에 대해서만 다루어 보도록 하겠습니다.

먼저 사용중인 포테이너 좌측의 Stacks 메뉴를 통해 기존에 배포했던 Stack을 직접 수정하도록 하겠습니다.

version: '3.3'
services:
  # OpenVPN 을 지원하는 트랜스미션 컨테이너
  transmission-openvpn:
    container_name: openvpn-transmission
    restart: always
    cap_add:
      - NET_ADMIN
    volumes:
      - '[직접입력]/data:/data' # 기본 데이터 경로
      - '[직접입력]/config:/config' # 설정파일 경로
      - '[직접입력]/config/ui/web:/config/ui/web' # 테마 폴더 매핑
      - '/volume2/Media1:/volume2/Media1' # 다운로드 파일의 최종 미디어 경로1 (예시)
      - '/volume3/Media2:/volume3/Media2' # 다운로드 파일의 최종 미디어 경로2 (예시)
      - '[직접입력]/download:/download' # 토렌트 다운로드 완료 경로
      - '[직접입력]/incomplete:/incomplete' # 토렌트 임시 다운로드 경로, 디스크 수명을 위해 설정
      - '[직접입력]/watch:/watch' # 토렌트 파일 자동 감시 경로
    environment:
      - OPENVPN_PROVIDER=NORDVPN # VPN 벤더
      - OPENVPN_CONFIG=us.socks.nordhold.net
      - NORDVPN_COUNTRY=US # 기본 지역은 미국
      - NORDVPN_CATEGORY=legacy_p2p # 토렌트용 p2p 설정
      - NORDVPN_PROTOCOL=tcp # VPN에 사용할 프로토콜
      - NORDVPN_SERVER=sg460.nordvpn.com # 사용할 VPN 서버 FQDN을 설정하고, API 권장 사항을 무시하고, 서버의 구성 파일을 다운로드
      - OPENVPN_USERNAME=[직접입력] # NordVPN 서비스 아이디
      - OPENVPN_PASSWORD=[직접입력] # NordVPN 서비스 비밀번호
      - OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60 # VPN 연결이 끊어지면 컨테이너도 종료시킴(킬 스위치)
      - TRANSMISSION_SCRAPE_PAUSED_TORRENTS_ENABLED=false # 최대 절전 모드 해제,VPN 끊김방지
      - LOCAL_NETWORK=192.168.0.0/16 # 로컬 서브넷 대역, 공유기에 따라 다름
      - TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true # 로그인 필수
      - TRANSMISSION_RPC_USERNAME=[직접입력] # 웹UI 로그인 아이디
      - TRANSMISSION_RPC_PASSWORD=[직접입력] # 웹UI 로그인 비밀번호
      - PUID=[직접입력] # 리눅스에서 id 를 입력했을때 나타나는 유저 번 매핑, 환경에 따라 다름
      - PGID=[직접입력] # 마찬가지로 groups 입력시 나타나는 그룹 번호, 환경에 따라 다름
      - TZ=Asia/Seoul # 국내 타임존으로 설정
      #- TRANSMISSION_WEB_UI=combustion # 기본으로 제공하는 테마 중 모바일 사용성이 가장 좋음
      #- TRANSMISSION_WEB_HOME=/config/ui/web # 커스텀 UI 적용시, 반드시 실제 경로에 파일이 존재해야함
      - OVERRIDE_DNS_1=8.8.8.8 # 구글 1차 DNS 적용
      - OVERRIDE_DNS_2=8.8.4.4 # 구글 2차 DNS 적용
      - TRANSMISSION_DOWNLOAD_DIR=/download # 볼륨을 매핑하니 기본 설정으로 둠
      - TRANSMISSION_INCOMPLETE_DIR=/incomplete # 볼륨을 매핑하니 기본 설정으로 둠
      - TRANSMISSION_WATCH_DIR=/watch # 볼륨을 매핑하니 기본 설정으로 둠
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한
    ports:
      - 39091:9091 # 트랜스미션 서비스 포트
      - 39117:9117 # Jackett 서비스 Port
    image: haugene/transmission-openvpn

  # Torrent RSS를 지원하는 재킷 컨테이너
  jackett:
    image: lscr.io/linuxserver/jackett:latest
    container_name: openvpn-jackett
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=[직접입력] # 리눅스에서 id 를 입력했을때 나타나는 유저 번 매핑, 환경에 따라 다름
      - PGID=[직접입력] # 마찬가지로 groups 입력시 나타나는 그룹 번호, 환경에 따라 다름
      - TZ=Asia/Seoul # 국내 타임존으로 설정
      - AUTO_UPDATE=true # 자동 업데이트 사용
    volumes:
      - /[직접입력]/config:/config
      - /[직접입력]/blackhole:/downloads
    depends_on:
      - transmission-openvpn # Set dependency on transmission-openvpn Container
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

YAML 예제를 한번 살펴보겠습니다.

특별히 달라진 것은 없고 익숙한 형태로 아래에 jackett 이란 서비스가 추가된 것처럼 보입니다.

여기서 중요하게 보실 부분은 network_mode: service:transmission-openvpn 으로 네트워크모드를 transmission-openvpn 컨테이너로 넘겨서 처리한 부분입니다.

실제로 jackett 서비스에는 외부 port(포트) 매핑이 전혀 없는 모습으로 오히려 포트를 지정하면 network_mode 설정 덕에 에러가 발생하게 됩니다.

반대로 transmission-openvpn 컨테이너의 포트를 보시게 되면 왠 - 39117:9117 # Jackett 서비스 Port9117 포트를 추가로 매핑해서 넘겨 주고 있는 모습입니다.

위 구조의 핵심은 매우 간단합니다.

추가하실 모든 컨테이너들은 추가로 서비스로 선언하고 네트워크 모드만 VPN이 동작 중인 서비스로 transmission-openvpn 컨테이너를 바라보도록 만들어주세요.

이후 포트는 네트워크를 담당하는 transmission-openvpn 컨테이너에서 원하는 포트로 직접 매핑해주시면 되겠습니다.

이렇게 간단하게 설정하는 것으로 사용중인 컨테이너들을 모두 VPN을 함께 사용하도록 설정해서 외부 포트로 꺼낼 수 있습니다.

YAMLlint - The YAML Validator
Validate, Verify and Reformat your YAML documents, optimized for Ruby on Rails

마찬가지로 배포시 YAML 문법 오류가 발생하시는 경우 위 Validator로 문제를 찾으시면 더욱 쉽게 수정이 가능하니 참고하시기 바랍니다.

문법 오류 없이 모두 수정 완료되셨다면 아래의 Update the stack 버튼을 눌러 Stack의 업데이트를 진행하겠습니다.

이때 새롭게 추가된 컨테이너를 추가 , 또는 기존의 컨테이너 삭제하면서 기존 Stack의 재배포가 진행됩니다.

VPN 추가 작업이 너무 간단해서 당황스러울 정도로 OpenVPN 설정이 쉽다는 것이 위 방식의 가장 큰 장점입니다.

그러나 대표인 transmission-openvpn 컨테이너의 VPN 연결이 끊어지면 Stack 으로 연결된 네트워크의 모든 서비스들 역시 인터넷이 끊어진다는 문제가 발생할 수 있습니다.

구조상 VPN이 끊어졌다고 해서 일반 인터넷으로 위험하게!? 대책 없이 사용이 되는 구조는 아니니 어떤 의미에선 안심이 되기도 하지만 여전히 수동 복구는 불편한 구석이 있습니다.

현재 OPENVPN_OPTS 설정으로 VPN이 어떤 이유로든 끊어지게 되면 트랜스미션 도커 컨테이너가 자동으로 종료되도록 세팅되어 있습니다.

아직까진 테스트를 진행하고 있는 중인데, 위 사진의 transmission-openvpn 컨테이너만 재기동해서는 다른 서비스들의 통신이 이미 끊어진채로 VPN 네트워크 문제가 해결되지 않았습니다.

이를 해결하기 위해선 Stack에서 직접 Update the stack 버튼으로 전체 compose를 재배포해야만 네트워크 문제가 해결 가능했기 때문에, 운영하기에 상당히 불편합니다.

다음으로는 VPN을 특정 주기로 재연결하거나 끊어지면 재기동할 방법에 대해 알아보고 있으며, 편리한 방법을 찾는대로 포스팅해보겠습니다.


3. 다양한 서비스를 한번에 배포한 예시

version: '3.3'
services:
  # OpenVPN 을 지원하는 트랜스미션 컨테이너
  transmission-openvpn:
    container_name: openvpn-transmission
    restart: always
    cap_add:
      - NET_ADMIN
    volumes:
      - '/volume1/Docker/openvpn-transmission/data:/data' # 기본 데이터 경로
      - '/volume1/Docker/openvpn-transmission/config:/config' # 설정파일 경로
      - '/volume1/Docker/openvpn-transmission/config/ui/web:/config/ui/web' # 테마 폴더 매핑
      - '/volume2/Media1:/volume2/Media1' # 다운로드 파일의 최종 미디어 경로1
      - '/volume3/Media2:/volume3/Media2' # 다운로드 파일의 최종 미디어 경로2
      - '/share/USB2/download:/share/USB4/download' # 토렌트 다운로드 완료 경로
      - '/share/USB2/incomplete:/share/USB4/incomplete' # 토렌트 임시 다운로드 경로, 디스크 수명을 위해 설정
      - '/share/USB2/watch:/share/USB4/watch' # 토렌트 파일 자동 감시 경로
    environment:
      - OPENVPN_PROVIDER=NORDVPN # VPN 벤더
      - OPENVPN_CONFIG=us.socks.nordhold.net
      - NORDVPN_COUNTRY=US # 기본 지역은 미국
      - NORDVPN_CATEGORY=legacy_p2p # 토렌트용 p2p 설정
      - NORDVPN_PROTOCOL=tcp # VPN에 사용할 프로토콜
      - NORDVPN_SERVER=sg460.nordvpn.com # 사용할 VPN 서버 FQDN을 설정하고, API 권장 사항을 무시하고, 서버의 구성 파일을 다운로드
      - OPENVPN_USERNAME=[직접입력] # NordVPN 서비스 아이디
      - OPENVPN_PASSWORD=[직접입력] # NordVPN 서비스 비밀번호
      - OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60 # VPN 연결이 끊어지면 컨테이너 강제 종료(킬 스위치)
      - TRANSMISSION_SCRAPE_PAUSED_TORRENTS_ENABLED=false # 최대 절전 모드 해제,VPN 끊김방지
      - LOCAL_NETWORK=192.168.0.0/16 # 로컬 서브넷 대역, 공유기에 따라 다름
      - TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true # 로그인 필수
      - TRANSMISSION_RPC_USERNAME=[직접입력] # 웹UI 로그인 아이디
      - TRANSMISSION_RPC_PASSWORD=[직접입력] # 웹UI 로그인 비밀번호
      - PUID=1000 # 리눅스에서 id 를 입력했을때 나타나는 유저 번 매핑, 환경에 따라 다름
      - PGID=100 # 마찬가지로 groups 입력시 나타나는 그룹 번호, 환경에 따라 다름
      - TZ=Asia/Seoul # 국내 타임존으로 설정
      #- TRANSMISSION_WEB_UI=combustion # 기본으로 제공하는 테마 중 모바일 사용성이 가장 좋음
      - TRANSMISSION_WEB_HOME=/config/ui/web # 커스텀 UI 적용시, 반드시 실제 경로에 파일이 존재해야함
      - OVERRIDE_DNS_1=8.8.8.8 # 구글 1차 DNS 적용
      - OVERRIDE_DNS_2=8.8.4.4 # 구글 2차 DNS 적용
      - TRANSMISSION_DOWNLOAD_DIR=/share/USB4/download # 볼륨을 매핑하니 기본 설정으로 둠
      - TRANSMISSION_INCOMPLETE_DIR=/share/USB4/incomplete # 볼륨을 매핑하니 기본 설정으로 둠
      - TRANSMISSION_WATCH_DIR=/share/USB4/watch # 볼륨을 매핑하니 기본 설정으로 둠
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한
    ports:
      - 39091:9091 # 트랜스미션 서비스 포트
      - 31080:1080  # Dante와 Socks5 Port
      - 39117:9117 # Jackett 서비스 Port
      - 36767:6767 # Bazarr 서비스 Port
      - 37878:7878 # Radarr 서비스 Port
      - 38989:8989 # Sonarr 서비스 Port
      - 35055:5055 # Overseerr 서비스 Port
      - 38080:8080 # SABNzbd 서비스 Port
    image: haugene/transmission-openvpn

  # Torrent RSS를 지원하는 재킷 컨테이너
  jackett:
    image: lscr.io/linuxserver/jackett:latest
    container_name: openvpn-jackett
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
      - AUTO_UPDATE=true # 자동 업데이트 사용
    volumes:
      - /volume1/Docker/openvpn-jackett/config:/config
      - /volume1/Docker/openvpn-jackett/blackhole:/downloads
    depends_on:
      - transmission-openvpn # Set dependency on transmission-openvpn Container
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

  # 자막 자동 다운로드 용 Bazarr 컨테이너
  bazarr:
    image: lscr.io/linuxserver/bazarr:latest
    container_name: openvpn-bazarr
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
    volumes:
      - /share/Docker/openvpn-bazarr/config:/config
      - /volume2/Media1:/volume2/Media1
      - /volume3/Media2:/volume3/Media2
      - /share/USB2:/share/USB4
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

  # 영화 자동 다운로드 용 Radarr 컨테이너
  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: openvpn-radarr
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
    volumes:
      - /share/Docker/openvpn-radarr/config:/config
      - /volume2/Media1:/volume2/Media1
      - /volume3/Media2:/volume3/Media2
      - /share/USB2:/share/USB4
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

  # TV 자동 다운로드 용 Sonarr 컨테이너
  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: openvpn-sonarr
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
    volumes:
      - /share/Docker/openvpn-sonarr/config:/config
      - /volume2/Media1:/volume2/Media1
      - /volume3/Media2:/volume3/Media2
      - /share/USB2:/share/USB4
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한
  
  # 미디어 요청 용 Overseerr 컨테이너
  overseerr:
    image: lscr.io/linuxserver/overseerr:latest
    container_name: openvpn-overseerr
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
    volumes:
      - /share/Docker/openvpn-overseerr/config:/config
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

  # 유즈넷 다운로드 클라이언트 SSBNzbd 컨테이너
  sabnzbd:
    image: lscr.io/linuxserver/sabnzbd:latest
    container_name: openvpn-sabnzbd
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Asia/Seoul # 국내 타임존으로 설정
    volumes:
      - /share/Docker/openvpn-sabnzbd/config:/config
      - /volume2/Media1:/volume2/Media1
      - /volume3/Media2:/volume3/Media2
      - /share/USB2:/share/USB4
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

  # 기왕 VPN 실행하는 김에 socks5 지원하는 프록시 서버도 설정
  socks5-proxy:
    image: wernight/dante
    container_name: openvpn-dante
    restart: unless-stopped
    network_mode: service:transmission-openvpn
    depends_on:
      - transmission-openvpn
    command:
      - /bin/sh
      - -c
      - |
        echo "Waiting for VPN to connect . . ."
        while ! ip link show tun0 >/dev/null 2>&1 || ! ip link show tun0 | grep -q "UP"; do sleep 1; done
        echo "VPN connected. Starting proxy service . . ."
        sed -i 's/^\(external:\).*/\1 tun0/' /etc/sockd.conf
        sockd
    logging:
      driver: json-file
      options:
        max-size: 10m # log 파일의 용량을 10m로 제한

Asustor 나스 기준 환경이다 보니 설정된 경로는 여러분에게 딱히 도움이 안될 수도 있습니다.

현재 제가 사용중인 YAML 전문이니 필요한 서비스가 있다면 참고해서 사용해보시고 생각보다 특별할 것 없는 네트워크 설정 구조를 참고하시길 바랍니다.

비정기로 발행되는 추천 포스트를 이메일로 받아 보실 수 있습니다.

특별한 추천 포스트를 바로 이메일로 받아보세요. 물론 무료입니다!
좋아요! 받은 편지함을 확인하고 구독을 확인하려면 링크를 클릭하십시오.
오류! 유효한 이메일 주소를 입력하십시오!