Our Goal

To create a blog on your own server using your domain url with an SSL certificate.
We want to have a more steramlined workflow, so we are also using Github Action to automatically deploy.
I’m using Goddy to buying my domain, and hosting a linux server on Linode.

Requirement

  • A server (e.g. gcp vm, aws ec2, linode, etc.)
  • A domain (e.g. google domain, godaddy, etc.)
  • A Cloudflare account
  • A GitHub account

Domain

In this section we have two things to do:

  1. Transfer our domain to Cloudflare
  2. Add the new DNS record (You need to create your server and the get the ip address)
  3. Set up the SSL/TLS

Step 1. Setup DNS record

Login your cloudflare > create a new site > select free plan > add an A record

Add an DNS record

And make sure you enable the proxy feature in cloudflare. To use free SSL/TLS, you will need to enable this feature.

Hint: You can find your ip address from your server provider website.

Linode as an example: Your ip address

Step 2. Change your nameservers

After you set up your DNS record, Cloudflare will provide their nameservers. You will need to log in to your domain provider’s website and change the nameserver to the one provided by Cloudflare.

Cloudflare nameservers

Godaddy nameservers

Step 3. Create Origin Certificates

To enable the strict SSL mode, we will need to create origin certificates and upload them to our server later.

Seleted your domain > SSL/TLS > Origin Server

Origin Certs Step 1

Origin Certs Step 2

To copy the origin certificate and private key to your local machine and save them as files. (e.g. origin-certs.pem & private-key.pem)

Remember where you put your origin-certs.pem and private-key.pem, we’ll need them later.

Server

Step 1. Connect your sever via SSH

Create a new user with sudo privileges

When you create a Linux server (Ubuntu) for the first time, you can use the root user to login to your server. Then, for security reasons, create another user with sudo privileges.

// Create a new user
adduser {your-user-name}
// Add sudo privileges to a user
adduser {your-user-name} sudo

Generate an SSH key Pair in your local machine.

ssh-keygen -b 4096

You can specify the storage name and location of the file or use the default value. (default name: id_rsa and id_rsa.pub, default location: /home/{your_username}/.ssh)

Remember where you put your id_rsa, we’ll need it next.

When you creating the key pair, you are given the option to encrypt the private key with a passphrase. You can enter your passphrase or leave it emtpy.

Upload your public key

ssh-copy-id [email protected]

You’ll see output like the follow, and a prompt to enter your user’s password:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/your_username/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:

Try to connect your server via SSH

ssh [email protected]

Step 2. Install Nginx

Install Nginx via package manager

sudo apt install nginx

Modify Nginx Configuration

  1. Disalbe the default NGINX configuration file
sudo unlink /etc/nginx/sites-enabled/default
  1. Upload your Cloudflare certificates to your server

We can use scp to upload our file to server

scp origin-certs.pem [email protected]:/etc/nginx/ssl
scp private-key.pem [email protected]:/etc/nginx/ssl
  1. Create a new folder for your blog

Example:

sudo mkdir /var/www/my-blog
  1. Create an NGINX configuration file for your site

Create an new file in /etc/nginx/sites-available/{your-file-name}.

erver {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        server_name {your-domain-name}

        ssl on;
        ssl_certificate /etc/nginx/ssl/origin-certs.pem;
        ssl_certificate_key /etc/nginx/ssl/private-key.pem;

        root /var/www/my-blog/public; // Hugo put all the html file under the public folder
        index index.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

Enable your site and Restart NGINX

  1. Enable your site
sudo ln -s /etc/nginx/sites-available/{your-file-name} /etc/nginx/sites-enabled/
  1. Restart NGINX
sudo systemctl restart nginx

Hugo

We are not going to spend time on how to create a new blog via Hugo.

You can find some more information here.

Github Action

If you don’t know how to create a new github repo, you can come here for more information.

Add new repo secrets

github action secret

We need to add four secrets in your repo.

  • REMOTE_USER: Your server username
  • REMOTE_HOST: Your server ip address
  • REMOTE_PATH: Your blog folder on the remote server
  • REMOTE_KEY: Your ssh key (copy and past all content in the id_rsa in the secret)

Create a github action flow

name: Hugo CI & Deploy

on:
    push:
        branches:
            - main

jobs:
    build:
        name: Build and deploy website
        runs-on: ubuntu-latest
        steps:
            - name: Checkout
              uses: actions/[email protected]
              with:
                  submodules: true
            - name: Setup Hugo
              uses: peaceiris/[email protected]
              with:
                  hugo-version: "0.91.2"
                  extended: true
            - name: Build website with Hugo
              run: hugo --minify
            - name: Deploy website with rsync
              uses: burnett01/[email protected]
              with:
                  switches: -avzr --quiet --delete
                  path: public/
                  remote_path: ${{ secrets.REMOTE_PATH }}
                  remote_host: ${{ secrets.REMOTE_HOST }}
                  remote_user: ${{ secrets.REMOTE_USER }}
                  remote_key: ${{ secrets.REMOTE_KEY }}

This github action workflow will deploy your blog post to your server automatically when you push a new comment to github.

If you want to learn more about github action your can go to GitHub Actions Documentation - GitHub Docs.

Reference