How to set up your self-hosted blog

This guide will help you set a new blog running in docker on an Ubuntu machine on the google cloud platform. We will be adding also a free https certificate, thanks to let’s encrypt.

Photo by Clément Hélardot on Unsplash

Set up a Google Cloud Instance

Define a static IP

Configure your DNS records

Add the following entries to your DNS configuration on your domain provider:

@   A

Replace with your instance external IP and with the domain you want to link to this machine.

Extend memory using a swap storage

Connect to the machine by clicking on the SSH button

Add Swap Space

sudo fallocate -l 1.2G /swapfile

# Allow Root Access:
sudo chmod 600 /swapfile

# Set up a Linux swap area
sudo mkswap /swapfile

Make changes permanent by appending to /etc/fstab this line:

/swapfile swap swap defaults 0 0

Congratulation you have your cloud instance running! 🎉

Set up Nginx and Docker

Install Nginx

sudo apt-get update

sudo apt install -y nginx

If you access your server though the browser you should see the default nginx message:

Install docker

Update apt package index

sudo apt-get update

sudo apt-get install \
  ca-certificates \
  curl \
  gnupg \

Add Docker's official GPG key:

curl -fsSL | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Add Docker's stable repository:

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Install Docker Engine

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli

Verify Docker is working

sudo docker run hello-world

You should see this message:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
  executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
  to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

Official Documentation: Install Docker Engine on Ubuntu | Docker Documentation

Install and Deploy Ghost

Pull the latest ghost image

sudo docker pull ghost:latest

Configure ghost

mkdir ghost_blog

echo '{
"url": "http://yourdomain-or-ip",
"server": {
  "port": 2368,
  "host": ""
"database": {
  "client": "sqlite3",
  "connection": {
    "filename": "/var/lib/ghost/content/data/ghost.db"
"mail": {
  "transport": "Direct"
"logging": {
  "transports": [
"process": "systemd",
"paths": {
  "contentPath": "/var/lib/ghost/content"
}' >> ghost_blog/config.json

Create a run script

echo '# Set path variables

# Purge the existing container if running.
docker kill $CONTAINER_NAME

# Mount the volumes - content directory and config file
# and add the url variable for docker map as the public URL
docker run \
-d \
--restart=always \
-p 80:2368 \
-e url="http://yourdomain-or-ip" \
-v $DATA_DIR/content:/var/lib/ghost/content \
-v $DATA_DIR/config.json:/var/lib/ghost/config.production.json \
ghost' >>

Run the script

sudo sh ./

Ignore the initial error.

Open in browser http://yourdomain-or-ip/ghost and follow the instructions

Point your domain at your google cloud instance

Go to /etc/nginx/sites-available.

Create a new entry for your domain:

sudo vi

Add the following content to the file:

# /etc/nginx/sites-available/

server {
root /var/www/html;
      listen 80;
      listen [::]:80;
      location / {
          proxy_redirect     off;
          proxy_set_header   Host $host;
          proxy_set_header   X-Real-IP $remote_addr;
          proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header   X-Forwarded-Host $server_name;
          proxy_set_header   X-Forwarded-Proto $scheme;

Add a symlink to the configuration into the sites-enabled folder

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

Restart nginx:

sudo service nginx restart

Set up HTTPS using Encrypt

Snapd is a software packaging and deployment system that works across Linux distributions. It comes preinstalled on Ubuntu and we can use it to install Certbot for setting up the Encrypt certificate.

Ensure snapd is up to date:

sudo snap install core; sudo snap refresh core

Install Certbot:

sudo snap install --classic certbot

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Install certificates:

sudo certbot --nginx

Test automatic renewal

sudo certbot renew --dry-run

To verify the domain is working, open it on your browser and you should see it running under https without any warnings.

If you need help check out Certbot Instructions | Certbot

Sources and credits