Hi, I'm Gerson!

The security configuration of my static blog

Even though I’m using Hugo to generate the source code of my blog, I decided to host it on a self-managed VPS. You could say this is a lot of overkill for a static site that can be hosted on any platform, and you will be right. But being in charge of my own turf gives me more control over the security settings than what I could have on a shared hosting.

The breaking point for me is that setting up, deploying, and maintaining web servers is always fun!

Setting up expectations

With this blog’s current security configuration I’m trying to:

Every piece of software on my server, or service around my website contributes to those goals.

I’m aware that there’s nothing 100% secure. In fact, affirming that a product/service/server is unhackable will likely raise the same reactions in the infosec community than questioning the speed of light in a room full of physicists.

However, if you want to have an online presence, you need to go as far as you can to protect your visitors, as this is the ultimate goal.

Protecting my web server

I’m using Ubuntu 18 as the OS of my web server. In my opinion, when it comes to security, new is always better.

Users, sessions & privileges

In a *nix system, the root user has the highest set of privileges. This user can run # rm -rf / and get away with it. The sudoers are users with privileges to perform actions outside their role.

If an attacker logs in to the server as a root user or a sudoer with enough privileges to modify the server’s configuration or the source code of my blog, things are going to get messy. That’s why protecting how these users log in, and what they can do once logged in is important.

Here’s what I did:

These settings will complicate an attacker’s attempt to brute force his/her way to my server.

Web server: Nginx

I wanted to dedicate some time to my web server because it is what interacts with my visitors. My default choice is Nginx and I always follow OWASP’s hardening recommendations to configure it for security.

To summarise, these recommendations help me configure Nginx to:

And in addition to OWASP’s security recommendations, I also configured Nginx to:

Server-side firewall: UFW

I personally love security solutions that require a lower learning curve and that are quickly to deploy. So when it comes to firewalls, I think UFW live up to its name: uncomplicated firewall. And that’s why I chose it.

My requirements for UFW were simple:

Some of this settings are redundant as per my Nginx’s configuration but think of this as a lettuce. It’s a layer on top of a layer on top of another layer.

Web application firewall (WAF/CDN)

I use Sucuri’s website security platform which includes a WAF/CDN. Why? Because even though my website is completely static, the backend still needs protection. My operating system and all of the software installed on it, including Nginx, could contain software vulnerabilities or misconfigurations.

Deploying a web application firewall allows me to protect my website from the attack vectors I wasn’t able to foresee.

There are other benefits of using a WAF. I’ll name the two most important to me.

Pain free migrations

Even though my website is static at the time of writing this post, it doesn’t mean it’ll stay that way.

WAFs are deployed through DNS changes, for this reason, they are great to deal with all sorts of migrations.

For example, if I want to move this blog to a CMS, all I’d have to do is set up a new server and point the WAF to the new IP address.


Serving my blog’s assets through a WAF/CDN will also help me improve the load time of my site, as a consequence of serving my content from servers closest to the location of my visitors.

And many other benefits that could fit on their own post.

SSL certificate

Even though SSL certificates do nothing to protect a website from the attack of cyber-criminals, they’re still a website security best practice.

Here’s why SSL is important for my blog:

Website monitoring

Despite all my efforts to secure this blog, things can still go south for many reasons. One of the best precautions I can take is to set a website monitoring service, such as the one Sucuri has, as part of its website security platform.

This monitoring service will verify the integrity of files and will load my website frequently using different IP addresses and user-agents to try to discover conditional malware or any other sign of compromise on my blog.

Here’s what I monitor for:

Response plan

My friend and colleague Val Vesa recently published a great blog post about creating a response plan you can trust. In my case, if the worst happens and my server is compromised, I have a couple of options.

  1. Just like in real life, I travel light. I can always destroy this server, create a new one and deploy my blog again. Making sure to understand how the compromise happened in order to block it in the future of course! This is an option because I’m a technical person and I know my way around terminals and configuration and log files.
  2. Submit a ticket to the response team at Sucuri so they can figure it out for me.

What am I lacking?

Automatic server deployments

At the time of writing this blog post I don’t have an automatic server deployment process and this need to change. Gio Delgado posted an amazing blog post talking about his over-engineer blog setup on dev.to. I’ll give it a few reads to take on inspiration!

An important note

This blog post doesn’t get to have a conclusion because securing online assets is a never ending process. Expect this to be a living blog post, updated regularly.

I hope you enjoyed the reading time!

Did you find a bug in my blog? Do you have any question about my security configuration? Do you want to share a gif or a meme? I’m on Twitter!

Blog Posts

External Blog Posts