Host a Blog on Your Raspberry Pi With Ghost
If you want to start a blog, but are unsure about the costs and complexity of hosting one, worry not ! Ghost is an open source CMS (Content Management System) that you can host 100% on your very own Raspberry Pi. This way you can keep hosting costs to a minimum.
In this article, I will show you how to install Ghost on your Raspberry Pi, using docker. I will also show you how to enable HTTPS traffic on your blog, using nginx
and Letsencrypt certificates with certbot
.
Prerequisites
To follow this tutorial, you will need:
- A Raspberry Pi (of course)
- Internet access
- Basic understanding of Docker
Installing docker
If you have already installed Docker on your Raspberry Pi, you can skip this part.
To install Docker on the Pi, we will be using the helper script that Docker provides. Downloading and running it is as simple as:
curl -sSL https://get.docker.com | sh
Done, Docker is now installed ! To be able to run docker
commands without sudo
, you will need to add the docker
group to your user:
sudo usermod -a -G docker $USER
If you close and reopen your terminal, you can run any Docker command as your non-sudo user !
Installing docker-compose
Installing docker-compose is not as straight-forward as for Docker. You first need to install a couple dependencies:
sudo apt-get install -y libffi-dev libssl-dev
sudo apt-get install -y python3 python3-pip
sudo apt-get remove python-configparser
Then, docker-compose can be installed using pip:
sudo pip3 -v install docker-compose
There you go, now we have all we need to run a Ghost instance on the Raspberry Pi. Let’s move on to setting it up.
Start up the ghost server
We will use docker-compose
to launch our ghost server. To do so, we will use the ghost:3-alpine
Docker image. By default, Ghost uses an SQLite database, but here we show you how to set it up with a MySQL one.
The setup is a bit trickier with MySQL, as the official Docker image has only been built for amd64
architectures. We used a different image, based on the official one, that has been re-build for arm
: hypriot/rpi-mysql:5.5
(https://hub.docker.com/r/hypriot/rpi-mysql/).
Using docker-compose to set all of this up, we end up with the following docker-compose.yml
file:
# docker-compose.yml
version: ‘3.1’services:
ghost:
image: ghost:3-alpine
restart: always
ports:
— 8080:2368
environment:
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: example
database__connection__database: ghost
url: https://example.com
volumes:
— ./content:/var/lib/ghost/content
db:
image: hypriot/rpi-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
— mysql-data:/var/lib/mysql# Use a docker managed volume for data persistency across reboots
volumes:
mysql-data:
Don’t forget to change the default database password, as we set it to example
here. Also, you will need to set the URL Ghost will be exposed on. The example value is https://example.com
, in a local setup you would set it to http://localhost:8080
, but in a production environment, you should set it to the domain name you expose your server on. Here, I set it to https://pivrous.wtf
for this website.
When you’re done with the config, it’s time to boot it up !
docker-compose up -d
Forwarding traffic to your Raspberry Pi
A final step before obtaining your certificate and starting the HTTPS web server is to route the traffic coming to your domain, say pivrous.wtf
in this example, to your Raspberry Pi.
There are two steps to that:
- Adding a DNS record that points to your public IP
- Adding port forwarding from your home router to your Raspberry Pi.
To add a DNS record that points to your public IP, you will of course need to buy a domain name. There are many DNS providers out there, just choose one that chooses you and with which you can buy a domain name that suits you.
All providers will then allow you to create DNS records. Here you will need to create an A type record, that points your domain name to your own public IP (your home router’s IP on the public internet). You can find that IP either on https://www.whatismyip.com/ or by using the following command:
dig +short myip.opendns.com @resolver1.opendns.com
Now, we need to route this traffic from your home router to your Raspberry Pi, in the local network. This can be done by accessing your home router’s admin interface, usually available at 192.168.0.1 or 192.168.1.1, depending on your internet provider.
You will then need to add a port-forwarding rule, or NAT rule, in your router’s config. You will want to route traffic from ports 80 and 443 on your router (HTTP and HTTPS traffic) to ports 80 and 443 on your Raspberry Pi.
Enabling HTTPS traffic
Now that our services are up and running, and that web traffic reaches our Raspberry Pi, all that’s left to do is to enable HTTPS traffic to reach our Ghost server.
To do this, we will use certbot
to obtain a Let's Encrypt SSL certificate, and nginx
to handle the HTTPS traffic. First, let's install nginx
:
sudo apt-get install nginx
Then, install certbot
from its own package repository:
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install python-certbot-nginx
You can then obtain a certificate :
sudo certbot — nginx -d pivrous.wtf
This will place your certificate in /etc/letsencrypt/live/pivrous.wtf
. We will then edit the default
file located in /etc/nginx/sites-available
to replace it with the following content:
server {
listen 80;
server_name pivrous.wtf; location / {
return 301 https://$server_name$request_uri;
}
}server {
server_name pivrous.wtf;
listen 443 ssl; location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
} ssl_certificate /etc/letsencrypt/live/pivrous.wtf/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pivrous.wtf/privkey.pem;
ssl on;
}
You will have to adapt the config with your domain name, this example is the one I used for pivrous.wtf
. Finally, we will enable the site and restart the nginx
service:
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
sudo systemctl restart nginx
And that’s it !
You can now access your Ghost site at https://pivrous.wtf ! Amazing, right ?