LJ Archive

DIY: RV Offsite Backup and Media Server

What better way to add a geeky touch to #vanlife than with a Linux server in your RV? By Kyle Rankin

Kyle

One easily could make the strong argument that an RV is the ultimate DIY project playground. It combines all of the DIY projects you could perform on a vehicle with the DIY projects for a home. Add to that the fact that you may spend days living in a small house on wheels navigating highways, forests and deserts, and you have a whole other class of DIY projects to make the most of that smaller space. RVs also offer a whole suite of power options from 12V deep cycle batteries to 110V shore power to generators and alternators to solar power, so there's a whole class of electrical DIY projects related to making the most of your changing power options.

And if you're a geek, having an RV introduces a whole other level of DIY possibilities. First, there are all of the electronics projects to manage switching between power sources, tracking energy consumption and keeping those batteries charged. Then there's an entire category of projects related to internet access while away from home that involve everything from mobile WiFi hotspots to cellular-boosting networks to roving satellite internet (and if you're clever, a smart router that routes you to the best and cheapest available option). Finally, there are several project possibilities related to the computer systems in the RV, including local switches and routers, personal computers that turn the RV into a mobile office, and media centers so you can watch TV and movies from the road.

It just so happens that I recently got an RV—a 1996 Roadtrek 170 to be exact. Although this purchase has spawned a huge list of DIY projects, my very first Linux-based project focuses on the media center. At home, my media center is a Raspberry Pi running OSMC, and it works great for accessing my ripped DVDs and CDs from my NAS and playing them on my living-room TV. When I got the RV, I realized that one of the first things we'd want is a way to access all of that media from the road, even if we were in the middle of the woods.

In this article, I describe all the steps I took to build a media server just for the RV that maintains an up-to-date copy of my media and even syncs up automatically when it's parked in my driveway. It turns out that in the process of building a media server, I ended up with a pretty great off-site backup solution as well. Even if you don't own an RV, you could adapt these steps to add your own semi-offsite backup to your car.

Van Winkle

Figure 1. Introducing "Van Winkle"

Bill of Materials

Before I go through each step of this project, I want to post the complete list of hardware I used. I try to explain why I chose the hardware I did below, and depending on your needs, some of this hardware might be optional. For instance, if you have good WiFi reception from your vehicle, you may not need the WiFi extender I bought. If you just want to build an offsite file backup solution without any media playback, you wouldn't need to buy the TV or mounting brackets.

Step 1: Media Server Hardware

The first step in this process was selecting the hardware and software for the media server itself. Since the hardware was going to run from my RV "house battery", the lower-power the better. I had planned on using some form of pre-made distribution for the Kodi media center software (I was torn between OpenELEC, LibreELEC and OSMC), so I wanted to choose hardware that was well supported by those distributions. Since the computer was going to perform media playback, and all of these low-power devices have relatively slow general-purpose ARM CPUs in them, it also was important that the distributions on my list could take advantage of hardware-accelerated playback for common media codecs. I wanted to sync my files over to this hardware wirelessly, so it was also important that the hardware have a wireless card. Finally, because I planned on attaching a large external USB3 hard drive to the computer to store all of my media, ideally the computer would have a higher-speed USB3 port.

As I evaluated hardware, the first major change I made was ditching my USB3 requirement in favor of hardware-accelerated media playback. Most of the single-board computers I evaluated that had USB3 support (like the Odroid XU4 I used for my NAS) didn't have guaranteed hardware acceleration for media. As I did research on the issue though, I realized that while USB2 bandwidth is relatively low, it turns out that many people in the community stream large media over USB2 and that it should be fine for my uses. With media playback out of the way, my other concern was in syncing files from my home network, but in that case, my WiFi connection was the real bottleneck.

Now that I no longer had to worry about USB3 support, I started to limit my choices to hardware explicitly supported by LibreELEC, as it was the front-runner in my distribution selection. For my final hardware selection, I narrowed it down to the Raspberry Pi 3 B+ or an Odroid C2—a competitor to the Raspberry Pi series that promised great graphics performance and had an integrated IR sensor. In the end I settled on the Raspberry Pi 3 B+ for the following reasons:

Along with a new Raspberry Pi 3 B+, I ordered a couple SD cards and chose a generic "MCE remote" that came with a USB IR receiver. MCE remotes are designed for Windows media PCs with a standard button arrangement for media servers, and they are generally well supported in Kodi distributions, so all of the buttons work out of the box.

Another key piece of hardware was the USB disk enclosure to store all of my files. I needed a lot of media storage in a relatively small package, so I opted for an 8TB Western Digital MyBook. You can find them in local electronic stores often for much cheaper than the same 8TB drive outside an enclosure. They also are powered by a 12V barrel connector, which makes it easy to swap out its AC adapter for a direct DC power supply that connects to one of the 12V DC adapters in the RV. Of course, if you can get by with less storage, you should consider a 2.5" laptop hard drive instead, as they typically have much lower power requirements (and take up less space) compared to a 3.5" drive.

Step 2: Media Server Software

I knew that I wanted to use some kind of pre-built Kodi distribution for my media center because I already was used to that interface at home. At home, I use OSMC, but for the RV system, I was choosing between it, OpenELEC and LibreELEC. OSMC is a Raspbian-based distribution that bundles in and configures Kodi for you. OpenELEC and its more cutting-edge fork LibreELEC are more focused on optimization, and instead of being based on Raspbian, they have a more heavily customized and lightweight distribution. The end result is that OpenELEC and LibreELEC end up booting much faster.

Ad Choices Symbol

Figure 2. OSMC Running on My RV TV

At home, I typically leave my media server on all the time, even if the TV isn't on, so the amount of time OSMC takes to boot isn't an issue. In the RV, I wanted to save power, so I planned to power the Raspberry Pi off of the TV, so that it automatically turned on only when the TV was turned on. This made a fast boot time more compelling, and since LibreELEC touted cutting-edge support for my cutting-edge Raspberry Pi, I decided to try that first.

The boot times for LibreELEC were great, but unfortunately, that stripped-down fast boot time also meant there weren't a whole lot of other tools available behind the scenes. Although LibreELEC does have the option to ssh in to the server, very few other packages are available. This meant I couldn't easily install rsync, which was critical to this project.

Ultimately, I decided on OSMC. Although the boot times are longer than LibreELEC, the fact that it is based on Raspbian means I can treat the underlying server like any other Debian system. This made customizing it to suit my backup and encryption needs much simpler. It also means I could add extra capabilities to this system in the future without springing for a separate Raspberry Pi.

Step 3: Media Server Configuration

Configuring the media server itself was pretty straightforward. I just copied the latest OSMC image from https://osmc.tv onto a microSD card per the instructions and booted from it just like with any other Raspbian install. On first boot, it resizes its partition to fill up the remaining space, and on the second boot, I went to the system settings page to make sure the Ethernet network was disabled and the WiFi network was connected to my access point. This is one time when I regretted that I have a long WiFi passphrase, because I had to enter it one character at a time via the arrow keys on a remote and the on-screen keyboard. (Note to self: next time bring a USB keyboard to the RV.)

Next, I ssh'd to this system over the wireless network from another computer with the default user name:password of osmc:osmc. This means my first step after I logged in was to change that password:


$ passwd

The next step was to configure the external 8TB hard drive. In most cases, this would just mean plugging it in, but given I planned to back up potentially sensitive documents to it, I wanted to add a layer of disk encryption, so if burglars came and stole my hard drive, they wouldn't be able to retrieve any data. First, I plugged in my hard drive and checked dmesg output to confirm what device it appeared as. Because it's the only SATA-style drive connected, it should come up as /dev/sda, but you still want to be sure:


$ sudo dmesg | grep sd
. . .
[    4.805850] sd 0:0:0:0: [sda] Spinning up disk...
[    4.815562] sd 0:0:0:0: Attached scsi generic sg0 type 0
[   21.442041] sd 0:0:0:0: [sda] Very big device. Trying to 
 ↪use READ CAPACITY(16).
[   21.442279] sd 0:0:0:0: [sda] 15628052480 512-byte logical 
 ↪blocks: (8.00 TB/7.28 TiB)
[   21.442284] sd 0:0:0:0: [sda] 4096-byte physical blocks
[   21.442599] sd 0:0:0:0: [sda] Write Protect is off
[   21.442604] sd 0:0:0:0: [sda] Mode Sense: 47 00 10 08
[   21.442907] sd 0:0:0:0: [sda] No Caching mode page found
[   21.442911] sd 0:0:0:0: [sda] Assuming drive cache: write 
 ↪through
[   21.443478] sd 0:0:0:0: [sda] Very big device. Trying to 
 ↪use READ CAPACITY(16).
[   22.786525]  sda: sda1
[   22.787302] sd 0:0:0:0: [sda] Very big device. Trying to 
 ↪use READ CAPACITY(16).
[   22.788287] sd 0:0:0:0: [sda] Attached SCSI disk

Now that I know it's showing up as /dev/sda, the next step is to set up encryption. To do this, I installed the cryptsetup package on my media server and then set up LUKS encryption on the external hard drive's only partition, /dev/sda1, that takes up all the space on the drive:


$ sudo apt install cryptsetup
$ sudo cryptsetup --verbose --verify-passphrase 
 ↪luksFormat /dev/sda1

This process prompts you to set a decryption passphrase, so be sure to remember it and optionally write it down or store it in your password manager. Next, I need to open the device so I can assign it a name and format it:


$ sudo cryptsetup luksOpen /dev/sda1 crypt-sda1
$ sudo mkfs -t ext4 /dev/mapper/crypt-sda1

Now the drive is ready to be mounted, but the next time the system reboots it won't mount automatically, so now I need to configure that. Because I want the system to be able to mount this partition automatically, this means creating a key file readable only by root on this system, filling it with random contents and making that file an additional key to unlock the encrypted volume. Later I can point the system to this keyfile, but first let's set it up:


$ sudo dd if=/dev/urandom of=/root/keyfile bs=1024 count=4
$ sudo chmod 0400 /root/keyfile
$ sudo cryptsetup luksAddKey /dev/sda1 /root/keyfile

To configure the system to set up this device automatically at each boot, next I need to figure out what UUID the /dev/sda1 partition was assigned. Although I could use /dev/sda1, what if some day I add a second USB hard drive and it grabs that device first? I use the blkid command to get the UUID for the device:


sudo blkid /dev/sda1
/dev/sda1: UUID="074051d8-e239-408b-a3ba-ee28301bdee2" 
 ↪TYPE="crypto_LUKS" PARTLABEL="My Book" 
 ↪PARTUUID="a97a96bf-41a5-4358-9c33-3458ab36ddf4"

Now I've got the information I need to create a file called /etc/crypttab. This will give the system the information it requires to set up the LUKS device automatically each time it boots. My file has the following contents:


$ cat /etc/crypttab
# <target name> <source device>      <key file>    <options>
crypt-sda1 /dev/disk/by-uuid/074051d8-e239-408b-a3ba-ee28301bdee2 
 ↪/root/keyfile luks

The first field is the name you want to assign to the device (this is what shows up in /dev/mapper). The next field is the full path to the raw device. As you can see, I pointed to the device by its UUID, which means using the path in /dev/disk/by-uuid/. The next field lets me point to the key file that I created, and the last field lets cryptsetup know that this disk is using LUKS for encryption.

OSMC now will mount this USB device at boot automatically without my having to add anything to /etc/fstab. By default, it mounts it in /media/UUID, but as that would be a pain to type for the rest of my scripts, I create a symlink under /mnt that's easier to type:


$ sudo ln -s /media/f6b0e02c-c08e-45f5-bb28-5a7c360d6f72/ 
 ↪/mnt/storage

Now I can use /mnt/storage whenever I want to access this device from my scripts.

Step 4: File Syncing

The next step was to set up my file-syncing script. The initial sync would take forever on WiFi, so I unplugged the drive and connected it directly to my NAS server, used the luksOpen command from above to open it with my passphrase, and then mounted it on a temporary directory (/mnt/temp in this example). Then I could create the directories for my backups and start the initial rsync commands:


$ sudo mkdir /mnt/temp/audio
$ sudo mkdir /mnt/temp/documents
$ sudo mkdir /mnt/temp/video
$ sudo rsync -avxH /mnt/storage/audio /mnt/temp/audio
$ sudo rsync -avxH /mnt/storage/documents /mnt/temp/documents
$ sudo rsync -avxH /mnt/storage/video /mnt/temp/video

This initial rsync took quite some time to complete, so in the mean time, I set up the rest of the syncing configuration. First, I added an entry to /etc/hosts that points to my RV for when it's on the network so I don't have to refer to it by IP:


192.168.1.50   rv

Because I want to rsync files as the root user on my NAS to the root user on my RV's media server, I end up breaking a general rule of mine and allow SSH logins as root. I make up for that though by setting up SSH keys for the default "osmc" user so I can disable password login altogether. From the NAS system I'll use to ssh in, I type the following as my regular user:


$ ssh-copy-id osmc@rv

This command will prompt me for my osmc user password one last time, and from that point on, I should be able to ssh back in to the RV without a password prompt. Now that I'm on the RV computer, it's a good time to create an SSH directory for the root user:


$ sudo mkdir -p /root/.ssh
$ sudo chmod 0700 /root/.ssh
$ sudo touch /root/.ssh/authorized_keys
$ sudo chmod 0600 /root/.ssh/authorized_keys

Since my rsync script will run as root (so it can make sure to have access to all the local files it is backing up), I also need to copy my root user's public SSH keys over. If your root user doesn't have SSH keys yet, just type the following to generate them:


$ sudo ssh-keygen -t rsa

Then copy and paste the contents of /root/.ssh/id_rsa.pub on your home file server to the /root/.ssh/authorized_keys file on your RV computer. Since I haven't enabled the root user yet (and the root user is disabled and doesn't have a password by default in OSMC), I have to use this method instead of ssh-copy-id.

Next I edit the /etc/ssh/sshd_config file on the RV server and make sure that the PasswordAuthentication option is commented out and the option PermitRootLogin is set to yes. Then I restart the SSH dæmon with:


$ sudo systemctl restart ssh

Note that if for some reason you didn't confirm that your user SSH keys were set up properly before this step and you end up being locked out, just power off the Raspberry Pi, remove the microSD card and insert it into another computer and undo your changes to the /etc/ssh/sshd_config file.

With the SSH dæmon restarted, I now should be able to become the root user on my home file server and ssh directly to root@rv without a password prompt.

The final step is to set up a script that synchronizes all of my files over to the RV server and add a cron job that tries to keep these files in sync every three hours. Because it's possible that it may take many hours sometimes to synchronize files between the systems over the wireless network, it's important to use a lock file so my script takes advantage of the flock command for this. Here is my /usr/local/bin/rvsync script that's on my home file server:


#!/bin/bash

date >>/tmp/rvsync-output
flock -n /tmp/rvsync.lock rsync -avxH /mnt/storage/audio/ 
 ↪rv:/mnt/storage/audio/ 2>/dev/null 1>>/tmp/rvsync-output
flock -n /tmp/rvsync.lock rsync -avxH /mnt/storage/documents/ 
 ↪rv:/mnt/storage/documents/ 2>/dev/null 1>>/tmp/rvsync-output
flock -n /tmp/rvsync.lock rsync -avxH /mnt/storage/video/ 
 ↪rv:/mnt/storage/video/ 2>/dev/null 1>>/tmp/rvsync-output

exit 0

The flock command sets up a lock file at /tmp/rvsync.lock. If another iteration of this script is running, the command doesn't run; otherwise, the rsync command runs. I add the current date and all rsync output to a /tmp/rsync-output file, so I can keep track of what was synced over in case I need to troubleshoot things or keep track of an rsync job that's in progress.

The rsync veterans among you might notice that I didn't include a --delete option in my rsync commands to remove files on the RV that were deleted at home. I did this mainly because I'm also using this as a kind of offsite backup, and I didn't want to risk a wayward delete command on my home NAS resulting in my backup being blown away as well. If storage starts to become a concern, I plan to run manual rsync commands with the --delete option added from time to time.

Finally, I created a file called /etc/cron.d/rvsync on my file server with the following contents:


0 */3 * * * root /usr/local/bin/rvsync

At the top of the hour every three hours, that script will attempt to run. If the RV isn't available, the script will fail silently; otherwise, it will sync over new files.

Once the initial sync progress was done, I unmounted and disconnected the USB drive and connected it back to my Raspberry Pi in the RV. Then I did a test run of the rvsync script. Although it worked, it was pretty slow due to the fact that the Raspberry Pi was pretty far away from the access point inside the house. Obviously, your circumstances might be different, but in my case, I decided to improve my reception by adding a WiFi extender.

WiFi extenders basically act as a kind of bridge between an existing access point and your computer. After some research, I selected the VONETS VAP11G-300, because it was small, relatively cheap and could be powered off USB. All I had to do to set this up was follow the simple instructions that came with the device. This involved plugging the power on, connecting to its default wireless network and then logging in to its web interface with its default credentials. At that point, I used its wizard to configure it as a bridge, which involved pointing it at my existing access point and giving it a new SSID to use. Finally, I went back to my RV media server and updated its wireless configuration to point at this new access point. With the WiFi extender in place, I was able to increase my file transfer rates between three and four times what they were before, so I consider it a worthwhile investment. What's more, I always have the option to reconfigure this access point on the road to boost the signal to an RV park's WiFi.

Step 5: Installation

Now that all the hardware and software was set up, the final step was the physical installation. My RV is old enough that it came with a cabinet designed for a CRT TV. Since modern LCDs don't need all that space, I decided to reuse that cabinet as a pantry and mount an RV LCD TV to the wall beside that cabinet. I didn't want the screen to stick out and be visible from the front of the RV when it was put away, so I measured the cabinet and decided a 15" screen would fit just about perfectly. Instead of going with a standard LCD designed for a computer, I opted for a TV designed for RVs that could be powered off a 12V DC car outlet and included a TV tuner. Some RV parks provide cable TV hookups, so I figured it might be fun to have that as an option. The direct DC power option was important too, because you ultimately waste power when you convert from AC to DC power (and even more so when you use an inverter to convert the RV's 12V DC to 110V AC only to convert it back to 12V DC), so I've made sure this entire system, including the external hard drive, could be powered off 12V DC. In the case of the hard drive, that meant scrounging around in a parts drawer for a universal 12V DC car adapter that happened to have the appropriate plug.

Another important consideration for my TV was making sure it not only had an HDMI input, but that it also had a USB port. I wanted to mount the Raspberry Pi to the back of the TV, and although those TV USB ports don't provide as much current as a proper USB power adapter, so far, I haven't had any issues. I ultimately settled on the AXESS TV1705-15 TV. I then used some of that blue tack material you might use to mount posters on a wall to mount my Raspberry Pi case to the back of the TV. I also used some of that tack material to mount the IR receiver on the underside of the TV. To help with cable management, I bought a short one-foot HDMI cable. You can see the end result in Figure 3.

Back of TV

Figure 3. The Back of the TV

You might notice that I didn't mount the huge external USB drive to the back of the TV. Because I had to route power from inside the old TV cabinet anyway, I decided to keep the USB drive inside that cabinet and just run the USB cable along with the cable TV and TV power cables.

The final important decision I needed to make was which mounting bracket to use. I had seen pictures and videos of other people's RV TV mounts, and my main concern with most of them was because they used a cheaper mounting bracket, they ended up using some kind of bungee cord or other solution to strap the TV in so it wouldn't flop around while they were driving. I opted to spend a bit more on my wall-mount bracket to get one that had lockable segments. This way I could loosen a few thumb screws and position the TV where I wanted and then lock it back in place and it would stay that way. I also could lock it in place when the TV was put away (Figure 4) and not worry about it banging against cabinets when I went over bumps.

Mounting Bracket

Figure 4. The Mounting Bracket Collapsed and Ready for Travel

Conclusion

I've taken this set up on a couple trips so far, and I have to admit, it's been pretty great to have all of my media with me at all times—my son especially approves of having all his cartoons at hand. In conclusion, here are a few things to keep in mind if you set up a similar system.

1. Old RV converters provide "dirty" power.

Once thing I noticed with this system was that it worked great whenever I was running directly off battery, but when I plugged in to "shore power" (connecting to 110V power from an extension cord at my house), the TV wouldn't always power on. It turns out that the electronics in older RVs that convert 110V power back to 12V don't necessarily provide clean 12V power. Although dumb appliances don't mind, modern electronics sometimes do. The solution is to upgrade your converter to a modern one or to use the system only when on battery power.

2. Do you leave the system on 24x7 when at home?

The big question you'll need to answer is whether you want to leave the RV media server on all the time when it's at home. If you are someone who leaves the RV plugged in when at home, that might work out great. Alternatively, if you have solar panels on top of your RV, you might be able to get away with leaving the system on all the time knowing that the solar panels are replenishing the power you draw from the house batteries. If you're relying on the house batteries by themselves to power your server, you'll probably drain your battery after a day or two.

Because I don't leave my RV powered on all the time, it means I have to take a more active approach to syncing my files. Every week or two, I turn on my RV media server for a few hours and let the cron job kick in and sync files over. When I know I'm going to be going on a trip, I tend to power the RV ahead of time to give the fridge a chance to cool down, so I also take that opportunity to sync files over. For now, this is a fair compromise for me until I upgrade my converter, and then I might consider leaving the server on all the time. If you are going to rely on this as your main offsite backup, that may not be frequent enough for you.

I've been pleased with this set up so far. It's nice to watch movies when I'm camped far enough away from civilization that streaming isn't an option. Even more than that, it's nice to have an additional backup of my important files that are near enough allowing me to access them if I need to, but on a mobile platform, so in the event of a fire or some other disaster, I could leave at a moment's notice and have everything I need with me.

Credit: photos from this article by Joy Rankin.

About the Author

Kyle Rankin is a Tech Editor and columnist at Linux Journal and the Chief Security Officer at Purism. He is the author of Linux Hardening in Hostile Networks, DevOps Troubleshooting, The Official Ubuntu Server Book, Knoppix Hacks, Knoppix Pocket Reference, Linux Multimedia Hacks and Ubuntu Hacks, and also a contributor to a number of other O'Reilly books. Rankin speaks frequently on security and open-source software including at BsidesLV, O'Reilly Security Conference, OSCON, SCALE, CactusCon, Linux World Expo and Penguicon. You can follow him at @kylerankin.

Kyle Rankin


LJ Archive