The XU4 Shellbox - An always-encrypted local seedbox

Moderators: meveric, mdrjr, odroid

The XU4 Shellbox - An always-encrypted local seedbox

Unread postby jsherm101 » Wed Oct 05, 2016 4:10 pm

Seedboxes are far from new, but I've yet to find one that will do everything that i wanted with my ODROID XU4, especially when integrated with the CloudShell case and LCD interface. This guide will show you how to build a seedbox that is:

  • Powered by the ODROID XU4
  • Uses an SSD with SATA connectivity for high speed transfers and read/write speeds
  • Runs the operating system and cache on the hard drive to reduce fatigue on the SD card
  • Supports web-access to Transmission for remote downloading
  • Automatically connects to a VPN upon boot for maximum security

So while nothing here is original, here's a sure-fire way to begin with a ODROID XU4 and a CloudShell kit, and end up with a working seedbox with all of these great features.


To make things easier for my dad, I built him a seedbox NAS last year for all of his downloading and storage needs. It used an old RPi 2 I had lying around before i found out about the far more poweful (and USB 3.0 capable) ODROID XU4. I used that RPi 2 to build him a seedbox that was a good start, but not a single unit and with high-speed

I also realized how convenient and well packaged the ODROID CloudShell is, so i decided to put two great things together and write a guide around turning a Cloudshell into a seedbox with VPN capabilities. There are other guides out there, often geared toward the RPi or VPSes, but I really prefer turn-key guides that don't require sifting through three different sets of instructions that don't address the nuances of the ODROID, ARM architecture, or the specific tools I want to use to achieve my ideal build. This will be a newer, faster, and sleeker upgrade to his Pi2!

Some credit is deserved to PiMylife and MakeUseOf, who had very useful Raspberry Pi guides that I’ve adapted for the XU4 and CloudShell. I also took some snippets / instructions from some ODROID community members on how to properly configure this guide for the XU4 and CloudShell. All in all this should run for less than $200, and offer anything you'd want out of a home seedbox or single drive NAS.

First, our parts:

  • CloudShell XU4 kit (featuring a USB 3.0 to SATA adapter and 2.2-inch TFT LCD Display)
  • RTC Battery
  • 256GB SSD (or other 2.5-inch storage device of your choice)
  • 32GB micro-SD Card (Or other OS drive of your choice)
  • VPN subscription with OpenVPN support

For the VPN provider: I use Torguard. If you're interested in finding a new VPN provider and find this guide useful, you can go to their website or use my referral link:

And here's a picture of all those parts in their glory!


To VPN or not to VPN:

This guide does include a step with setting up traffic encryption through a Virtual Private Network (VPN). I highly recommend you use a VPN with a seedbox or NAS you're using for downloading content for security and peace-of-mind. You sacrifice your peak speed capabilities if you have a fiber optic or other high speed Internet connection, but many VPN providers can offer fairly good speeds despite routing all traffic through a third party server. Plus, you can still locally access those files, maximizing connectivity and the value of the USB 3.0 to SATA connectivity.

Local or online?

This guide is for a local seedbox setup. Can you do it online? Sure, but you open yourself up to a number of security risks. This guide involves plain text passwords (for the sake of simplicity and a local-only implementation) to make it easier to configure the VPN connection on each launch. You may not need this depending on if you want a VPN, if your VPN service provider doesn't need a username and password, etc. There also may be a more secure way to implement this, so feel free to make suggestions in the thread for anyone else considering such a build. I went this way as it's based on a previous method that I knew worked and meets my personal needs in having a local NAS with 100 percent encrypted traffic.

Getting Started

First we will update our ODROID, as this is guide starts with running an out-of-the-box 16.04 Ubuntu MATE image.

Code: Select all
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade

This will take awhile. We could use a more minimal image, but this guide is geared toward simplicity. Go get some coffee and come back when it's done! Here's a closer look at the guts of this build in the meantime:


Next we want to configure our seedbox’s CloudShell display to make sure it works. We start with smartmontools:

Code: Select all
$ sudo apt install smartmontools

Now we need to follow ODROID’s instructions to configure the frame buffer for our TFT display in the CloudShell:

Code: Select all
$ sudo -s
$ echo "options fbtft_device name=hktft9340 busnum=1 rotate=270" > /etc/modprobe.d/odroid-cloudshell.conf
$ echo "spi_s3c64xx" >> /etc/modules
$ echo "fbtft_device" >> /etc/modules

Next we'll remove the blacklist on the Serial Peripheral Interface (SPI) through which our ODROID XU4 and CloudShell are connected. We do this by opening blacklist-odroid.conf:

Code: Select all
$ sudo nano /etc/modprobe.d/blacklist-odroid.conf

When you're finished, it should look like this. Note the two SPI rows and LCD row are now commented:

Code: Select all
# Comment the required lines

# IO Board
blacklist ioboard_bh1780
blacklist ioboard_bmp180
blacklist ioboard_keyled

# blacklist spidev
# blacklist spi_s3c64xx

# 3.2" LCD Touchscreen driver
blacklist ads7846

Now we can reboot our XU4, but make sure you don't have any HDMI cables connected to it to ensure it connects to the LCD display.


Success! But the display is blank...We want it to show all sorts of useful info about our CloudShell, so let's use a useful script to do this for us. Eventually we'll be using /dev/sda2 as our storage drive, so let's modify mdrjr's application and install it:

Code: Select all
$ sudo apt-get install curl sysstat
$ wget
$ sudo dpkg -i cloudshell-lcd_20160913-3-fixed.deb

If we reboot again, it should now show some useful information about the device, such as:

    CPU usage and temperature
    RAM availability
    The local IP address of the device
    Transfer rates
    Disk usage (right now empty, because we haven’t configured our /dev/sda2 drive)


Configuring Our Installation

Next comes the meat of this project: Getting a BitTorrent protocol app to play nice with our SSD. This is all nothing more than an apt-get command if we wanted to use our SD Card where the OS is installed, but this poses two issues:

First, there are large SD cards (>256GB), but they're more expensive or slower than their SSD and HDD counterparts.
Second, an SD card has a much shorter read/write lifecycle than an SSD or HDD, and will fail sooner.

To solve this, we're going to actually move our ODROID installation to the SSD and boot from the SSD for both our operating system and our additional NAS storage folder. All credit goes to James @ MakeUseOf for this great idea. This might not be a concern for most practical uses, but is done as a precaution in this build given the high number of reads and writes anticipated in regular use.

Once we complete this, we'll be installing Transmission as our BitTorrent software of choice. It's fairly equal in usage to Deluge and other clients, and comes down to a matter of preference in this case. Both Transmission and Deluge support web-based GUIs and server-client configurations for remote access.

Now let’s configure our storage drive. We’ve already plugged it into our assembled CloudShell and the necessary SATA-to-USB drivers are configured with smartmontools, so it should appear in fdisk in the first drive:

Code: Select all
$ sudo fdisk /dev/sda1

My drive is currently an NTFS drive from an old Windows installation. We'll want to press "d" in fdisk to delete the partition, then "n" to create a new one, then "p" for primary partition. We're ultimately creating two partitions: One for the OS we're moving to the SSD, and one for the storage area we'll share over the local network.

Create the first partition at the first sector available (probably 2048) and then type "+16G" to create a 16GB partition in size. Then start again typing "n" and "p" to create a second partition with the remaining storage on the drive. My 256GB SSD left about 208 GB after accounting for capacity formatting and the installation partition.

Once we're finished, type "w" to write the new partitions to the SSD.

Next we convert both parittions into the ext4 format and mount them to the two folders we've set aside for this project:

Code: Select all
$ sudo mkfs.ext /dev/sda1
$ sudo mkfs.ext /dev/sda2
$ sudo mkdir /media/systemdrive
$ sudo mkdir /media/NAS1
$ sudo mount /dev/sda1 /media/systemdrive
$ sudo mount /dev/sda2 /media/NAS1
$df -h (to see a list of drives and confirm everything is in order)

Once you've finished this, your drive configuration should look something like this.


Now we can use rsync to move over our data on the SD Card to the SSD. Before we do this, we should make a backup of the boot.ini file we'll end up editing, which is in the FAT boot partition of the SD Card:

Code: Select all
$sudo cp /media/boot/boot.ini /media/boot/boot.ini.bak

Now we need to find the UUID of the unique partition we made earlier.

Code: Select all
$ lsblk -f

Mine is: 7d62ae29-a3cf-41d0-9127-065cfc08fbe6, for this build as an example.

Now we can open boot.ini and search for “Basic Ubuntu Setup.” you can search in Nano with CTRL+W

Code: Select all
$ sudo nano /media/boot/boot.ini

Comment out the line that’s currently below it. That is our original configuration for booting to the SD Card. We can always revert if anything goes wrong by plugging the SD Card into any device (PC or *nix) and re-editing the boot.ini file.

Below it, we’ll add our own new instructions:

Code: Select all
## Boot from USB device
setenv bootrootfs "console=tty1 consoleblank=0 root=UUID=7d62ae29-a3cf-41d0-9127-065cfc08fbe6 rootwait rootdelay=10 ro"

Just make sure the UUID is whatever UUID comes up for your 16GB system partition under /dev/sda1.

Now, before we use rsync to transfer over to the new partition, we need to edit fstab to mount our new drives on startup:

Code: Select all
$ sudo nano /etc/fstab

Comment out the first line and now add these two lines below, assuming you've used the same partition names and folders as me:

Code: Select all
$ /dev/sda1 / ext4 defaults,noatime 0 1
$ /dev/sda2 /media/NAS1 ext4 defaults 0 2

Finally, we can move over our OS from the SD Card to the new partition we've set aside for it. Keep in mind that once you've done this, any changes to the OS won't appear after you restart the computer, as you'll be working from the new partition. It's best to reboot once you finish this rsync command:

Code: Select all
$ sudo apt-get install rsync
$ sudo rsync -axv / /media/systemdrive

You'll probably have some time to grab a coffee (or two) while this transfers. To elaborate on what's happening, we're copying over our entire OS to /media/systemdrive, where we've mounted our /dev/sda1 partition. Keep in mind that after we restart, our fstab + boot.ini will remount and redirect the /dev/sda1 partition to "/" and serve as our operating system. We'll still be using the boot partition of your SD Card, so don't remove it!

Once it finishes, it's time to reboot and hold our breath:

Code: Select all
$ sudo reboot

If we successfully reboot, then we're definitely working from one of our two partitions, either on the SD card or SSD. You can confirm we're using the SSD by checking our partitions again:

Code: Select all
$ lsblk -f

You should see /sda/1 mounted at "/" to confirm our success.


Configuring Transmission

Okay, so we have our operating system transferred, and our display is showing our fancy 256GB SSD in working condition.


Now we need to install Transmission and setup our tranmission-daemon. We'll be using our odroid default user, as well as be configuring our drive to have an incomplete and complete folder to

Let's start by installing Transmission and adding our new incomplete and complete folders:

Code: Select all
$ sudo apt-get install transmission-daemon
$ sudo mkdir -p /media/NAS1/incomplete
$ sudo mkdir -p /media/NAS1/complete

Now we need to configure Transmission by turning off its services and opening the settings file:

Code: Select all
$ sudo service transmission-daemon stop
$ sudo nano /etc/transmission-daemon/settings.json

You’ll want to configure several settings:
  • Set your incomplete to “true” and “media/NAS1/incomplete”
  • Set your complete to “media/NAS1/complete”
  • Set rpc-authentication-required to “false”
  • Set the whitelist to 192.168.*.* to ensure you can access it remotely from another device on your network.

    Each of the rows we edited should look like this, scattered around the settings file:

    Code: Select all
    "download-dir": "/media/NAS1/complete",
    "incomplete-dir": "/media/NAS1/incomplete",
    "incomplete-dir-enabled": "true",
    "rpc-authentication-required": "false",
    "rpc-whitelist": ",192.168.*.*,10.0.*.*",

    There are also some other settings you can adjust, and i recommend checking out the Transmission website for instructions on how to configure your tool.

    Before we start our transmission-daemon, we need to change ownership to our user ODROID to make everything work properly. There are more ideal ways of doing this, but i prefer to stick to a single user since this server will have no other purpose other than as a seedbox and I don't see a need in this situation to stick to the transmission-daemon user that Transmission normally intends to use.

    Code: Select all
    $ sudo chown -R odroid:odroid /etc/transmission-daemon
    $ sudo chown -R odroid:odroid /etc/init.d/transmission-daemon
    $ sudo chown -R odroid:odroid /var/lib/transmission-daemon
    $ sudo chown -R odroid:odroid /media/NAS1/

    We also need to open the Transmission daemon service and set user="odroid" from "transmission-daemon"

    Code: Select all
    $ sudo nano /etc/systemd/system/

    We also want to do this in the init.d file, switching in "odroid" for "USER"

    Code: Select all
    $ sudo nano /etc/init.d/transmission-daemon

    Lastly, let’s reset that related Transmission daemon and turn back on Transmission:

    Code: Select all
    $ sudo systemctl daemon-reload
    $ sudo service transmission-daemon start

    Configuring Samba

    Now we have everything we need to download a file, but we need a way to access the files we download over our local network. If you’re using a Windows device, then Samba is the way to go. Let’s get started by installing it and configuring our network share. We will need to configure it in a way that allows us to login with our odroid user and easily download files, as well as remove files we no longer want on our seedbox:

    Code: Select all
    $ sudo apt-get install samba samba-common-bin
    $ sudo nano /etc/samba/smb.conf

    Let's add the following as a new config for sharing our relevant folders:

    Code: Select all
    security = user

    comment = odroid
    path = /media/NAS1
    valid users = @odroid
    force group = odroid
    create mask = 0775
    force create mode = 0775
    security mask = 0775
    force security mode = 0775
    directory mask = 2775
    force directory mode = 2775
    directory security mask = 2775
    force directory security mode = 2775
    browseable = yes
    writeable = yes
    guest ok = no
    read only = no

    Before we move on, we’ll need to set a Samba password for our odroid user. You can also create separate accounts if you so choose, as long as those users are in the odroid group:

    Code: Select all
    $ sudo smbpasswd -a odroid

    Now we can restart, and we should be able to remotely access our seedbox folders!

    Code: Select all
    $ sudo service smbd restart

    Keep in mind that you can always add new compatible users, as long as you set a proper Samba password and add those users to the "odroid" group or whichever group you assign access to for these files.

    Configuring the VPN

    Finally, we’ll want to configure our VPN for an automatic secure connection upon boot, once again with thanks to the James @ MakeUseOf who figured out this fast and easy way to get your VPN working without needing to manually start the VPN or enter credentials each time you restart your device. This is essential if you want to guarantee the encryption of your connection while using the seedbox. In this guide, we’re using an OpenVPN connection, which depends on:

    • An OpenVPN configuration file
    • A certificate from your VPN provider
    • Your username and password for your VPN provider stored in a text file
    • Three special shell scripts to start our VPN automatically upon boot and route traffic

[u]Note:[u] Yes, storing a password in text is not ideal. However, it’s the fastest and leanest way to get things going, and since we’re only using this locally, having your VPN credentials stored on this device will not risk the files to those outside your home network. If you want to host your seedbox with port forwarding and essentially open to the Internet, I highly recommend either searching for an alternative method or considering these risks before proceeding.

Let’s install the OpenVPN software:

Code: Select all
$ sudo apt-get install openvpn resolvconf

We’re going to leave everything in our home folder (/home/odroid in this case) while doing this. It really can be anywhere, but these are not files you want in the same place where people on your home network will connect and download files from your seedbox.

First, get your OpenVPN configuration file (referred to as vpn-server.opvn in this guide) and place it in your home folder along with your certificate file (referred to as ca.crt in this guide). Now create a new text file (.txt) with two lines. The first line should be the username of your VPN connection service, and the second line should be your VPN connection service’s password:

Code: Select all
$ sudo nano /home/odroid/pass.txt
$ username
$ password

Next, we’re going to open our configuration file, which in my case is “vpn-server.opvn”:

Code: Select all
$ sudo nano /home/odroid/vpn-server.opvn

We’re going to add the following line at the bottom, which will let us connect to the VPN provider without entering the credentials manually:

Code: Select all
$ auth-user-pass /mnt/torrents/openvpn/pass.txt

Now we’re going to add these three lines which refer to the shell scripts we’re about to create:

Code: Select all
$ route-up /home/odroid/
$ down-pre
$ down /home/odroid/

This will allow OpenVPN to connect to our VPN provider automatically. Once it connects, it will automatically route all traffic through these VPN connection, whether incoming ( or outgoing (

Next we’re going to create these two shell scripts:

Code: Select all
$ sudo nano /home/odroid/

Enter the following for

Code: Select all
iptables -t nat -I POSTROUTING -o tun0 -j MASQUERADE

And for

Code: Select all
$ sudo nano /home/odroid/

Enter the following for

Code: Select all
$ #!/bin/sh
$ iptables -t nat -D POSTROUTING -o tun0 -j MASQUERADE

Lastly, we need a shell script that we can launch when our OS boots and use to initiate the VPN connection automatically:

Code: Select all
$ sudo nano /home/odroid/

Enter the following for

Code: Select all
$ sudo openvpn --client --config /home/odroid/vpn-server.ovpn --ca /home/odroid/ca.crt --script-security 2

Great, we’re all set. Now let make all of these files executable:

Code: Select all
$ sudo chmod +x /home/odroid/
$ sudo chmod +x /home/odroid/
$ sudo chmod +x /home/odroid/

Now we’re going to open up our rc.local file, which runs scripts upon system startup:

Code: Select all
$ sudo nano /etc/rc.local

Add this line right above the “exit 0” line:

$ /home/odroid/

And that’s it! Your VPN is configured and your seedbox will now download exclusively through an encrypted connection with your VPN provider.

You can easily test this by using the TorGuard test file which checks your IP address when downloading the file.

Connect to your Transmission web GUI at odroid:9091, or whatever your local IP address is.
Upload the TorGuard test file and check the IP address reported as “Success! Your torrent client IP is XX.XX.XX.XX”
Check this IP address against what Google reports as your IP address by searching “What is my IP Address?”


If the IP addresses are different, then your connection is secure! You can still use your local IP address to access and download files via Samba. In terms of performance, you can see download

my VPN provider allows me to hit speeds around 75 Mbps, with the ODROID XU4 peaking at around 22 percent CPU usage, showing just how powerful the octa-core processor is for tasks such as these. But the real glory is the transfer speeds from your ODROID to your personal computer. I saw 800 Mbps transfer speeds when moving some files back and forth, making this seedbox also an extremely viable Network Attached Storage Device too.


Feel free to offer any comments or suggestions. This is hardly perfect, but it's a surefire way for anyone to get started with their very own seedbox!

User avatar
Posts: 6
Joined: Thu Dec 11, 2014 9:32 am
languages_spoken: english

Re: The XU4 Shellbox - An always-encrypted local seedbox

Unread postby mad_ady » Fri Oct 07, 2016 3:09 am

Very nice and friendly tutorial! You could add a cron job that runs fstrim on your emmc/ssd periodically to help it keep its speed.
User avatar
Posts: 3334
Joined: Wed Jul 15, 2015 5:00 pm
Location: Bucharest, Romania
languages_spoken: english
ODROIDs: XU4, C1+, C2

Re: The XU4 Shellbox - An always-encrypted local seedbox

Unread postby MattiA » Tue Aug 29, 2017 1:07 am

Thank you for this useful advice. I wanted to keep my XU4 booting from my eMMC. This means my USB drive is /dev/sda1. I mounted it to /media/NAS1. Sysstat readings related to drive use on the lcd-monitor are now empty (since no /dev/sda2 existst). What should I do to get the right readings to the lcd-monitor?
Posts: 11
Joined: Wed Apr 02, 2014 11:12 pm
languages_spoken: english
ODROIDs: Odroid-XU
Odroid - xu3
Parallella-16 Z-7020

Re: The XU4 Shellbox - An always-encrypted local seedbox

Unread postby mad_ady » Tue Aug 29, 2017 2:47 am

Instead of reading from /dev/sda1/2 try reading from /dev/disk/by-uuid/your-uuid instead
User avatar
Posts: 3334
Joined: Wed Jul 15, 2015 5:00 pm
Location: Bucharest, Romania
languages_spoken: english
ODROIDs: XU4, C1+, C2

Return to Ubuntu (All Linux'es)

Who is online

Users browsing this forum: No registered users and 2 guests