Skip to content

Latest commit

 

History

History
312 lines (249 loc) · 10.1 KB

image.adoc

File metadata and controls

312 lines (249 loc) · 10.1 KB

Image

This section describes how to prepare and build Docker image for the Transmission.

Preparing OpenVPN Profiles

Create a transmission directory under the /root/silverbox/vpn directory:

sudo mkdir /root/silverbox/vpn/transmission
sudo chmod 700 /root/silverbox/vpn/transmission

And copy all OpenVPN profile files (*.ovpn) that you want to use for Transmission client into it (you can have multiple files as exit point rotation will be configured). This way you can use different OpenVPN profiles (and thus exit points) for SOCKS5 proxy and for Transmission.

Note
At any time, if you want only to use specific profile, create a symlink named profile pointing to desired profile. For example ln -s SOME_PROFILE.ovpn profile. Make sure the link is relative and not absolute: otherwise it won’t work inside the container.

Preparing Directory Structure

In this configuration, Transmission will use directories on the NFS share to read torrent files and to store downloaded files. These directories need to be created in advance.

As your user, create directories for torrent files and downloads in the NFS directory and set proper permissions/ownership:

mkdir -p /srv/nfs/torrents/torrentfiles # (1)
mkdir -p /srv/nfs/torrents/downloads # (2)
chown {SB_USER}:{SB_NFS_GROUP} -R /srv/nfs/torrents
chmod 770 -R /srv/nfs/torrents
  1. This directory will be automatically watched for the *.torrent files and once new file appear download will be started automatically (torrent file will be removed once added to the queue).

  2. Finished and in-progress downloads will be placed into this directory.

Note
Of course, you can use different directory structure and names, this is just an example.

Preparing Image Files

Create a directory for the Transmission container:

sudo mkdir /root/silverbox/containers/transmission
sudo chmod 700 /root/silverbox/containers/transmission

Inside the transmission directory, create a file named docker-compose.yaml with the following content:

/root/silverbox/containers/transmission/docker-compose.yaml
version: '3.8'

networks:
  default:
    name: vpn
    external: true

services:
  transmission:
    container_name: transmission
    init: true
    build:
      context: /root/silverbox/containers/transmission
      args:
        version: '{SB_DEBIAN_VERSION}' # (1)
    restart: on-failure:15
    logging:
      driver: json-file
      options:
        max-size: 10mb
    ports:
      - 127.0.0.1:{SB_TRANSMISSION_PORT}:{SB_TRANSMISSION_PORT}/tcp # (2)
    networks:
      default:
        ipv4_address: {SB_TRANSMISSION_ADDR} # (3)
    devices:
      - /dev/net/tun
    cap_add:
      - NET_ADMIN
    volumes:
      - /srv/nfs/torrents:/data
      - /root/silverbox/vpn/transmission:/vpn-profiles
      - /root/silverbox/vpn/auth:/vpn-credentials
  1. Replace {SB_DEBIAN_VERSION} with the actual latest debian image version (can be checked at the Docker Hub). Note that this is not the Transmission version.

  2. Replace {SB_TRANSMISSION_PORT} with the actual port number.

  3. Replace {SB_TRANSMISSION_ADDR} with the actual address.

Next, create a file named Dockerfile with the following content:

/root/silverbox/containers/transmission/Dockerfile
ARG version=latest

FROM debian:$version

ARG UID={USER_ID} # (1)
ARG GID={GROUP_ID} # (2)

RUN apt-get update && \
    apt-get install -y --no-install-recommends bash iputils-ping iptables openvpn transmission-daemon && \
    addgroup --system vpn && \
    addgroup --gid ${GID} transmission && \
    adduser transmission --uid ${UID} --gid ${GID} --disabled-login --no-create-home --gecos "" --shell /usr/sbin/nologin && \
    mkdir /config && chown transmission:transmission /config

COPY docker-entrypoint.sh /usr/local/bin/
COPY start-transmission.sh /usr/local/bin/
COPY --chown=transmission:transmission settings.json /config/

HEALTHCHECK --interval=120s --timeout=20s --start-period=120s CMD ping 1.1.1.1 -c 1 # (3)

VOLUME ["/vpn-profiles", "/vpn-credentials", "/data"]

EXPOSE {SB_TRANSMISSION_PORT}/tcp # (4)

ENTRYPOINT [ "/usr/local/bin/docker-entrypoint.sh" ]
  1. Replace {USER_ID} with the UID of your {SB_USER} user on the server.

  2. Replace {GROUP_ID} with the GID of your {SB_NFS_GROUP} group on the server.

  3. Feel free to customize health check command.

  4. Replace {SB_TRANSMISSION_PORT} with some port number of your choice (e.g. 12345). The container will expose this port to access the Transmission web UI.

Create the start-transmission.sh file with the following content:

/root/silverbox/containers/transmission/start-transmission.sh
#!/bin/bash

echo "-- Preparing to start transmission-daemon..."

if [ -f /config/transmission.log ]; then
    echo "-- Cleaning log file..."
    tail -c 10000000 /config/transmission.log > /config/transmission.log.trunc
    mv /config/transmission.log.trunc /config/transmission.log
    chown transmission:transmission /config/transmission.log
fi

TUN_IP=$(ip address show dev tun0 | awk '/inet/{ split($2, a, "/"); print a[1] }')
if [ -z "$TUN_IP" ]; then
    echo "-- Failed to get tun0 IP address"
    exit 1
else
    echo "-- tun0 address: [$TUN_IP]. Updating config file."
    sed -i "s/\(\"bind-address-ipv4\":\)\s\+\".\+\",/\1 \"$TUN_IP\",/" /config/settings.json
    echo "-- Starting transmission-daemon..."
    su transmission -s /bin/bash -c "transmission-daemon -g /config --logfile /config/transmission.log"
    if [ $? -ne 0 ]; then
        echo "-- Failed to start transmission"
        exit 1
    else
        echo "-- Transmission started"
    fi
fi

And mark it as executable:

sudo chmod a+x start-transmission.sh

Create the docker-entrypoint.sh file with the following content:

/root/silverbox/containers/transmission/docker-entrypoint.sh
#!/usr/bin/env bash

function configure_iptables()
{
    set -e

    local config_file="$1"
    local host=$(awk '/^remote / {print $2}' "$config_file")
    local port=$(awk '/^remote / && NF ~ /^[0-9]*$/ {print $NF}' "$config_file")

    if [ -z "$port" ]; then
        echo "-- No port number specified in the VPN profile file"
        exit 1
    else
        echo "-- Setting up firewall rules for VPN server $host on port $port"
    fi

    iptables --flush
    iptables --delete-chain

    iptables --policy INPUT DROP
    iptables --policy OUTPUT DROP
    iptables --policy FORWARD DROP

    iptables -A INPUT -i lo -j ACCEPT
    iptables -A INPUT -i tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -i eth0 -p tcp -s $host --sport $port -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -i eth0 -p tcp -s {VPN_NETWORK_GW} --dport {SB_TRANSMISSION_PORT} -j ACCEPT # (1)

    iptables -A OUTPUT -o lo -j ACCEPT
    iptables -A OUTPUT -o tun0 -j ACCEPT
    iptables -A OUTPUT -o eth0 -d {VPN_NETWORK_GW} -p tcp --sport {SB_TRANSMISSION_PORT} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # (2)
    iptables -A OUTPUT -o eth0 -p tcp -d $host --dport $port -m owner --gid-owner vpn -j ACCEPT

    set +e
}

if [[ $# -ge 1 ]]; then
    exec "$@"
else
    if [ -f /vpn-profiles/profile ]; then
        echo "-- Profile file found: only it will be used"
        PROFILE_FILE="/vpn-profiles/profile"
    else
        echo "-- Profile file not found: random profile file will be picked"
        PROFILE_FILE="$(ls -1 /vpn-profiles/*.ovpn | shuf -n 1)"
        echo "-- Selected profile file: $PROFILE_FILE"
    fi

    configure_iptables "$PROFILE_FILE"

    exec sg vpn -c "openvpn --config $PROFILE_FILE --verb 1 --auth-user-pass /vpn-credentials/credentials --auth-nocache --script-security 2 --route-up /usr/local/bin/start-transmission.sh"
fi
  1. Replace {VPN_NETWORK_GW} with the default gateway address of your VPN Docker network {SB_VPN_SUBNET}. For example, if your {SB_VPN_SUBNET} is 172.18.0.0/24 the gateway address would be 172.18.0.1. Also, replace {SB_TRANSMISSION_PORT} with the actual port number.

  2. Same as above.

Mark this script as executable:

sudo chmod a+x docker-entrypoint.sh

Finally, create the settings.json file with the following content:

/root/silverbox/containers/transmission/settings.json
{
    "rpc-enabled": true,
    "rpc-bind-address": "{SB_TRANSMISSION_ADDR}", # (1)
    "rpc-port": {SB_TRANSMISSION_PORT}, # (2)
    "rpc-whitelist": "{VPN_NETWORK_GW}", # (3)
    "rpc-whitelist-enabled": true,

    "alt-speed-enabled": false,
    "speed-limit-down-enabled": true,
    "speed-limit-down": 2500,
    "speed-limit-up-enabled": true,
    "speed-limit-up": 200,

    "blocklist-enabled": false,

    "download-dir": "/data/downloads",
    "incomplete-dir-enabled": false,
    "rename-partial-files": true,
    "start-added-torrents": true,
    "trash-original-torrent-files": true,
    "watch-dir-enabled": true,
    "watch-dir": "/data/torrentfiles",
    "umask": 7,

    "cache-size-mb": 16,
    "prefetch-enabled": true,

    "encryption": 1,

    "message-level": 2,

    "dht-enabled": true,
    "lpd-enabled": false,
    "pex-enabled": true,
    "utp-enabled": false,

    "bind-address-ipv4": "127.0.0.1",

    "peer-limit-global": 100,
    "peer-limit-per-torrent": 40,
    "peer-congestion-algorithm": "",

    "peer-port": 51413,
    "peer-port-random-on-start": false,
    "port-forwarding-enabled": false,

    "download-queue-enabled": true,
    "download-queue-size": 5,
    "queue-stalled-enabled": true,
    "queue-stalled-minutes": 30,
    "seed-queue-enabled": true,
    "seed-queue-size": 3,

    "alt-speed-time-enabled": false,
    "idle-seeding-limit-enabled": false,

    "ratio-limit-enabled": true,
    "ratio-limit": 1.2
}
  1. Replace {SB_TRANSMISSION_ADDR} with some address from the {SB_VPN_SUBNET} that Transmission container will be running on.

  2. Replace {SB_TRANSMISSION_PORT} with the actual port number. Make sure this is number and not string in quotes.

  3. Replace {VPN_NETWORK_GW} with the actual address.

Note
Feel free to adjust the values in the settings.json file according to your needs.