One of the fastest and easiest ways to download files is through BitTorrent, but there is content that only a small number of people have and the download can take hours or even days. In these cases, it is worth having a dedicated download server exclusively for this task, so it will not be necessary to leave our computer on all that time. This article will explain how to install a headless transmission server, how to configure a client to manage downloads from our PC, and how to share downloaded content using ZFS-NFS4.
The article is composed of different sections:
- Jail mounting and parent configuration
- Download directory
- Minimum jail configuration
- Transmission installation and configuration
- Client installation, configuration, and management
- NFS access
- Firewall
- Client NFS access
- Download script
- Debug
Jail mounting and parent configuration:
For greater versatility and convenience, we are going to mount the server on an
Iocage
jail:
iocage set ip4_addr=“nfe0|192.168.69.7/24” Lomax
iocage list
+-----+---------+-------+--------------+--------------+
| JID | NAME | STATE | RELEASE | IP4 |
+=====+=========+=======+==============+==============+
| 10 | Lomax | up | 12.2-RELEASE | 192.168.69.7 |
+-----+---------+-------+--------------+--------------+
Transmission requires higher than normal UDP buffers, if we don’t increase them we will see the following error in the messages log when starting the service:
Nov 17 22:10:19 Lomax transmission-daemon[2775]: UDP Failed to set receive buffer: requested 4194304, got 42080 (/wrkdirs/usr/ports/net-p2p/transmission-daemon/work/transmission-3.00/libtransmission/tr-udp.c:97)
FreeBSD by default has the following values:
kern.ipc.maxsockbuf: 2097152
net.inet.udp.recvspace: 42080
We modify them through the sysctl.conf file:
kern.ipc.maxsockbuf=5242880
net.inet.udp.recvspace=4194304
We apply the changes:
Note that we are modifying the parameters for all jails, in the jail itself it is not possible to do so since the kernel is shared, if we try we will get the following error message:
sysctl: kern.ipc.maxsockbuf=5242880 at line 10: Operation not permitted
sysctl: net.inet.udp.recvspace=4194304 at line 11: Operation not permitted
Download directory:
We create a dataset with compression enabled, this directory will be linked in the jail and will serve as the download directory:
We access the jail and assign a password to the root account:
passwd
We create the download directory:
exit
We link the dataset with the jail’s download directory:
iocage fstab -l Lomax
+-------+---------------------------------------------------------------------------------------------------+
| INDEX | FSTAB ENTRY |
+=======+===================================================================================================+
| 0 | /storage/torrents /zroot/iocage/jails/Lomax/root/storage/torrents nullfs rw 0 0 |
+-------+---------------------------------------------------------------------------------------------------+
We restart the jail:
iocage start Lomax
Minimum jail configuration:
We access the jail to install the base software and add a user:
We install some basic programs and Python:
pkg install vim htop bash screen py37-pip curl
We install the requests package using pip:
We enable and start the Ssh service:
service sshd start
We create a regular user with whom we will operate:
Login group is kr0m. Invite kr0m into other groups? []: wheel
Shell (sh csh tcsh bash rbash nologin) [sh]: bash
Transmission installation and configuration:
Now that we have our user and Ssh enabled, we can continue with the rest of the steps from an Ssh console:
su -l
We install transmission:
We can see the configuration parameters allowed in the rc.conf file in the following file:
In our case, we only need to modify the download directory:
Regarding the flags, we will have to consult the man:
In my case, I have to allow access to the ip addresses of the jail itself and my pc, in addition to ip filtering, we assign a user and password:
NOTE: We should never restart the service, as it seems not to reload the configuration, so we will do a stop/start.
We will modify the rest of the configuration parameters in the settings.json file, stopping the service beforehand:
vi /usr/local/etc/transmission/home/settings.json
service transmission start
Solo modify the parameters that we cannot modify by the two methods described above, if we do not respect this rule, transmission will overwrite our configuration.
We change the permissions of the download directory:
We enable and start the service:
service transmission start
We check that it has started with the correct parameters:
transmission 89161 0.4 0.3 41292 12172 - SsJ 12:59 0:00.07 /usr/local/bin/transmission-daemon -g /usr/local/etc/transmission/home -w /storage/torrents -x /var/run/transmission/daemon.pid -a 192.168.69.4,192.168.69.7 -t -u kr0m -v PASSWORD
Installation, configuration, and management of the client:
We install Transmission on the PC to be able to manage downloads remotely:
We check that both the IP filter and the user/password work:
ID Done Have ETA Up Down Ratio Status Name
Sum: None 0.0 0.0
Adding a torrent is as simple as indicating its URL:
We can also pass it a magnet link:
Checking the download status:
ID Done Have ETA Up Down Ratio Status Name
1 0% None Unknown 0.0 0.0 None Idle debian-10.6.0-arm64-xfce-CD-1.iso
2 n/a None Unknown 0.0 0.0 None Idle Lynda+-+Learning+Debian+Linux+[AhLaN]
Sum: None 0.0 0.0
To remove a torrent, we must pass the ID of the torrent to be removed and the -r parameter:
Multiple torrents can be removed with a single command:
To operate with Transmission in a simpler way, we can create the following alias:
alias tsm="transmission-remote 192.168.69.7 --auth kr0m:PASSWORD"
Now checking the torrents is as simple as this:
ID Done Have ETA Up Down Ratio Status Name
1 n/a None Unknown 0.0 0.0 None Idle Lynda+-+Learning+Debian+Linux+[AhLaN]
3 54% 398.4 MB 1 min 0.0 11717.0 0.0 Downloading debian-10.6.0-arm64-xfce-CD-1.iso
Sum: 462.2 MB 0.0 15387.0
NFS Access:
One of the advantages of serving downloaded content via NFS is that if it is a multimedia file, we can stream it directly from the server without having to copy the file to our computer.
NFS access will be done from the parent of the jail, we enable the NFS4 service and start it:
sysrc nfsv4_server_enable="yes"
sysrc nfsuserd_enable="yes"
service nfsd start
We share the directory restricting access by IP:
NOTE: With the mapall=root option, we make NFS accesses with the root user, all accesses from clients have the root permissions of the remote server, if we did not configure it, we should have the same users with the same UIDs/GIDs both on the NFS server and on all clients to which we give access.
My first idea was to map it to the transmission user and not to root, but since we share it from the parent, the transmission user does not exist and NFS4 no longer allows mapping by UID :
uid/gid numbers are no longer used in the NFSv4 protocol
Firewall:
We configure the firewall rules so that only our PC has access to NFS and the Transmission RPC configuration service. To make the rules clearer, I indicate below the correspondence of the IP addresses:
- PC: 192.168.69.4
- Father: 192.168.69.2
- Jail: 192.168.69.7
# Torrent NFS access:
# NFS access:
# NFS: Port tcp/udp 111
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 111 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 111 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 111 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 111 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 111 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 111 in via $wanif
# NFS: Port tcp/udp 950
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 950 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 950 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 950 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 950 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 950 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 950 in via $wanif
# NFS: Port tcp/udp 2049
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 2049 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 2049 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 2049 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 2049 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 2049 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 2049 in via $wanif
# NFS: Port tcp/udp 882
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 882 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 882 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 882 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 882 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 882 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 882 in via $wanif
# Transmission Lomax RPC:
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.7 9091 in via $wanif
$cmd 00805 allow tcp from 192.168.69.7 9091 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.7 9091 in via $wanif
# All other Lomax traffic
$cmd 00805 allow all from any to 192.168.69.7 any in via $wanif
$cmd 00805 allow all from 192.168.69.7 any to any out via $wanif
We restart the ipfw service:
NFS client access:
From my PC, we can see the resources served by NFS:
Exports list on 192.168.69.2:
/storage/torrents 192.168.69.4
We mount the /storage/torrents resource:
mount 192.168.69.2:/storage/torrents /nfs/torrents
We can automate the process through a simple script, but we will have to grant some permissions to our user:
kr0m ALL=(ALL) NOPASSWD: /sbin/mount 192.168.69.2\:/storage/torrents /nfs/torrents
kr0m ALL=(ALL) NOPASSWD: /sbin/umount /nfs/torrents
We will generate the script from our user kr0m:
#!/usr/local/bin/bash
mount|grep '192.168.69.2:/storage/torrents'
if [ $? -eq 1 ]; then
echo -e "-- Mounting NFS: /nfs/torrents"
sudo /sbin/mount 192.168.69.2:/storage/torrents /nfs/torrents
else
echo -e "-- Umouning NFS: /nfs/torrents"
sudo /sbin/umount /nfs/torrents
fi
We assign the necessary permissions:
Download script:
Transmission is capable of executing a script every time a download finishes. Our script will send a Telegram with the name of the recently downloaded torrent and remove it from the list of torrents:
#!/usr/local/bin/bash
function sendTelegram {
message=${@:1}
/usr/local/bin/curl -s -X POST https://api.telegram.org/botAPI_KEY/sendMessage -d chat_id=CHAT_ID -d text="$message"
}
tsm='/usr/local/bin/transmission-remote 192.168.69.7 --auth kr0m:PASSWORD'
DOWNLOADED=$($tsm -l | /usr/bin/awk '$2 == "100%" {print $10" "$11" "$12" "$13" "$14" "$15" "$16" "$17" "$18" "$19" "$20}')
IFS_ORI=$IFS
IFS=$'\n'
for TORRENT in $DOWNLOADED; do
/bin/echo "TORRENT: $TORRENT"
msg="Downloaded: $TORRENT"
sendTelegram $msg
done
IFS=$IFS_ORI
DOWNLOADED_IDS=$($tsm -l | /usr/bin/awk '$2 == "100%" {print $1}')
for ID in $DOWNLOADED_IDS; do
/bin/echo "ID: $ID"
$tsm -t $ID -r
done
We assign the necessary permissions and change the owner of the script:
chown transmission:transmission /usr/local/etc/transmission/home/notifyTorrentDownload.sh
We stop the service:
We modify the configuration to take into account the script:
"script-torrent-done-enabled": true,
"script-torrent-done-filename": "/usr/local/etc/transmission/home/notifyTorrentDownload.sh",
We start the service:
When a torrent finishes, we will receive a notification via Telegram similar to the following:
Debug:
We stop the service:
We start the service in foreground as root:
When we finish, we will have to rectify some file permissions generated while the process was running as root:
chown -R transmission:transmission /storage/torrents/
We start the service regularly:
Transmission writes its logs in /var/log/messages, so we check in this file that no errors appear:
It is also possible to execute commands with the transmission user, but for this we will have to temporarily change the shell, execute the command, and revert the change:
su transmission -c “/usr/local/etc/transmission/home/notifyTorrentDownload.sh”
chsh -s /usr/sbin/nologin transmission