How to Secure and Optimise your Website or Blog

Self-Hosting Jun 30, 2021

Last Updated: 10th July 2021

Intro

It's important to optimise your website as this will reduce loading times, and stop viewers from abandoning your page. Search engines also factor in loading times, so it's a win win to optimise your website, happy viewers, high rankings.

I've spent many hours optimising and securing cyberhost.uk, so to save you the time, here's a little list of the important bits!

Contents

DNS

In order for visitors to connect to your site, they'll resolve your hostname such as example.com to an IP address 93.184.216.34. Therefore it is important to minimise response times for your visitors so that the webpage loads faster.

Chances are your DNS provider is the same as the registrar you purchased your domain from. It's worth taking a look at changing this and using a provider which has a global anycast network or where response times are low in your target audience location.

Fastest DNS Providers: https://www.dnsperf.com/
Global DNS Benchmark: https://www.dnsperf.com/dns-speed-benchmark/

Reverse Proxy

I'm sure you already have a reverse proxy running if you're Self-Hosting your website or blog.

I'd recommend using Caddy for a few reasons:

  • Built in a memory safe language (Go)
  • Easy to configure and maintain
  • HTTPS by default (provisions and renews certificates for you)
  • HTTP to HTTPS redirect by default

There will be a few examples in this post using the Caddy configuration file (Caddyfile).

Security Headers

What are headers?

Headers are sent alongside HTTP requests and responses. The client will send some headers such as their user-agent and any cookies. We will be taking a look at different security headers that can be sent as response headers. These will be used to instruct the browser how to behave, and will increase visitors security and privacy.

HTTP request and response headers for cyberhost.uk
X-Content-Type-Options : nosniff

This instructs the browser not to adjust the MIME type advertised in the Content-Type header. This leads to some none executable files being changed to executables files, so it's best to stop the browsers sniffing about!

Referrer-Policy

Controls how much information is sent in the referer header. We set ours to strict-origin-when-cross-origin but take a look at the Mozilla Docs and pick the best for your needs.

Permissions-Policy : interest-cohort=()

To opt Chrome users out of Google FLOC while browsing your site, set this header to interest-cohort=(). Plausible have a good blog that covers this in detail here.

X-Frame-Options : SAMEORIGIN

This is used to help protect against clickjacking and indicates whether the browser should be allowed to render the page as a frame, iframe, embed or object.

X-XSS-Protection : 1

This has a limited impact as it is only supported by Internet Explorer and Safari, it has since been replaced by the Content-Security-Policy header. Setting X-XSS-Protection to 1 enables XSS (Cross Site Scripting) filtering and will sanitise the page if XSS is detected.

Strict-Transport-Security : max-age=63072000;

Strict-Transport-Security (HSTS) instructs the browser that the website should only be accessed over HTTPS instead of HTTP. This helps secure against Man In The Middle (MITM) attacks. However, if the initial HTTP request is hijacked, a MITM attack can still be carried out as the browser won't receive the initial Strict-Transport-Security header.

To improve upon this you can set the header to max-age=63072000; preload and then get added to the HSTS List. The preload list is implemented into browsers and will then prevent browsers from ever connecting via HTTP to your website. This results in far greater security and reduced loading times as a redirect to HTTPS is not required.

Content-Security-Policy

The Content-Security-Policy HTTP response header helps you reduce the risk of XSS attacks and ensures only allowed resources are loaded in. - https://content-security-policy.com

View our headers at: https://securityheaders.com/?q=cyberhost.uk

Secure Admin/Login Pages

Login pages on CMS's such as Wordpress or Ghost are a common attack vector via brute force attacks or vulnerabilities.

  1. Have a strong password (25+ characters, numbers and special characters).
  2. Use an IP allowlist for the Login/Admin pages. So only your IP address(s) can load in sensitive pages.

IP allowlist with Caddy (Reverse Proxy):

  handle /ghost/* {
    respond @notmyip "Unauthorized Access" 401
    reverse_proxy 127.0.0.1:2368
  }

  @notmyip {
    not {
      remote_ip 127.0.0.1/24 192.168.0.0/16
    }
  }

Any IP's trying to access the /ghost/* path that is not 127.0.0.1/24 or 192.168.0.0/16 will be given an Unauthorized Access error. So if you are coming from one of those ranges the reverse_proxy will work allowing you to login.

Warning: Adding an IP allowlist will break Zapier (Used for automation) as the API endpoint is under /ghost/api/v2/admin/. The ideal solution would be to add Zapier's IP addresses but they use random AWS IP's making it almost impossible.

Therefore you may want to improve upon this Caddyfile, where the admin API endpoint is accessible from any IP (an API Key is required) and then all /ghost/* content is only accessible from your IP's.

Complete Cadddyfile:

ghost.example.com {

  handle /ghost/api/v2/admin/* {
    reverse_proxy 127.0.0.1:2368
  }
  
  handle /ghost/* {
    respond @notmyip "Unauthorized Access" 401
    reverse_proxy 127.0.0.1:2368
  }

  @notmyip {
    not {
      remote_ip 127.0.0.1/24 192.168.0.0/16
    }
  }
  
  #Used for all other content
  reverse_proxy 127.0.0.1:2368
}

Secure your server

  1. Update OS/Software on a regular basis
  2. Use SSH Keys (disable password and root login)
  3. Use a Firewall (UFW)

Optimise, make it speedy!

Compression

Reduce the amount of data transfer required, this speeds up loading times and reduces your bandwidth costs!

GZIP and Brotli (br) are the most common compression technologies. GZIP saves 78% whereas Brotli saves 82% on average, however Brotli is fairly CPU intensive. A more detailed comparison can be found here.

Caching

I was able to reduce load times by 100-300ms by using a Varnish Cache Server. Take a look at my detailed post here.

Preconnect

<link href="https://cdn.cyberhost.uk" rel="preconnect">

Using the link tag above in your HTML will initiate a connection to the URL. This makes the DNS lookup, TCP connection and TLS negotiation. Reducing the load times on any HTTP requests coming up.

DNS Prefetch

<link rel="dns-prefetch" href="//cdn.cyberhost.uk">

This link tag makes the browser send a DNS request for the domain which can then be stored in the browser's cache, reducing load times significantly.

Compress Images

Reducing the sizes of your images greatly reduces the amount of Internet transfer required, speeding up load times.

https://squoosh.app is a handy tool to help compress images.

Resize Images

Resize your images so they are suitable for the size shown on the webpage. There's no point in having profile pictures measuring 5000x5000px where they are only displayed at 50px.

https://squoosh.app can also be used to resize your images (maintain aspect ratio to prevent them from looking odd!)

Got any additional tips? Drop them in the comments!

Comments

Tags