The Raspberry Pi 4B as a shiny server

[This article was first published on Econometrics and Free Software, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

This blog post will not have any code, but will document how I went from hosting apps
on shinyapps.io to hosting shiny apps on my own server, which is a Raspberry Pi 4B with 8 gigs of ram.
First of all, why hosting apps on a Raspberry Pi? And why not continue on shinyapps.io?
Or why not get one of hose nifty droplets on DigitalOcean? Well for two reasons; one is that I wanted
to have full control of the server, and learn some basic web dev/web engineering skills that I lacked. These services
simplify the process of deploying and hosting a lot, which of course is a good thing if your only
goal is to deploy apps. But I wanted to learn how to do it myself from scratch for some time.
True, with a DigitalOcean droplet, I could have learned quite a lot about the whole process as well,
but there’s a second problem; the minimum amount of processing power that the droplet needed to run
shiny came at 10€ a month. Not a fortune, but already quite expensive for me, since I just wanted
to learn some stuff on my free time. Which is why I got a Raspberry Pi 4B with 8 gigs of ram. It’s less
than 100€, and now that I have it, I can do whatever I want whenever I want to. If I don’t touch it
for several months, no harm done. And if I get tired of it, I’ll make a retro console out of it and
play some old schools games. It’s a win-win situation if you ask me.

So first, you should get a Raspberry Pi. Those are quite easy to find online, and there’s many
tutorials available on how to install Ubuntu (or any other Linux distro) on it, so I won’t bother
with that. I also won’t explain to you how to ssh into your Raspberry Pi, again, there’s many tutorials
online. More importantly, is how to get Shiny on it? There’s two solutions; you either install
it from source, or you use Docker. I chose to use Docker, but maybe not in the way you’d expect;
there’s a lot of talk online about dockerizing apps, complete with all their dependencies and
environment. The advantage is that you’re guaranteed that deployment with be very smooth. But the
big disadvantage is that these dockerized apps are huge, around 1GB, or sometimes more. It is true that disk space is
quite cheap nowadays, but still… so I prefer to run a Shiny server from Docker, and then run the
apps out of this server. My apps are thus very small, and it’s only the Shiny server that is huge.
I found a Github repository from user havlev that explains how to do it here.
I have followed this guide, and created my own docker container, which is based on havlev’s
one. I added some dependencies (to the base Debian distro included, as well as some more R packages).

If you’re in a hurry, and want to use my Docker image, you can simply type the following on your
Raspberry pi:

mkdir shiny-server
cd shiny-server
mkdir apps
mkdir conf
mkdir logs
docker run -d -p 3838:3838 -v shiny-apps:/srv/shiny-server/ -v shiny-logs:/var/log/ -v shiny-conf:/etc/shiny-server/ --name rpi-shiny-server brodriguesco/shiny_1_5:firstcommit

The first 5 commands will create some folders that we’ll need later on, while the last one will pull
my Docker container, which is based on havlev’s one, launch the server and it’ll start listening to
port 3838.

I made an app (another blog post, focusing on this app, will follow soon), hosted on my Raspberry Pi
that you can find here. I’ll also give you
some pointers on how you can achieve that.

But let’s start from the beginning.

Adding dependencies to a Docker container

So let’s suppose that you’re me a few weeks ago, and that you find and follow havlev’s guide here.
Getting the docker running is quite easy, you just need to set up Docker, and then find the line in the
tutorial that starts with docker run…. You’ll get Shiny running with its hello world app. Now,
how can you add more packages, either to the base Debian image, or R packages? For this part, I
followed this guide.
The idea is to “log in” to the console of the base Debian distro that is running from the container.
First, find the ID of the container by typing the following command in the terminal:

docker ps

You should see something like this:

[email protected]:~$ docker ps
CONTAINER ID        IMAGE                                COMMAND                  CREATED              STATUS              PORTS                    NAMES
69420blazeit        brodriguesco/shiny_1_5:firstcommit   "/etc/shiny-server/i…"   About a minute ago   Up About a minute   0.0.0.0:3838->3838/tcp   rpi-shiny-server

now with the ID in hand, you can start any command line program from your Docker container, for instance
bash:

docker exec -it 69420blazeit bash

You’ll be “logged in” as root:

[email protected]:/# 

and from there, you can install Debian packages. The following two packages are necessary to install
many R packages from source, so I recommend you install them:

[email protected]:/# apt-get install libssl-dev libxml2-dev

Once these Debian packages are installed, you can start R by simply typing R in the same console,
and install whatever packages your Shiny apps will need. In my case, I installed {golem} and several
others, but this will be the subject of another blog post. We’re almost done with that; we now need
to save the changes because if you restart the container, you’ll lose all these changes. To save these
changes, let’s run the following command, but in a new terminal on your Raspberry Pi (on the
“local” Ubuntu, not the Debian running in the container):

[email protected]:~$ docker commit -m "added some dependencies" 69420blazeit shiny_with_deps

So now you could run this container with the command from above, by replacing the adequate parts:

docker run -d -p 3838:3838 -v shiny-apps:/srv/shiny-server/ -v shiny-logs:/var/log/ -v shiny-conf:/etc/shiny-server/ --name rpi-shiny-server shiny_with_depsshiny_with_deps

Using your Shiny server

Ok so now that the server is running, you can you deploy apps on it? Remember the folders that we
created at the beginning of the blog post (or that you created if you followed havlev’s guide)?
This is where you’ll drop your apps, the usual way. You create a folder there, and simply put the
ui.R and server.R files in here, and that it. These folders can be found in your $HOME directory,
and they are accessible to your docker container as well. Once you dropped one or two apps, you’ll be able to access them on a link
similar as this one:

http://192.168.178.55:3838/hello/

where 192.168.178.55 is the local IP address of the Raspberry Pi, 3838 is the port the server
is listening to, and /hello/ is the name of the subfolder contained in the ~/shiny-server/apps
folder that you created before. What is left doing is making your Raspberry Pi a proper server that
can be accessed from the internet. For this, you’ll need to ask your ISP for a dynamic IP address.
Generally, you’ll have to pay some money for it; in my case, I’m paying 2€ a month. This address
can then be used to access your Raspberry Pi from the internet. The problem, is that being dynamic,
the address changes every time you restart your server. To solve this issue, you can use a free
dynamic DNS. I use duckdns. This will allow you to have domain that you
can share with the world. What’s nice is that if you follow their guide
the redirection to the dynamic IP address will happen seamlessly every time it changes, so no need
to think about it and do it manually.

Finally, you’ll also have to open up port 3838 on your router. The procedure changes from router
to router, but you should be able to find the instructions for your router quite easily. If not, you
should also be able to get help from your ISP.

The end result is that you’ll have your own Shiny server running off a Raspberry Pi, and accessible
over the internet! You’ll be able to deploy as many apps as you want, but of course, don’t forget
that you’re running all this on a Raspberry Pi. While these machines have become quite powerful over
the years, they won’t be powerful enough if you’re running some heavy duty apps with hundreds of
concurrent users.

In my next blog post, I’ll walk you through the development of a Shiny app using the {golem} package,
which you can find here.

Hope you enjoyed! If you found this blog post useful, you might want to follow
me on twitter for blog post updates and
buy me an espresso or paypal.me, or buy my ebook on Leanpub.

Buy me an EspressoBuy me an Espresso

To leave a comment for the author, please follow the link and comment on their blog: Econometrics and Free Software.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)