Hosting a Static Website Using CloudFlare and BackBlaze B2 (part 1)
Tuesday, June 7, 2022
Reading time 10 minutes
This is the first part of a series of posts I started detailing the steps I’ve followed to publish a static website using Cloudflare and B2, along with GitLab runners, which are responsible for building and uploading the site files. You can find the other parts of this series in the following links:
After migrating this site to Hugo, I read somewhere (or maybe on Twitter, I’m not clear right now) an idea about hosting and serving the entire website from an S3-style service. There are many services that offer compatibility with the S3 API right now (among which is, of course, S3 itself). In this post I intend to explain, broadly speaking, the process I followed to configure one of these object storage services and Cloud Flare to be able to have a website without the need for a web server.
Why do all this?
When it comes to deploying a site made with a static generator, it’s always recommended to use platforms like Netlify, GitHub pages or a similar platform. And they’re certainly quite good. Although in my case I decided to try hosting the web in a Backblaze B2 bucket as an experiment for another project I have in mind, plus this is a quite interesting way to maintain the same level of control and privacy over the website files. Also another common question that may arise is, in a market where getting a VPS server is so cheap (they start at 3 dollars), is it really worth maintaining a configuration like this? What’s the point of all this? And although I still couldn’t give an opinion from personal experience, I do believe that doing it this way can provide interesting things, such as the following:
- No need to maintain a complete web server: The only thing you’ll need to provide access to a website, once the configuration phase is finished, is to continue updating it. For this you only need to generate the site and upload it to the BackBlaze bucket. You don’t need servers, operating systems, updates, additional configurations, SSL, etc. CloudFlare and Backblaze will take care of all this, with Backblaze being the repository where the website is stored. But not just Backblaze, because these instructions would work with practically any object storage service that allows displaying HTML. To serve a site that only consists of static files, it may not be a good idea to dedicate a web server’s resources.
- Speed: Between Cloudflare’s cache system and the low latency their data centers have with Backblaze, page resolution will be faster.
- Cost: Backblaze B2 is an object storage system that allows creating buckets. A bucket is like a directory that can contain more directories and files. For each Gigabyte stored, Backblaze charges $0.005 dollars per month. That’s much cheaper than hosting a website on a VPS, and serves the same function.
Necessary Steps
First of all, you need to have a static site (of any type, it just has to be static) that can already be generated in a local directory, for example. In my case I’ve been using Hugo for a couple of months, so it was with this generator that I ended up making these adjustments. You also need to have accounts on Cloudflare, and have previously added a domain with them (you’ll need to change the DNS servers to CloudFlare’s so it can take control of the domain); as well as on backblaze b2. At this point, instead of Backblaze you could use practically any other file storage system that allows querying files through a public URL.
Step 1. Starting Point
When starting with these adjustments, I had a simple configuration. I have my website files hosted in a GitLab repository, which built the website every time a commit was made using the “hugo” command in the GitLab runners that were available in my instance. The runners used for the site are docker runners, which have exactly the same type of configuration as those you can use on gitLab.com, for example. Every time a job is executed, the runner creates a docker container with the image requested, clones the repository, and executes the commands inside the “script” section that you define in the file where the jobs are specified. The docker host runs on Linux, so it’s not possible to use Windows containers, although that’s not necessary for this task. Once the site has been generated, the final step of the job is to leave the HTML files that were created ready for another job to take them and do something with them, presumably upload them to some site so they can be accessed. This is done by defining the folder where the generated html files are saved as an artifact. In GitLab, artifacts are the files you’re interested in passing to other jobs, so they can operate with them. In this example, only two jobs would be used: the first would build the website, and the second would take the generated files and do something with them. To give a better idea, and without intending this to be an introduction to GitLab runners, which are already very complex, here’s the .gitlab-ci.yml file that was in my website repository before starting with the configuration to serve it through CloudFlare and Backblaze.
# File to generate the website using GitLab's docker runners.
# Set strategy for git, when cloning the repository, to also clone submodules recursively.
# otherwise, hugo themes may fail, since they recommend using git submodules.
variables:
GIT_SUBMODULE_STRATEGY: recursive
# Define the stages of this project. Each job can be assigned to one of these
# All jobs in each stage must be completed before starting the next one.
stages:
- build
- upload
# Generate HTML files from the repository, using the docker runner and GitLab's hugo image.
make_site:
tags:
- docker
stage: build
only:
- master
interruptible: true
image: registry.gitlab.com/pages/hugo:latest
script:
- 'hugo'
artifacts:
paths:
- public
expire_in: 1 day
There’s some other job configuration I’ve left without commenting, but broadly speaking this runs every time GitLab receives a new commit on the master branch, creates the docker container, clones the repository including submodules, and builds the website. Then, it copies the files found in the “public” directory to GitLab’s artifact cache, from where another job, which we’ll generate later, will take them and place them in the backblaze bucket.
Step 2. Creating the Bucket in BackBlaze
The first thing to do is create the bucket in B2, and configure it as public. It’s also important to generate an access key, which will allow us to upload files from GitLab securely to our newly created bucket. To create the bucket, you can do it through these steps:
- On the B2 buckets page, locate and activate the link called “Create Bucket”. This will open a modal dialog where we can configure the most important aspects of our new bucket. Among the most important options to consider are the following:
- Bucket Unique Name: Buckets must have a unique name throughout the region where they are created. This means that if I use my bucket name, no one else in the entire Backblaze region can create a bucket with the same name. Buckets must have a name with a minimum of 6 characters, and you can only use English alphabet letters, numbers, and hyphens. Since we’re configuring the manuelcortez.net website, I decided to create the bucket called manuelcortez-net.
- Files in Bucket are: Here you can specify whether the files in this bucket will be public or private. To serve a website they must be public.
- You can leave the rest of the options as they are.
- When you’re done, locate the button called “Create bucket” and press it to finish creating it.
- When finished creating it, the modal dialog will close and we’ll return to the buckets page. Here a list will be shown where we can see the bucket we created, along with some information that will be important later. The list of buckets is shown just below the link to create more of them.
- It may be desirable to change the file lifecycle options for our new bucket. By default, Backblaze will save all versions of the same file that are uploaded. Over time, that means we’ll have many copies of our files, which won’t be necessary, since git itself can serve us better when it comes to returning to a previous repository state. To change this, just after the bucket information, a list of links with various options will be shown. Locate the option called “Lifecycle Settings” and access it.
- Once you’re in this section, you’ll be shown several radio buttons with the possible lifecycle configuration for files in your bucket. If you want to keep only the last version of files, select the option “Keep only the last version of the file” and press the “Update Bucket” button.
- Back in the bucket list, locate the information for the one you’ll use and look for the line called “S3 endpoint”. Copy the line below it and paste it in a document you have at hand, along with your bucket name. The line is a URL address, which serves to identify the region where we’re going to tell GitLab to upload our website later. The endpoint may look something like this: s3.us-west-001.backblazeb2.com.
Step 3. Creating the Application Key in BackBlaze
The next step is to create the application key within Backblaze itself. This key will be our credentials to be able to upload files using the data we already have, such as our bucket name and the s3 endpoint. To create the key:
- In the Backblaze app keys section, a list of all the keys you’ve created will be shown. If none are created, you can make your first key using the link called “Add a New Application Key”, which will open another modal dialog where we can configure the following:
- Name of Key: The system focus by default falls here. Specify the key name. Valid characters again are alphabet letters, numbers, and hyphens. This name will be useful mainly when displaying it in the key list.
- Allow access to Bucket(s): In this combo box, you can choose which bucket this key will have access to. As a general rule, it’s recommended that each key have access to only one bucket. It’s more secure and if at some point your key were compromised, it would be easier to remove it from the list without fear that the key could have been used on other buckets.
- Type of Access: The access mode for this key. By default the mode is read and write, which will allow whoever uses this key to read, write and delete files from the bucket. Unless there’s a very good reason to change this, it should be left as is.
- You can leave the rest of the options as they are. When you’re done with the options, click on the “Create New Key” button.
- Once your new key is created, its data will appear below. It’s very important that you can copy your key data, because part of this information will never be shown again. Start by looking for a message that says something similar to the following: “Success! Your new application key has been created. It will only appear here once.” Once found, copy the lines below “keyID:” and “applicationKey:”. In simple terms, keyId would be your username, and applicationKey would be your password to be able to upload files. Again, copy this data and paste it in your reference document.
After this data, you should have a document with information similar to this:
Bucket name: manuelcortez-net
S3 endpoint: s3.us-west-001.backblazeb2.com
keyID: 001f24eXXXX
applicationKey: K001hgpMXXXX
And so, we’re almost completely done with BackBlaze. But for now that’s all. In future posts we’ll continue with the details about what we have to do on the GitLab side to upload the site to B2, and also in cloudflare, to be able to connect a domain to our Bucket.
S3 B2 Static website gitlab CI/CD