βββ β ββ β¦ ββ β βββ
This setup doesn't work with ProtonVPN anymore as of 2024-12-03
This setup depends on a βcompanyβ VPN container for each jD2 container. For this I chose walterl/proton-privoxy since it has a feature to randomly select an exit server. This container depends on the (stale) community CLI implementation of the ProtonVPN API to work. Since March 2024 the issues with this tool have been increasing (for reasons explained here) and itβs going to stop working soon due to dropped support from ProtonVPN. The Implications of this for walterl/proton-privoxy are discussed here and below.
Some notes about replacing/fixing these issues:
- Instead of using the community CLI itβs possible to get the required exit server information from the public ProtonVPN API as suggested here.
- The development on walterl/proton-privoxy seems to be stale too - neither an experimental killswitch feature nor an ip6tables fix have been merged.
- Wireguard instead of OpenVPN is probably not a good option for this random server selection because with ProtonVPN each Wireguard exit server uses its own private key and/or peer address (see here).
- This also impacts tprasadtp/protonvpn-docker, a Wireguard ProtonVPN implementation thus only suitable for a single exit server.
- ingestbot/randomizer also has currently only Wireguard support. (Very interesting python project, Reddit announcement post)
- bubuntux/protorrent, a qBtittorrent client with ProtonVPNβs Wireguard built in.
- It might be possible to replace walterl/proton-privoxy with qdm12/gluetun
- According to this issue it should support random exit servers.
- This might be possible through the optional environment variables
Since Iβm anyway planning to migrate to a K3S based homelab setup Iβll have to create a similar setup within K3S. Here is the K8S sidecar documentation (draft) for qdm12/gluetun.
Here I describe the setup I came up with in order to use multiple jDownloader2 instances in parallel on the same machine. With it you can bypass the by many One-click hosters enforced limit that prevents multiple simultaneous downloads (or enforces a waiting period between downloads).
Currently I use five parallel jd2 instances, each behind its own VPN container. With my ProtonVPN plan I could use up to ten instances simultaneously. However there is nothing preventing you from using other VPN providers or mix multiple providers.
Note
Of course this setup is useless for One-click hosts that prohibit downloads from IPs associated with VPS or VPN. Geoblocking can also be an issue due to the random connections.
- Docker containers utilized
The following different containers are part of this setup:
-
walt3rl/proton-privoxy
(GitHub, DockerHub) β I use this since my VPN provider is ProtonVPN, however they plan to sunset the method used here soon(ish), as discussed here forwalt3rl/proton-privoxy
, including a fix. In the future some other container might be required, maybe gluetun. In order to work best, this setup requires a VPN container that selects an exit server at random upon restart. -
plusminus/jdownloader2-headless
(GitHub, DockerHub) β Despite not been updated in a long time, this container worked best for me. The regular updates of jD2 are installed upon container restart.This image is not available for
linux/arm64
! β buildjdownloader2-headless
on RasPigit clone https://github.com/PlusMinus0/headless-jd2-docker cd headless-jd2-docker/ docker build -t localjd2 -f alpine.Dockerfile .
Replace every
image: plusminus/jdownloader2-headless
indocker-compose.yaml
withimage: localjd2
-
lscr.io/linuxserver/syncthing
(LinuxServer.io) β I run the setup on a VPS to circumvent disconnections caused by my ISP, so I need some tool to retrieve successfully downloaded files. -
jamesread/olivetin
(GitHub, DockerHub) β Used to restart individual components of the setup without requiring to log into the serverβs shell, Portainer or something similar. -
lscr.io/linuxserver/code-server
(LinuxServer.io) β Only required to edit the config file ofjamesread/olivetin
, can be omitted/replaced as needed.
Warning
This setup includes no killswitch! If a VPN container fails, the corresponding jD2 instance connects through the hostβs network to the internet. If you need it, check the experimental killswitch feature or better switch to gluetun.
- Docker-compose file
The following docker-compose.yaml
and .env
files create three jD2 instances:
jd2_0
connects without a VPN to the internetjd2_1
connects through the containervpn_1
jd2_2
connects through the containervpn_2
The downloaded files (partial and finished files) are placed in the volume jd2_downloads
, which is mounted into the Syncthing container at /data1
.
SYNCTHING_HOSTNAME=host
SYNCTHING_PORT_WEBUI=8384
SYNCTHING_PORT_LISTENING=22000
SYNCTHING_PORT_DISCOVERY=21027
TIMEZONE=Europe/Berlin
OLIVETIN_PORT=1337
VSCODE_PW=
VSCODE_PORT=8443
JD2_EMAIL=
JD2_PW=
PVPN_USERNAME=
PVPN_PASSWORD=
PVPN_TIER=2
PVPN_1_PORT=8080
PVPN_2_PORT=8081
version: '3.3'
services:
syncthing:
container_name: syncthing
image: lscr.io/linuxserver/syncthing
restart: unless-stopped
hostname: ${SYNCTHING_HOSTNAME}
environment:
- PUID=0
- PGID=0
- TZ=${TIMEZONE}
ports:
- ${SYNCTHING_PORT_WEBUI}:8384
- ${SYNCTHING_PORT_LISTENING}:22000/tcp
- ${SYNCTHING_PORT_LISTENING}:22000/udp
- ${SYNCTHING_PORT_DISCOVERY}:21027/udp
volumes:
- syncthing_config:/config
- jd2_downloads:/data1
olivetin:
container_name: olivetin
image: jamesread/olivetin
restart: unless-stopped
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- olivetin_config:/config
ports:
- ${OLIVETIN_PORT}:1337
vscode:
container_name: vscode
image: lscr.io/linuxserver/code-server:latest
restart: unless-stopped
environment:
- PUID=0
- PGID=0
- TZ=${TIMEZONE}
- PASSWORD=${VSCODE_PW}
- DEFAULT_WORKSPACE=/mnt
volumes:
- olivetin_config:/mnt/olivetin_config
ports:
- ${VSCODE_PORT}:8443
vpn_1:
container_name: vpn_1
image: walt3rl/proton-privoxy
restart: unless-stopped
devices:
- /dev/net/tun
cap_add:
- NET_ADMIN
volumes:
- /etc/localtime:/etc/localtime:ro
ports:
- ${PVPN_1_PORT}:8080
environment:
- PVPN_USERNAME=${PVPN_USERNAME}
- PVPN_PASSWORD=${PVPN_PASSWORD}
- PVPN_TIER=${PVPN_TIER}
- PVPN_CMD_ARGS=connect --random
- PVPN_DEBUG=1
vpn_2:
container_name: vpn_2
image: walt3rl/proton-privoxy
restart: unless-stopped
devices:
- /dev/net/tun
cap_add:
- NET_ADMIN
volumes:
- /etc/localtime:/etc/localtime:ro
ports:
- ${PVPN_2_PORT}:8080
environment:
- PVPN_USERNAME=${PVPN_USERNAME}
- PVPN_PASSWORD=${PVPN_PASSWORD}
- PVPN_TIER=${PVPN_TIER}
- PVPN_CMD_ARGS=connect --random
- PVPN_DEBUG=1
jd2_0:
container_name: jd2_0
image: plusminus/jdownloader2-headless
restart: unless-stopped
user: root
environment:
EMAIL: ${JD2_EMAIL}
PASSWORD: ${JD2_PW}
volumes:
- jd2_0_config:/opt/JDownloader/cfg
- jd2_0_logs:/opt/JDownloader/logs
- jd2_0_extensions:/opt/JDownloader/extensions
- jd2_downloads:/opt/JDownloader/Downloads
- /etc/localtime:/etc/localtime:ro
jd2_1:
container_name: jd2_1
image: plusminus/jdownloader2-headless
restart: unless-stopped
user: root
network_mode: 'container:vpn_1'
depends_on:
- vpn_1
environment:
EMAIL: ${JD2_EMAIL}
PASSWORD: ${JD2_PW}
volumes:
- jd2_1_config:/opt/JDownloader/cfg
- jd2_1_logs:/opt/JDownloader/logs
- jd2_1_extensions:/opt/JDownloader/extensions
- jd2_downloads:/opt/JDownloader/Downloads
- /etc/localtime:/etc/localtime:ro
jd2_2:
container_name: jd2_2
image: plusminus/jdownloader2-headless
restart: unless-stopped
user: root
network_mode: 'container:vpn_2'
depends_on:
- vpn_2
environment:
EMAIL: ${JD2_EMAIL}
PASSWORD: ${JD2_PW}
volumes:
- jd2_2_config:/opt/JDownloader/cfg
- jd2_2_logs:/opt/JDownloader/logs
- jd2_2_extensions:/opt/JDownloader/extensions
- jd2_downloads:/opt/JDownloader/Downloads
- /etc/localtime:/etc/localtime:ro
volumes:
syncthing_config:
driver: local
name: syncthing_config
olivetin_config:
driver: local
name: olivetin_config
jd2_downloads:
driver: local
name: jd2_downloads
jd2_0_config:
driver: local
name: jd2_0_config
jd2_0_logs:
driver: local
name: jd2_0_logs
jd2_0_extensions:
driver: local
name: jd2_0_extensions
jd2_1_config:
driver: local
name: jd2_1_config
jd2_1_logs:
driver: local
name: jd2_1_logs
jd2_1_extensions:
driver: local
name: jd2_1_extensions
jd2_2_config:
driver: local
name: jd2_2_config
jd2_2_logs:
driver: local
name: jd2_2_logs
jd2_2_extensions:
driver: local
name: jd2_2_extensions
Enter your credentials in .env
, then run docker compose pull
and docker compose up -d
.
Config
- jD2 configuration
β¦
- Open βhttps://my.jdownloader.org/β and login with your credentials.
- Stop all instances of
jdownloader2-headless
but the one you want to configure.
All fresh instances have the same name so you canβt identify them otherwise. - Select your new instance
- Settings β General
- Set βDefault Download Folderβ to
/opt/JDownloader/Downloads/D/<jd:packagename>
(tick βsubfolder as package nameβ) - Disable βAutomatic reconnectβ
- (optional) Set speed limit. I noticed that all containers connected to VPN containers might crash if all download simultaneously with a very high rate.
- Set βDefault Download Folderβ to
- Settings β Plugins
- (optional) Change settings for different hosters.
- Settings β Extension Manager
- Install βFolder Watchβ and enable it.
- Enter the value for βFolderWatch: Foldersβ, depending on the jd2 instance:
- jd2_0 β
["/opt/JDownloader/Downloads/watch/all","/opt/JDownloader/Downloads/watch/0"]
- jd2_1 β
["/opt/JDownloader/Downloads/watch/all/added","/opt/JDownloader/Downloads/watch/1"]
- jd2_2 β
["/opt/JDownloader/Downloads/watch/all/added/added","/opt/JDownloader/Downloads/watch/2"]
- jd2_3 β
["/opt/JDownloader/Downloads/watch/all/added/added/added","/opt/JDownloader/Downloads/watch/3"]
- jd2_0 β
- Settings β Archive Extractor
- Disable the extension.
- Settings β Professional settings
GeneralSettings: If File Exists Action
βSkip the file
GeneralSettings: Auto Start Download Option
βAlways
GeneralSettings: Auto Start Countdown Seconds
β0
MyJDownloaderSettings: Device Name
β enter an individual name
- Click βJD restartβ (under Settings β General) to make sure your settings got saved. Recent setting changes might get lost if a container is stopped/restarted through the docker cli.
- Proceed the same way with your other new instances.
- Olivetin configuration
Open the vscode
containerβs WebUI, navigate the explorer to /mnt/olivetin_config
, create a new file called config.yaml
(next to installation-id.txt
) with the content
actions:
- title: restart jd2 stack [1]
icon: '<img src = "https://jdownloader.org/_media/knowledge/wiki/jdownloader.png" width = "48px"/>'
shell: docker restart vpn_1 jd2_1
timeout: 30
- title: restart jd2 stack [2]
icon: '<img src = "https://jdownloader.org/_media/knowledge/wiki/jdownloader.png" width = "48px"/>'
shell: docker restart vpn_2 jd2_2
timeout: 30
See the documentation for more options. The container vscode
can (and should) be stopped now.
- Syncthing configuration
β¦
- General
- set a fitting folder label, like
jd2_${SYNCTHING_HOSTNAME}
- Folder Path:
/data1
- set a fitting folder label, like
- Sharing
- select your desired (home) Syncthing instance
- File Versioning
No File Versioning
- Ignore Patterns
- set as follows:
*.part jd_accessCheck_* <jd:default>
- Advanced
- β¦
β folder structure for .dlc
files
/data1
βββ .stfolder
βββ D
βββ watch
βββ 0
βββ 1
βββ 2
βββ all
βββ added
βββ added
Additional topics
- Browser setup, useful Windows software
β¦
- Solve captcha with 9kw.eu integration
β¦
- Download workflow
β¦
- Improvement ideas
Just some bullet points of improvement ideas:
- automatically split download links best between containers
- reduce required browser interaction
- remove the need for https://my.jdownloader.org/ (maybe through only local connections?)
- build a script to detect idle containers (maybe by network load?) and restart the associated containers
- script to identify (and resolve) problems related to
<jd:default>
- script to identify (and resolve) problems related to too long filenames (Synology problem?)
βββ β ββ β¦ ββ β βββ