Transmission-OpenVPN 컨테이너의 편리한 설정, 다른 서비스들을 VPN과 함께 나누어 쓰는 방법!
VPN
관련 도커 프로젝트 중 transmission-openvpn
컨테이너는 OpenVPN
서버를 품고 있어 트랜스미션을 VPN
안에서 안전하게 이용할 수 있도록 도와주는 편리한 이미지입니다.
그러나 VPN
의 아이디라는 것은 한번 결제해서 무한정 나누어 쓸 수는 없으니 제한 없이 여러대를 사용할 수는 없습니다.
그렇다면 자연스럽게 다른 도커 컨테이너들 역시 함께 한번의 VPN
을 연동하고 싶은 목표가 생깁니다.
제 경우는 현재 NordVPN
같은 VPN
서비스를 쓰고 있으며 사이트에서 확인해보니 최대 6대
의 장치까지 중복 로그인을 허용하고 있었습니다.
비용을 들여 구매한 계정이니 개인용 태블릿
이나 PC
등 다양한 장치에서 사용을 하게 될 예정인데 가능하면 장치의 갯수를 줄이는 것이 좋겠습니다.
그렇다면 도커 컨테이너인 transmission-openvpn
을 어떻게 하면 다른 도커 이미지들과 함께 사용이 가능한지 위 가이드에서도 간단하게 설명하고 있습니다.
좀 더 자세하게 실제 예시로 사용 방법을 알아보겠습니다.
1. 대상 컨테이너 확인 및 테스트 후기
먼저 사용 중인 서비스들 중 VPN
을 통해서 사용할 대상을 준비해봅니다.
먼저 토렌트 인덱서인 Torznab
을 제공하는 Jackett
의 경우 일부 제공자들이 IPS
에서 직접 연결을 차단 당하기도 하기 때문에 후보군에 올렸습니다.
동일한 이유로 유사하게 동작하게 될 Radarr
,Sonarr
,Bazarr
도 대상에 포함됩니다.
마지막으로 딱히 추가할 필요는 없지만 Overseerr
까지 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
을 적용하는 것으로 진행해보겠습니다.
먼저 Jackett
은 Sonarr
, 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 서비스 Port
로 9117
포트를 추가로 매핑해서 넘겨 주고 있는 모습입니다.
위 구조의 핵심은 매우 간단합니다.
추가하실 모든 컨테이너들은 추가로 서비스
로 선언하고 네트워크 모드만 VPN
이 동작 중인 서비스로 transmission-openvpn
컨테이너를 바라보도록 만들어주세요.
이후 포트는 네트워크를 담당하는 transmission-openvpn
컨테이너에서 원하는 포트로 직접 매핑해주시면 되겠습니다.
이렇게 간단하게 설정하는 것으로 사용중인 컨테이너들을 모두 VPN
을 함께 사용하도록 설정해서 외부 포트로 꺼낼 수 있습니다.
마찬가지로 배포시 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
전문이니 필요한 서비스가 있다면 참고해서 사용해보시고 생각보다 특별할 것 없는 네트워크 설정 구조를 참고하시길 바랍니다.