How to Configure Gitea Webhooks

Published: 2022-02-13 | Last Updated: 2022-03-04 | ~25 Minute Read

Table of Contents

Context

We will be looking at how to configure Gitea’s webhooks feature today, this feature uses git’s hooks capabilities. I have mentioned this feature in the past, but decided not to use it then.

I thought I’d walk through how that would be setup since I’m working on a project that will benefit from this feature.

This can be seen as a continuation of the previous post where we installed a simple Nginx web server on our LXC container.

By the end of this post we expect to have a website that gets updated automatically every time there is a push to Gitea.

Environment

We will have two main systems to work with, a client and a server. The server is hosting a Gitea instance and the client is our LXC Nginx web server.

Since our LXC container has a very minimal set of packages we will need to install some programs along the way.

We need to install git on our container, this is easily done via slackpkg:

root@slack-nginx:~# slackpkg update gpg
root@slack-nginx:~# slackpkg update
root@slack-nginx:~# slackpkg install git

slackpkg git install

I’d also like to install vim in order to edit the files we need to edit:

root@slack-nginx:~# slackpkg install python-2.7

slackpkg python install

root@slack-nginx:~# slackpkg install vim

slackpkg vim install

One more package that we will need is sudo:

root@slack-nginx:~# slackpkg install vim

Install sudo

Configuring Nginx

First we confirm our container information:

root@container-host:~ # lxc-ls --fancy
NAME        STATE   AUTOSTART GROUPS IPV4         IPV6 
slack-nginx RUNNING 0         -      192.168.2.21 -    

The required steps here are very similar to what we have done before, so I will not replicate the same information here.

Once Nginx is configured, check to make sure that it’s working as expected:

Default Nginx installation

Installing Bourne to Blog

We will be using Bourne to Blog to generate our website content dynamically when we push to our git repository. Note that using Bourne to Blog is not a requirement, you could easily do this manually or with any other method that may better suit your specific needs.

Transfer a previously built discount package from the host to the container:

root@container-host:/tmp # scp discount-2.2.7-x86_64-1_SBo.tgz root@192.168.2.21:/tmp

And now we can install it on the container:

root@slack-nginx:/tmp# installpkg discount-2.2.7-x86_64-1_SBo.tgz 
Verifying package discount-2.2.7-x86_64-1_SBo.tgz.
Installing package discount-2.2.7-x86_64-1_SBo.tgz:
PACKAGE DESCRIPTION:
# discount (implementation of Markdown text to html language in C)
#
# This is an implementation of John Gruber's Markdown text to HTML
# language written by David Loren Parsons. There's not much that
# differentiates it from any of the existing Markdown implementations
# except that it's written in C instead of one of the vast flock of
# scripting languages that are fighting it out for the Perl crown.
#
# Homepage: https://www.pell.portland.or.us/~orc/Code/discount/
#
Executing install script for discount-2.2.7-x86_64-1_SBo.tgz.
Package discount-2.2.7-x86_64-1_SBo.tgz installed.

The full installation steps are described in the README of the repository:

  1. Install the discount library with your system’s preferred method
  2. Ensure that you have /usr/local/bin/ in your $PATH i.e. $ echo $PATH
  3. su - root
  4. wget https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/blog -P /usr/local/bin/
  5. chown YOUR_USER:YOUR_USER_GROUP /usr/local/bin/blog i.e. chown username:groupname /usr/local/bin/blog
  6. chmod +x /usr/local/bin/blog
  7. Configure all the variables with your favorite text editor i.e. vim /usr/local/bin/blog

I created the webuser in the container and will be using that user to perform all Git related operations.

Create a repo in Gitea

There are several ways to create a repo, in this case I will create it on Gitea.

Log into Gitea and create a new repository:

Create Gitea repository

The new repository configuration is pretty basic:

Gitea repository settings

Click on Create Repository and you should see a new page with some instructions:

Git configuration instructions

Before we use the instructions we need to do a bit of setup on our container:

webuser@slack-nginx:~$ mkdir webpage 
webuser@slack-nginx:~$ cd webpage/
webuser@slack-nginx:~/webpage$

Now we will follow the instructions from the provided Quick Guide almost to the letter:

webuser@slack-nginx:~/webpage$ git config --global user.email "mail@domain.com"
webuser@slack-nginx:~/webpage$ git config --global user.name "grokkingnix"
webuser@slack-nginx:~/webpage$ touch README.md
webuser@slack-nginx:~/webpage$ git init
Initialized empty Git repository in /home/webuser/webpage/.git/
webuser@slack-nginx:~/webpage$ git checkout -b main
Switched to a new branch 'main'
webuser@slack-nginx:~/webpage$ git add .
webuser@slack-nginx:~/webpage$ git commit -m "first commit"
[main (root-commit) d62940b] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
webuser@slack-nginx:~/webpage$ git push -u origin main
Username for 'http://192.168.2.22:3000': grokkingnix
Password for 'http://grokkingnix@192.168.2.22:3000': 
Counting objects: 3, done.
Writing objects: 100% (3/3), 207 bytes | 207.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: . Processing 1 references
remote: Processed 1 references in total
To http://192.168.2.22:3000/grokkingnix/webpage.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

Now that we have made our first push to Gitea let’s check what our repository looks like:

Gitea repository after first push

Great we have our, very empty, first repository.

Configure Bourne to Blog

Let’s configure Bourne to Blog now, I only edited the following lines since we will only be using the building feature:

This is the final configuration, most of the fields were left as the defaults except for the four above:

# Edit these variables to fit your environment before first use

# Start editing
############

# Define global script variables
# Source directory that contains the original files to process
SOURCE_DIR=/home/webuser/webpage/pages/

# Directory to store html files created by the buildWebsite function
WORK_DIR=/var/www/html/

# Blog posts path on the public ftp server, where blog posts and blog index will reside
BLOG_DIR=/blog/path/on/your/webserver

# Blog posts folder name on the public ftp server, without slashes "/"
BLOG_DIR_NAME=posts

# Document root path on the public ftp server, where pages like index.html and feed.xml will reside
ROOT_WEB_DIR=/root/path/on/your/webserver


# Blog index path on the public web server, where the page that will display blog entries will reside
BLOG_MAIN=/

# Blog domain without an ending slash "/"
BLOG_DOMAIN=https://yourdomain.com

# Blog index page name
BLOG_INDEX=/path/to/the/blog/index/file.md

# Public address for the blog index page without an ending slash "/"
BLOG_MAIN_PAGE=https://yourdomain.com/path/to/blog.html

# Full path to the RSS header file.
RSS_HEADER_FILE=/path/to/the/rss/header/file

# Full path to the RSS footer file.
RSS_FOOTER_FILE=/path/to/the/rss/footer/file

# Full path to the individual blog post header file. This value will be ignored if the -h flag is provided
HEADER_FILE=/home/webuser/webpage/static/header.html

# Full path to the footer file. This value will be ignored if the -f flag is provided
FOOTER_FILE=/home/webuser/webpage/static/footer.html

# Full path to the main blog page header file. This value will be ignored if the -h flag is provided
MAIN_HEADER_FILE=/path/to/the/main/header/file.html

# Variables for SFTP connection
USER=ftpusername
HOST=ftp.host.name.com
#IDENTITY_FILE=/home/username/.ssh/identity/file

# The format/extension that the files to process are in
SOURCE_EXTENSION=*.md

# Additional (optional) module variables
OPENRING_MODULE=/openring/module/path/openring.sh

# Stop editing
############

I also commented out the IDENTITY_FILE variable since it was giving errors on the console and the OUTPUT variable since we won’t be using sftp and makes the script hang.

Test run

At this point we have Nginx, Git and Bourne to Blog installed and configured, let’s do a test and make sure that everything is working as expected.

Clone the repository on another system that can reach the Gitea instance, in my case a computer in the same 192.168.2.0/24 network:

normaluser@normalpc:~$ git clone http://192.168.2.22:3000/grokkingnix/webpage.git
Cloning into 'webpage'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), 187 bytes | 93.00 KiB/s, done.
normaluser@normalpc:~$ ls
webpage/
normaluser@normalpc:~$ cd webpage/
normaluser@normalpc:~/webpage$ ls
README.md

Let’s add the structure for our simple website:

normaluser@normalpc:~/webpage$ mkdir css img pages static
normaluser@normalpc:~/webpage$ ls
README.md  css/  img/  pages/  static/

Now let’s get some of the sample files from Bourne to Blog:

normaluser@normalpc:~/webpage$ cd static/
normaluser@normalpc:~/webpage/static$ wget -q https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/samples/footer-sample
normaluser@normalpc:~/webpage/static$ wget -q https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/samples/header-sample
normaluser@normalpc:~/webpage/static$ ls
footer-sample  header-sample
normaluser@normalpc:~/webpage/static$ mv footer-sample footer.html 
normaluser@normalpc:~/webpage/static$ mv header-sample header.html 

Edit the header.html and footer.html files to suit your needs, this what I left mine with:

normaluser@normalpc:~/webpage/static$ cat header.html 
<!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">
        <link rel="stylesheet" href="/css/style.css">
        <link rel="icon" href="/favicon.ico">
        <title>Bourne to Blog</title/>
    </head>
    <body>
        <nav>
            <a id="menu-one" href="/index.html">Home</a>
            <a href="/blog.html">Blog</a>
        </nav>
        <main>

normaluser@nginx:~/webpage/static$ cat footer.html 
        </main>
        <footer>
            <br>
            <br>
            <br>
            <br>
            <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
                <img alt="Creative Commons License" style="border-width:0"src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
            </a>
            <p>This work is licensed under a 
                <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
            </p>
            <br>
            <br>
        </footer>
    </body>
</html>

Let’s get the CSS:

normaluser@normalpc:~/webpage/static$ cd ../css/
normaluser@normalpc:~/webpage/css$ wget -q https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/samples/style-sample.css
normaluser@normalpc:~/webpage/css$ ls
style-sample.css
normaluser@normalpc:~/webpage/css$ mv style-sample.css style.css

And finally an image:

normaluser@normalpc:~/webpage/css$ cd ../img/
normaluser@normalpc:~/webpage/img$ wget -q https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/samples/img/bourne-to-blog-workflow.png  
normaluser@normalpc:~/webpage/img$ ls
bourne-to-blog-workflow.png

A simple set of .md files should do as our website content:

normaluser@normalpc:~/webpage/pages$ cat index.md 
# This is the index page!

This is a paragraph. Link to the [second page](/second.html)

Let's include an image:

![sample image](/img/bourne-to-blog-workflow.png "sample image")

normaluser@normalpc:~/webpage/pages$ cat second.md 
# This is the second page

Link to the [index page](/index.html)

This is our basic structure populated with some data:

normaluser@normalpc:~/webpage$ tree
.
|-- README.md
|-- css
|   `-- style.css
|-- img
|   `-- bourne-to-blog-workflow.png
|-- pages
|   |-- index.md
|   `-- second.md
`-- static
    |-- footer.html
    `-- header.html

Now let’s push our new content to our repository:

normaluser@normalpc:~/webpage$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        css/
        img/
        pages/
        static/

nothing added to commit but untracked files present (use "git add" to track)
normaluser@normalpc:~/webpage$ git add .
normaluser@normalpc:~/webpage$ git commit -m "Add webpage files"
[main fcf94ee] Add webpage files
 8 files changed, 276 insertions(+)
 create mode 100644 css/style.css
 create mode 100644 img/bourne-to-blog-workflow.png
 create mode 100644 pages/index.md
 create mode 100644 pages/second.md
 create mode 100644 static/footer.html
 create mode 100644 static/header.html
normaluser@normalpc:~/webpage$ git push 
Username for 'http://192.168.2.22:3000': grokkingnix
Password for 'http://grokkingnix@192.168.2.22:3000': 
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 2 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (14/14), 37.64 KiB | 3.76 MiB/s, done.
Total 14 (delta 1), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://192.168.2.22:3000/grokkingnix/webpage.git
   d62940b..fcf94ee  main -> main
normaluser@normalpc:~/webpage$

Let’s check in Gitea:

New files in Gitea

Gitea is working as expected, when we check our Nginx web server we still see the default Nginx page since the rebuild process is not yet ready.

Configure Gitea Webhooks

Gitea webhooks will help us with this, and it’s very simple to configure too. In your repository go to Settings > Webhooks:

Gitea settings

Gitea webhook settings

Select the Gitea webhook:

Gitea webhook

Set your desired settings for the webhook:

Webhook settings

Setting details:

In my deployment of Gitea I also had to set the ALLOWED_HOST_LIST configuration in the app.ini file since it was not there, I added the following lines:

[webhook]
ALLOWED_HOST_LIST = *

For more details on the available settings take a look at the Gitea documentation.

Test webhook delivery

Once you confirm the settings and click on Add Webhook you should see the following:

Created webhook

If you go back into the webhook settings page by clicking on the edit button you will find a Test Delivery button:

Test delivery

If we were to click that button now we would get an error like the following:

Delivery faliure

Upon closer inspection by clicking on the error UUID:

Error details

We see that there was a 404 error response, the response details:

Response error details

But let’s focus on the request for a second, we see that there is parameter called X-Gitea-Signature. This parameter is important because we will use it to confirm that the requests to our buildpage.html endpoint really came from Gitea.

From the sample code that is provided in Gitea’s webhooks guide we can see that there is a payload_signature variable defined by the hashed result of two components: payload and secret_key.

The algorithm used by Gitea is sha256 which is used for many different applications. In our case we will use it to make sure only the appropriate systems requested a rebuild of our website.

Configure Nginx logs

Now that we have our Gitea webhook configured and active we need to change the Nginx configuration a bit. The sample code provided by Gitea uses the PHP programming language which is fine but in our simple website we will only have static HTML web pages.

PHP is usually implemented when a backend or some type of server logic is needed, we will not need this so we will implement the same functionality with bash and Nginx’s logging capabilities.

We need to add the X-Gitea-Signature header contents to the Nginx logs, we can do this by updating the Nginx log_format directive in our /etc/nginx/nginx.conf file on the Nginx server:

log_format  main  'signature="$http_X_Gitea_Signature" $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

I simply added it to the already existing main log format, but you could create a new one if you like.

Now set the updated main log format to the Nginx server block that corresponds to our website, in my case located in /etc/nginx/conf.d/webpage.conf:

root@slack-nginx:~# cat /etc/nginx/conf.d/webpage.conf
server {
        listen 80;
        server_name 192.168.2.21;
        root /var/www/html;
        index index.html;
        access_log  /var/log/nginx/access.log  main;
}

Restart Nginx:

root@slack-nginx:~# /etc/rc.d/rc.nginx restart 
Shutdown Nginx gracefully...
Starting Nginx server daemon...

Now we can see that every entry in the Nginx log contains the signature="" string at the beginning of every line:

root@slack-nginx:~# tail -5 /var/log/nginx/access.log 
signature="-" 192.168.2.10 - - [13/Feb/2022:05:36:33 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" "-"
signature="-" 192.168.2.10 - - [13/Feb/2022:05:36:33 +0000] "GET /favicon.ico HTTP/1.1" 404 169 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" "-"
signature="-" 192.168.2.10 - - [13/Feb/2022:05:36:36 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" "-"
signature="-" 192.168.2.10 - - [13/Feb/2022:05:36:36 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" "-"
signature="-" 192.168.2.10 - - [13/Feb/2022:05:36:36 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" "-"

And when we actually receive a request from Gitea we see the following:

root@slack-nginx:~# tail -1 /var/log/nginx/access.log 
signature="e44bb6044df479cd3e0f4160391e811d0a806fdfaec32e9c309e29e959c4f980" 192.168.2.22 - - [13/Feb/2022:05:39:42 +0000] "GET /buildpage.html?payload=...
...HTTP/1.1" 404 169 "-" "Go-http-client/1.1" "-"

Excellent we can see the signature value between the quotes like we told Nginx, let’s confirm that we have the right value by comparing it with Gitea’s X-Gitea-Signature:

Gitea signature

Looks good!

So for requests that do not have the X-Gitea-Signature header we’ll have a -, and for Gitea requests we will have the appropriate signature value.

Gitea sends the payload in the request as well, which is already being logged by Nginx, which is very handy. We will use the payload as our second requirement to get our own hash value for validation.

Bash script to rebuild the website

We now have several of the pieces we need to rebuild our website when our repository receives a push.

In this script we will perform the following actions:

The script makes use of typical Linux utilities, and the JSON command line processor jq to properly format the payload data before hashing, so make sure you have this installed.

This is the final script:

root@slack-nginx:~# cat watch.sh
#!/bin/bash

# This script will monitor the Nginx logs and trigger a build of the page
# if there was a validated request from the Gitea instance webhook

# Define the secret configured in Gitea
secret="secretstring"

# Define nginxLog location
nginxLog="/var/log/nginx/access.log"

# Define payload file location
payloadPath="/var/log/nginx/decoded-payload.txt"

# Define web server endpoint to which Gitea will send requests
endpoint="/buildpage.html"

# Define the non-privileged user that will own the git repository
nonPrivUser="webuser"

# Define the repository path on the system
gitRepository="/home/webuser/webpage"

# Function to get sha256 signature
function getSignature() {
        digest="$1"
        data="$2"
        key="$3"
        shift 3
        echo -n "$data" | openssl dgst "-$digest" -hmac "$key" "$@"
}

# Function to decode the payload from the request
function decodeURL() { 
        printf "%b\n" "$(echo $payload | sed 's/%\([0-9a-fA-F][0-9a-fA-F]\)/\\x\1/g')"
}

# Function to transform the decoded payload to proper JSON
function transformPayload() { 

        # Decode URL from the nginx logs and transform to proper JSON format
        # Send the transformed JSON to $payloadPath
        decodeURL | sed "s|, |,\n|g" | sed "s|+| |g" | jq > $payloadPath
}

# Watch changes to the nginx access log
while inotifywait -qqr $nginxLog -e modify; do 

        # Get signature from request Nginx logs
        requestSignature=$(tail -1 $nginxLog | sed -n 's/signature=\"\([^]]*\)\" .*/\1/p')

        # Define the $number value
        number=$(tail -1 $nginxLog | grep -o "\"GET $endpoint?payload=[^ ]* HTTP/1.1\"" | cut -d " " -f 2) 

        # Get payload
        payload=$(echo $number | sed "s|^$endpoint?payload=\([^]]*\)|\1|")

        # Transform the payload to proper JSON
        transformPayload

        # Get signature from payload and secret key
        signature=$(getSignature "sha256"  "$(cat $payloadPath)" "$secret" | cut -d " " -f 2)

        # Check if $number is not empty
        if [ ! -z $number ] && [ $signature == $requestSignature ]; then

                # Print message to console
                echo "build was triggered"

                # Have git pull the contents of the remote repository
                # as a non-privileged user
                sudo -u $nonPrivUser git -C $gitRepository pull

                # Build the pages with Bourne to Blog
                /usr/local/bin/blog -b

                # Copy all images from the local repository img folder to the NG
                /usr/bin/cp $gitRepository/img/* /var/www/html/img/

                # Copy the CSS from the local repository css folder to the NGINX
                /usr/bin/cp $gitRepository/css/* /var/www/html/css/
        fi
done

Set the script to run on container start by adding the following lines to the /etc/rc.d/rc.local file:

# Run the watch.sh script
if [ -x /root/watch.sh ]; then
  /root/watch.sh
fi

Finishing touches

Now that we have the script setup we will take care of that 404 error from earlier.

We need to create the buildpage.html page that Gitea is expecting to see at the root of our Nginx web server, on our normalpc:

normaluser@normalpc:~/webpage/pages$ echo "building webpage" > buildpage.md 
normaluser@normalpc:~/webpage/pages$ ls
buildpage.md  index.md  second.md

Push the changes to our repository:

normaluser@normalpc:~/webpage/pages$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        buildpage.md

nothing added to commit but untracked files present (use "git add" to track)
normaluser@normalpc:~/webpage/pages$ git add buildpage.md 
normaluser@normalpc:~/webpage/pages$ git commit -m "Add webhook endpoint"
[main 47391b9] Add webhook endpoint
 1 file changed, 1 insertion(+)
 create mode 100644 pages/buildpage.md
normaluser@normalpc:~/webpage/pages$ git push 
Username for 'http://192.168.2.22:3000': grokkingnix
Password for 'http://grokkingnix@192.168.2.22:3000': 
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 348 bytes | 116.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://192.168.2.22:3000/grokkingnix/webpage.git
   fcf94ee..47391b9  main -> main

We also need to make sure that we delete the default Nginx pages:

root@slack-nginx:~# ls /var/www/html/
50x.html  index.html
root@slack-nginx:~# rm /var/www/html/*
root@slack-nginx:~# ls /var/www/html/
root@slack-nginx:~# 

First run

Before we run Bourne to Blog, pull repository changes:

webuser@slack-nginx:~/webpage$ git pull 
remote: Counting objects: 30, done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 30 (delta 11), reused 0 (delta 0)
Unpacking objects: 100% (30/30), done.
From http://192.168.2.22:3000/grokkingnix/webpage
   d62940b..9e5165e  main       -> origin/main
Updating d62940b..9e5165e
Fast-forward
 css/style.css                   | 233 ++++++++++++++++++++++++++++++++++++++
 img/bourne-to-blog-workflow.png | Bin 0 -> 36729 bytes
 pages/buildpage.md              |   1 +
 pages/index.md                  |   8 ++
 pages/second.md                 |   3 +
 static/footer.html            |  17 +++
 static/header.html            |  16 +++
 7 files changed, 278 insertions(+)
 create mode 100644 css/style-sample.css
 create mode 100644 img/bourne-to-blog-workflow.png
 create mode 100644 pages/buildpage.md
 create mode 100644 pages/index.md
 create mode 100644 pages/second.md
 create mode 100644 static/footer.html
 create mode 100644 static/header.html

Confirm we have the latest information from the repository on the Nginx web server:

webuser@slack-nginx:~/webpage$ tree
.
|-- README.md
|-- css
|   `-- style.css
|-- img
|   `-- bourne-to-blog-workflow.png
|-- pages
|   |-- buildpage.md
|   |-- index.md
|   `-- second.md
`-- static
    |-- footer.html
    `-- header.html

Now let’s do a first build with Bourne to Blog:

root@slack-nginx:~# blog -b
Building Posts
Creating buildpage
Creating index
Creating second
Posts Built

And make sure we have what we expect for Nginx to use in /var/www/html:

root@slack-nginx:~# ls /var/www/html
buildpage.html  index.html  second.html

Perfect, let’s check what we see when going to the web server address:

First build

Close but not quite, we’re missing the img and css directories and files, let’s create the directories:

root@slack-nginx:/var/www/html# mkdir img css 
root@slack-nginx:/var/www/html# ls
buildpage.html  css/  img/  index.html  second.html

We’ll let the script copy the files once it runs.

We have successfully ran the first build for the pages stored in our local repository.

Final test

Everything is now ready for a final test, let’s start the script:

root@slack-nginx:~# ./watch.sh

Now let’s make a change to one of our pages and push the change to our repository:

normaluser@normalpc:~/webpage/pages$ vim index.md 
normaluser@normalpc:~/webpage/pages$ git add index.md 
normaluser@normalpc:~/webpage/pages$ git commit -m "Update index"
[main 47d47ba] Update index
 1 file changed, 1 insertion(+)
normaluser@normalpc:~/webpage/pages$ git push
Username for 'http://192.168.2.22:3000': grokkingnix
Password for 'http://grokkingnix@192.168.2.22:3000': 
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 401 bytes | 401.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To http://192.168.2.22:3000/grokkingnix/webpage.git
   993289e..47d47ba  main -> main

And at the same time on our Nginx web server get the following from the watch.sh script:

root@slack-nginx:~# ./watch.sh
build was triggered
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 8 (delta 4), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From http://192.168.2.22:3000/grokkingnix/webpage
   15e30a6..47d47ba  main       -> origin/main
Updating 15e30a6..47d47ba
Fast-forward
 pages/index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Building Posts
Creating buildpage
Creating index
Creating second
Posts Built

Let’s take another look at our generated web site:

Final updated page

Success! We now have all of the mechanisms in place to work remotely on our website and have it update automatically when we push changes to our Gitea repository.

Conclusion

This is a Gitea feature that I plan to use for upcoming website projects and thought I’d share the setup process. The setup can easily be adapted to fit different needs of course, Enjoy!

Have a comment on one of my posts? Start a discussion in my public inbox by sending an email to ~grokkingnix/blog@lists.sr.ht [mailing list etiquette] [mailing list archive]


Posts from blogs I follow:

Open Source is defined by the OSI's Open Source Definition

The Open Source Initiative (OSI) publishes a document called the Open Source Definition (OSD), which defines the term “open source”. However, there is a small minority of viewpoints within the software community which wishes that this were not so. The most c…

via Drew DeVault's blog March 1, 2022
Introducing a Falkon extension RSS Finder

This weekend I decided to semi automate the process of searching for RSS feeds on websites while using Falkon web brosers. Many websites provide RSS feeds but do not provide any visible link or icon to access them (eg. many Wordpress based sites) and I ha…

via My land January 23, 2022
A warning to business owners and managers, you are a big part of the problem!

In my last couple of articles, mainly So-called modern web developers are the culprits and Is the madness ever going to end? I have written about some of the major problems with so-called modern web development and I have addressed the issues to the devel…

via unixsheikh.com January 13, 2022

Generated by openring