Home Self hosting on the Raspberry Pi with Cloudflare and Nginx
Post

Self hosting on the Raspberry Pi with Cloudflare and Nginx

The Goal of this article is to guide you through the process of setting up a home server on a raspberry pi (or any linux machine), using cloudflare as a proxy server.

Why a Raspberry home server?

Home servers are great. They enable a user to setup any service they desire, based on any technology stack they prefer, never stack on the limitations of an intermediate hosting provider and their associated costs.

And while it is possible to host one’s services on their home computer, I always felt it is bad practice to leave a home workstation on, for prolonged periods of time.

Instead, a Raspberry Pi device is an excellent choice to use as a home server, due to several benefits associated with it, such as:

  • A very low energy footprint
  • The fact that it is designed to run 24/7, for extended periods of time
  • It can be a very powerful device, depending on the model
  • They support several common linux based operating systems
  • They can be quite cheap to buy and very small in size

Delegating the server functionality to a dedicated device is good practice. But it does come with some associated issues we should take into consideration.

Networking

Making a service available to the public, requires that a remote device be able to reach one’s home server, and thus, their home network. Usually, a home network is behind a Nat, and thus requires a port forwarding rule to the device on which the home server runs.

To make this more clear. A NAT is a subnetwork, under which all the home devices are connected. Multiple mobile devices, laptops, and any other device connected to the home router, is part of the local, home network.

Communication between devices behind a NAT, can be achieved via the use of local IP addressed, such as 192.168.1.1, 192.168.1.2 etc.

The external IP, is the address by which one’s whole home network (their router) is reachable by the wider web, and it is assigned by their ISP.

Since home networks are not meant to be reached by the public, most routers block incoming traffic, and thus for our service to be reachable, a router port forwarding rule is needed.

Also, ISPs usually assign a dynamic external ip to home networks. Which means, that a home external ip address can change, making it impossible for a client to reach the home network, and the associated service. ISPs sometimes offer static ip addresses for home networks, but for significant extra cost.

Another issue, is that ISPs sometimes drop packets targeting specific common ports, such as 80 (used by the HTTP protocol), and/or port 443 (HTTPS), making common server functionality impossible for a home network.

Finally, sometimes ISPs place entire neighbourhoods behind their own NAT network, making it even more complex to setup a home server.

Although the issues above can often be fixed, there ultematelly always remains a certain, very serious concern, which has to do with the security implications of exposing one’s own home network to the public.

Cloudflare

Cloudflare is a (mostly) free service, which offers lots of benefits for a home server setup.

Proxy

Cloudflare can work as a proxy between one’s home server and the general public. That means, all traffic targeting one’s home network, instead targets the cloudflare server, which delegates all traffic to the home network.

Cloudflare Proxy

This offers many security benefits to a home network. Firstly, by setting up Cloudflare as a proxy, there is no need for a home server to expose its external Ip Address to the public. Secondly, since only cloudflare servers are expected to propagate traffic to the home network, network filters and firewall rules are easy to setup, dropping all incoming packets with source addresses that don’t match the cloudflare servers.

Cloudflare also offers free DoS protection, and as a CA, free SSL Certificates for the home server.

As if all of that is not enough, Cloudflare can also work as a CDN, reducing traffic to your home server and improving overall performance.

Cloudflare Tunnels

Remember all the connectivity issues that might arise when trying to expose a home network to the public. ISP dynamic IP allocation, ISP neighbourhood NAT, ISP dropping packets targeting common ports. All those issues can make it a pain, or even impossible to expose a home server to the public.

Cloudflare Tunnels offer a simple solution to all of these issues. Instead of exposing the home server to the public, the home server sets up a service that connects to the Cloudflare servers, and through that service, Cloudflare is able to propagate all traffic to the home server through that connection. This makes it possible for zero configuration home networks, to connect to cloudflare, as clients, thus making all ISP or network related issues irrelevant. An extra benefit to this setup, is that only traffic that’s propagated by Cloudflare can ever reach the home server, making the connection more secure in the process.

A tunnel is also pretty straightforward to setup, making Cloudflare a “too good to be true” choice for any home server setup, considering the fact that it’s completely free!

Obtaining a domain

Now that we’ve explained a few basic concepts, let’s dive in and start building our server.

The first thing you need to do, is to create a free Cloudflare account. In order for Cloudflare to work, you will also need a domain name.

Note: Cloudflare is a little particular when it comes to domain names. It doesn’t support all TLDs. You can find all supported TLDs under Domain RegistrationRegister Domains, in your Cloudflare Dashboard.

I highly recommend you register your domain name through Cloudflare. You can avoid some setup hustle and be sure cloudflare supports that domain. If you choose to register your domain through another registrar, Cloudflare offers instructions on how to transfer your domain to cloudflare, here.

Depending on the TLD, your domain name can cost from around 5$+ per year, making it the only monetary burden you have to carry for your home server to go public.

For this tutorial, we shall assume our domain name is example.com

Setting up Nginx

Nginx is a very popular, high performance web server and reverse proxy. Setting up nginx on our raspberry pi (Raspbian, or ubuntu based for this article) is pretty straightforward.

Note: Make sure you don’t have another server, such as apache installed and running on the ports you’re going to use for Nginx. Port 80 for http and port 443 for https by default.

First, you should update your system, if you haven’t done so already.

1
sudo apt update && sudo apt upgrade

Next, install Nginx with the following command:

1
sudo apt install nginx

Once Nginx is installed, we simply need to start it as a service.

1
sudo systemctl start nginx

Now Nginx should be installed and running, we can check the state of nginx with:

1
sudo systemctl status nginx

Serving our first website on Nginx

Serving a website with Nginx is a very straightforward process:

  1. We position our files in a directory of our choice.
  2. We create a configuration file in Nginx for the given website.
  3. We restart the Nginx service.

For the first step, we should decide on a path, under which we shall be placing our websites.
For this tutorial, our websites will be placed in our home directory, under the folder ”~/www”.

Our first website shall be a test one, which we will access under localhost. So, create the directory, and place our test index.html file there:

1
2
mkdir -p ~/www/localhost
cd ~/www/localhost

Create the index.html file using an editor, eg nano, and copy the following code inside.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Hello Nginx</title>
  </head>
  <body>
    <main>
        <div class="center-div">
            <h1 class="header-text">Hello Nginx!</h1>
        </div>
    </main>
  </body>
  <style>

    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }

    .center-div {
        background-color: #171717;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        padding: 40px;
        border-radius: 15%;
    }
    
    .header-text{
        color: white;
    }
  </style>
</html>

Configuration

For each website we want to serve with Nginx, we should create a relevant configuration file. Nginx configuration files are placed under /etc/nginx/sites-available.

So we should create our configuration file under that folder:

1
sudo nano /etc/nginx/sites-available/localhost

Copy the following code there:

1
2
3
4
5
6
7
8
9
server {
    listen 80; # The default port 80 for http
    server_name localhost; # our website's url
    
    location / {
        root /home/<username>/www/localhost;  # Replace <username> with your username
        index index.html;  # Sets the default index file
    }
}

This configuration file makes Nginx listen on port 80 for incoming connections, to serve our website under the chosen location. To check if our configurations are correctly setup, we can use:

1
sudo nginx -t

Our configuration now exists, but it is not enabled. To enable the configuration for this webstie, we also need to create a link of our configuration file under the directory /etc/nginx/sites-enabled:

1
sudo ln -s /etc/nginx/sites-available/localhost /etc/nginx/sites-enabled/

Finally, we should restart Nginx for our changes to take effect.

1
sudo systemctl restart nginx

Our website can now be accessed under localhost. Go to your browser and access it. If everything is setup correctly, you should be able to see the message Hello Nginx!.

Setup Cloudflare

Once that’s ready, go setup a site with the domain you just bought under Websites in your dashboard. Cloudflare offers relevent instructions, here.

This post is licensed under CC BY 4.0 by the author.