Setting up a (temporary) Raspberry PI Server with Arch Linux ARM, Docker, and Ghost

Well, my old college laptop, which as of Feburary 2018 has the job of hosting this and other of my websites, has a slightly broken fan that makes noise, so I've got to do some repairs on it, and I thought it would be a good opportunity to see how easy it would be to get this website setup on a new computer, and what better to try it with than a Raspberry Pi 3? That way, it will, at least for a while, be the computer that this website runs off of, for short term, until I've finished my laptop repairs 😀. This will also be good practice in covering fundamentals in setting up these types of things, and I thought it would make a good technological article to write up, so here goes!

The Computer - A Raspberry Pi 3 B

IMG_20180228_122445235

How simple can you get?! About the size of a credit card, and only $35 dollars (plus shipping), it has an ARM CPU, 1GB of RAM, a microSD card for a hard drive, and a USB input port for power (bottom left), and an ethernet port, everything one needs to host a website like this! (I put the silver heatsink in the middle on myself.) More info about Raspberry Pi's can be found at https://www.raspberrypi.org/

First: the operating system.

Windows won't do, it's too much for this computer, and plus, I don't like it! I have all my tools ready to run on Linux, a free open-source operating system with many different versions (aka. distros), including some that run on computers like these. So, tasking myself with installing my chosen operating system of Arch Linux ARM onto my 64 GB microSD card, I'm ready to do it!

My instructions come from https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-3, which will set up exactly the file system that I need in order to get started with all the basic programs, tools, and commands that I've grown familiar with - a functional and working Linux Environment. I won't copy and paste those instructions here, but I can summarize that pretty much exactly what those instructions do are to format the SD card into a bootable hard drive, and download and copy all the Linux operating system files to it. My laptop that I'm doing all this from is running Linux as well, and all those commands are run from a command window, or a Terminal as it's known in the Linux world (and Mac world), and all these commands will work without me installing anything extra.

So, I open up a terminal, and type su<Enter> and enter my password, because I'm going to be formatting disks, which requires "root" permissions, even on my laptop. I use the command lsblk to see that my SD card is at /dev/mmcblk0, so my first command that I run after popping my SD card in is fdisk /dev/mmcblk0, and I follow on from there. I could go into detail and explain what all the commands on that page do, but if you're on Linux, running man <the command name> shows a manual page on what that command is, what it does, and how to use it.

... One installation page and several commands later ...

I now have a computer that will start up if I turn it on, but I want to get my website files now, while I'm still at my computer.

Copying files from my current server to the Raspberry Pi

I want these website files to be exactly the same as they currently are. I keep all my websites' data under a folder on my server laptop called /srv, short for "services", or "servers" if you prefer. /srv/ghost is where this website's files are at, and there are a few other folders there as well, including all of my HTTPS certificates, which are VERY important to keep safe. Since permissions need to be the same (where I need to be root again), I create a file I'm calling srv.tar, a 5GB file that has all the files and folders under /srv copied into it, with permissions, owners, and links preserved. After googling, I wind up here: https://superuser.com/questions/838392/how-to-tar-a-directory-preserving-not-only-permissions-but-ownership-too, which tells me the incantation I need below. (I run this next command from my web server's computer)

$ sudo tar -cvpf srv.tar /srv
$ ls -l        # this shows me that "srv.tar" is there and is big.

Then, I copy that to my computer, where I can extract it back out onto the SD card. (I run this command from my main Laptop, in the same folder I've been working from, as my regular old non-root self)

$ scp jvd.site:/home/jeff/srv.tar srv.tar
    (about 20 minutes of downloading later...)
$ sudo tar -xpf srv.tar -C root
    (extract /srv onto the card)
$ sync
    (make sure all that gets written to the sd card)
$ sudo umount boot root
    (unmount the SD card, sort of like "ejecting" it)

...I'm ready...

Time to turn it on!

Now I pop out the SD card and insert it into the Raspberry Pi, everything on there and ready to go. I'll plug in a USB wireless keyboard to control it and enter commands for setting it up. I plug in a monitor into the HDMI port...

So now I turn it off, and plug an ethernet cable from the Raspberry Pi into my WiFi router, so that I can get Internet to my new operating system. I also plug in an HDMI cord to the TV for a monitor, and a USB keyboard to control it. Now... I plug in the USB cord...

IMG_20180227_210433245

Yes! It's alive!

I think I'll login as the user "root" (the one with complete permission to do anything), with the password "root" to do some system setup first.

1. User Account Setup

If I didn't change the default passwords before this thing goes on the Internet, everyone would be able to login as "alarm". So I'll change root's and alarm's passwords:

# passwd
    (This asks me for a new password, sorry, not telling 😊)
# passwd alarm
    (see? It's like "passwd" above, but instead of root's password, it's jeff's password)

I could create a new user with the name "jeff", or rename alarm, but this whole setup is only temporary, so I'll leave it as "alarm".

2. Update ALL THE THINGS!

This is simple, but very important to fix possible security vulnerabilities that might have been discovered since my installation was created. Most Linux distributions, including Arch Linux, keep software in repositories on the Internet, somewhat like the Google Play store, but with much more control over when and how to update and install programs. Programs on Linux are also known as "packages", and programs called "package managers" can install, update, and uninstall them, much like apps on the app store. Arch Linux's package manager is called pacman, and it's really pretty awesome how it maintains and manages the installed programs.

# pacman -Syu

This is how to tell pacman to upgrade all installed packages. "S" is used for installs or updates, the "y" part fetches info about the latest versions from the online software repositories, and "u" updates everything installed. And as expected, it's a fairly large update, lots to download. Only rarely is the answer to pacman's question to proceed ever not "yes"...

After this point, I figure it's a good idea to reboot the computer since that update changed some pretty fundamental programs (like systemd), and since everything's up to date, I should be able to do the rest of the setup without any serious changes, so I should be able to ditch using the TV at this point, and here's how:

I happen to know that in Arch Linux, an ssh server is installed on the Raspberry Pi, and it is set to start running when Arch Linux ARM finishes turning on. So... I should be able to "ssh" into the Raspberry Pi and enter commands to control it from any computer on my network, using the username "alarm" with the password I changed it to.

Important side note - Arch Linux is one of many distros that uses systemd to manage services, that is, to start and stop certain programs on the computer. An example of one of these services is actually the SSH server that I mentioned earlier - configured to start after the computer finishes turning on. Docker, which I'll be going over in a bit, is another such service.

So, first to turn it off, I use the command poweroff, and wait until the screen goes dark before unplugging the USB cable from the Pi. I then unplug the HDMI cord, and then, with the ethernet cord still plugged in, I plug the USB cord back in again, and I see the red light turn on, and then after a few seconds, the green one starts flashing like crazy. At this point, I'm taking it for granted that it's working, but I can make sure. From my computer, I now use the command ssh [email protected] to connect to my computer, and this is what I see:

[[email protected] ~]$ ssh [email protected]
[email protected]'s password:
Welcome to Arch Linux ARM

     Website: http://archlinuxarm.org
       Forum: http://archlinuxarm.org/forum
         IRC: #archlinux-arm on irc.Freenode.net
[[email protected] ~]$

YES! At this point, I'm controlling the Raspberry Pi from my main computer, and the system is updated and working smoothly!

Now to turn it into my web server...

3. Install Docker

First, I use su to switch to the root user, using the password I changed it to before. I now install Docker, which will allow me to install and start up Ghost (the system and program that actually runs my website), in one simple step. First: install Docker.

# pacman -S docker

What Docker basically is, is a way to bundle up programs and applications, with all their required files and environment, and create mini-systems based off those bundles that run safe and separate from the main operating system. It's somewhat like Virtual Machines (running a computer inside a computer), but more lightweight and flexible. I can use Docker to take a bundle of Ghost, also known as an "image" of Ghost, located here, and create a local running copy of it to host my website, without getting into the details about how Ghost works. Docker has a bit of a learning curve, but I'll try to summarize what's going on at each step.

Docker is seen as a service to systemd, so after installing it, we have to start it. I can verify that docker is installed, even if it's not running, by using this command:

# systemctl status docker        (I press 'q' to exit)

Systemctl is the systemd command that manages services on the operating system. This is what I see:

* docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://docs.docker.com

To enable and start docker, I run:

# systemctl enable docker
    (now it will start up when the Raspberry Pi turns on)
# systemctl start docker
    (this starts docker right now. Verify that it's working...)
# docker info

Looks like that command worked, and so things are OK, apart from some warnings that don't really concern me. Now, to install and run Ghost!

4. Create and run the web server

The following commands are ones that I prepared through research, and some trial-and-error, and they are such that I can delete everything that they start up, and start from scratch, with all the data located under /srv, and it will be all that I need to do to get things working from the computer's point of view. I actually tried a few different setups to get this to work, and though I tried to get HTTPS working from the Raspberry Pi, the Docker images I was using don't work on it, so I'll be using only HTTP to actually access the website on the Raspberry Pi.

Enough explaining, start doing!

First, I will fetch the image "nginx-proxy" and start running a new container based off of it.

docker run --detach \
    --name ghost \
    --restart always \
    -p 80:2368 \
    -v /srv/ghost:/var/lib/ghost/content \
    -e url=http://blog.jvd.site \
    arm32v7/ghost

As for what that was: I've now started up the container, and from top to bottom: name the new container "ghost" for easy reference, told it to always restart if it dies or if the computer reboots (very convenient!), tie the port that the Ghost Node.js server is running on (port 2368) to port 80, which is where HTTP requests come in from the Internet. I've given this container access to /srv/ghost, which is where all the files and data unique to my website are stored, and told Ghost that it's running at the url http://blog.jvd.site (it will still be HTTPS to the outside world, but port 80 is HTTP-only).

For my real server, I use a slightly different setup to work with automatic HTTPS management, but for now, I don't need it, and can't use it easily with the same Docker images that I have on my laptop. It's a bit unfortunate, but it does work for temporary purposes.

I confirm that this works by typing "http://alarmpi/" into my browser. This connects to my server the same way the outside Internet will, but it only works from my home network, because the Internet doesn't know that "alarmpi" is the name of a small little computer in my house, of all the millions of computers in the world. It does know (because I paid for it) that "jvd.site", and "<anything-else>.jvd.site" is the name for my home router as the outside world sees it, so all that's left to do is to connect the Raspberry Pi to the rest of the world through the router.

5. Configure the router to put the Raspberry Pi online

Since I'm only using port 80 on the Raspberry Pi, I'll have to configure the router that sits between the internet and the computers on my home network (including my old laptop, and the Raspberry Pi). For most people (including me), this might involve poking around and doing lots of web searches, at least at first. Essentially what I do is make it so that the Raspberry Pi keeps the same IP address, and then forward any requests coming from the Internet over port 80. To keep the IP Address, I need to know the Raspberry Pi's MAC address, which I find using the command ip addr show eth0 (this command also tells me the IP Address), and then enter that into my router. I'm being vague because many people's routers are different, but for me, the setting is under the DHCP server settings (the service on a router that assigns IP addresses to computers), under the Static Leases section. I then went to the Port Forwarding settings, and changed ports 80 (again, HTTP) and 443 (HTTPS, not used, but just for good measure) to point at the ip address of the Raspberry Pi.

While I was doing this, I also had to modify a detail about how Cloudflare, connects to my web server at home. Cloudflare is a free service sits between the computer at my house and the rest of the Internet trying to connect to my website (like you!), and it protects me somewhat from the wild hackers of the Internet. It can also speed up the website somewhat. Anyway, since I got HTTPS working from my laptop before, I was telling Cloudflare to connect to my site using HTTPS, the same way any other outsider would - through HTTPS. This meant that the entire connection from any computer on the Internet to my server at home was encrypted, and was safe for sending passwords and logins. However, since I failed to get the Raspberry Pi to use HTTPS the way I wanted to, I now have to tell Cloudflare that it's OK to connect to my website using old-school unencrypted HTTP. This means that if anyone found out the path from Cloudflare to my home server (which is theoretically possible), they might be able to spy on the data going back and forth - which could mean disaster if they saw any passwords typed into a login page. However, as long as I only login to my website's admin area from home, using the Raspberry Pi's name, then this is not a concern for now. There is nothing terribly sensitive about the content on this blog.

I then tested the whole setup by going to Firefox and typing in "blog.jvd.site", but it didn't seem to work - it gave me a message saying "503 Service Temporarily Unavailable". Hmm... try turning the router off and on again? Of course, a reboot of the router made the settings take effect. It seems that cloudflare was still trying to connect to my laptop, and I had shutdown my website running from there after changing where port 80 went from my router.

6. The new status quo

And that brings us to the way things will be for the next few weeks, until I fix the fan in my old laptop. My other websites are a pain to have down, especially my local instance of GitLab, where I keep several of my coding projects, but I can wait, and they're all on my personal Laptop anyway. So here's waiting for one stupid fan to get here from China, and in the meantime, the living room should be a bit quieter now that the laptop can be turned off!

End result: my website's new "home", for now...

IMG_20180228_122153945

One final note...

I at first tried this with a Raspberry Pi B, but the CPU was too old to work with the docker image that I wanted. I ordered my current Raspberry Pi 3 after I found that out. Lots of trial and error... The whole process wasn't quite as easy as I thought, but when issues came up, I figured out how to fix them. And now, it works! Job well done, and I've learned some lessons, and have become more sure on other points, which is exactly what I hope to gain from doing projects like this.