Setup Raspberry Pi to act as your own web server

In this blog post I will describe how I set up my own web server using just a single Raspberry Pi at home. This is a cheap and fun solution to hosting your own applications, in my case using Docker.

Setting up the Raspberry Pi

Install the Raspbian OS on your Raspberry Pi’s SD card.

In order to connect wirelessly to the Raspberry without having it connect to a monitor, you need to set up headless SSH.

Connect with Ethernet cable to Router (first time only).

Find the IP of your Raspberry:

ping raspberrypi.local

SSH into it:

ssh pi@<ip>

The default password is raspberry. It might be a good idea to change this now!

Installing Docker

If you want to run your application code inside a Docker container, this is how you do it:

Install Docker:

curl -sSL https://get.docker.com | sh

Install Docker Compose:

sudo pip3 install docker-compose

Run Docker as sudo:

sudo groupadd docker
d \$USER docker
newgrp docker

Set up ssh keys:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

You are now ready to launch an application of your own! I did it by simply pulling a git repo and following the instructions in the repo’s README file.

Connect from the outside world

Make sure you have a public IP. I requested a static public IP address from my ISP, but this is optional. Another option is to set up a dynamic IP address using for example noip.com or duckdns.org.

Give your Raspberry Pi a static IP on your local network. This is how I did it for my Netgear router.

Forward port 8080 from your router to the Raspberry. Again, this is how I did it on my Netgear router.

In order to get a nice, user-friendly web domain instead of having to remember your public IP, there’s a nice service called DuckDNS. Just create a free account and then follow the instructions.

HTTPS communication

Of course you need to encrypt traffic on your web site. For this, you can use the free service Let’s Encrypt.

Run the following commands on your Raspberry Pi:

sudo apt-get update
sudo apt-get install certbot

Make sure port 80 is open.

Temporarily shut down the server, then run:

sudo certbot certonly --standalone

The certificates and key chain are now saved under /etc/letsencrypt, so copy them to your application folder or change the certificate path in your application code to point there.

Renew manually

Your certificates will need to be renewed every 90 days. To do so manually, make a bash script with the following content and run it:

sudo certbot renew --pre-hook "docker-compose stop" --post-hook "sudo docker-compose start"

sudo cp /etc/letsencrypt/live/bissenisse.duckdns.org/fullchain.pem ~/bissenisse-backend/sslcert/fullchain.pem

sudo cp /etc/letsencrypt/live/bissenisse.duckdns.org/privkey.pem ~/bissenisse-backend/sslcert/privkey.pem

sudo docker-compose restart

Note: it is very important to run docker-compose with sudo, otherwise the container will have insufficient permissions to read the certificate files.

Automatic renewal

You can also set up a cronjob to automatically renew your certificates. Maybe I will return with instructions for this later, for now it is left as an excercise for the reader!