A blog post about the blog you're reading this post on
A few months ago I decided I wanted to do some blogging about technical challenges, process observations (and opinions), and some topics I would find valuable to have written down somewhere. I also find blogging cathartic as a means to get an idea, that could otherwise stay wedged, out of my head.
The Web Developer’s Blog Pitfall
As a web developer, it’s extremely difficult to resist the urge to build a blog site from scratch. “I do web development professionally, surely I can create a small blog website for myself. I mean, if I can’t spin up a small blog website from scratch, am I really a web developer?” Thoughts like this are a slippery slope. Sure I can, but should I?
I spent some time debating what I am actually trying to get out of the project – do I want to flex the technical skills I’ve learned up to this point and build a site from scratch or do I want to focus on content? I chose the latter. Having the site up and running in a few hours allowed me to focus on writing posts. While the platform is established, there are still opportunities to tweak performance or even create a theme, if I’m so inclined.
Getting My Fix
After looking at a few platforms, I ended up choosing Hugo – it’s blog-ready, has a lot of community built themes, and is simple. Hugo’s documentation is extremely straightforward, there’s a lot of themes, and with a few clicks a Hugo site can be published on Azure. Within a few hours I had a website deployed to https://squalr.us/ using the m10c theme.
Now that the site is established and a few posts are added, I can get my engineering fix.
First, I ran the site through PageSpeed Insights to identify any web performance issues, and found a small one related to Cumulative Layout Shift. I opened a pull request updating some CSS to fix an images’ height.
Not only did this present an opportunity to do some web development, but I would argue it’s more fulfilling than had I “built a site on my own”. Contributing in this way allows me to collaborate and give back to a community, benefitting more than just my site. If yor looking for a straightforward, performant theme, I recommend m10c by vaga.
Second, I ran the site through WebPageTest to learn that there are some opportunities to improve both security and caching, something that is not auto-solved out of the box with Hugo or Azure Static Web Apps.
Cache static content
My site was flagged for not having a very robust cache policy. Azure Static Web Apps supports adding cache headers via a staticwebapp.config.json
file that can be included in the root of the deployed site. Adding this file to Hugo’s /static/
folder allowed me to configure the following for caching.
Security headers
The site was also flagged for missing security headers, specifically x-frame-options
and a content-security-policy
. Again, Azure Static Web Apps supports adding these security headers via a staticwebapp.config.json
file.
X-Frame-Options
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a
<frame>
,<iframe>
,<embed>
or<object>
. Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites.
Because I do not have any need for my personal site to be embedded, I set this to DENY
.
Content-Security-Policy
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribution of malware.
Setting an accurate Content Security Policy can be done fairly easily by trial and error, in fact a “what if” style header can also be used that will not enforce the policy but any violation will be reported: Content-Security-Policy-Report-Only
.
default-src
Value: 'self' https://squalr.us;
Explained: States that content can come from the “self” or my production domain (needed for some staging environments my site runs on).
script-src
Value: 'self' https://www.google-analytics.com 'sha256-d8WoQSinwBfvQBSI1cIf68DLqh2eUwA1HYB0xu6gBsA=' https://platform.twitter.com https://gist.github.com;
Explained: States that JavaScript may be executed from “self”, Google Analytics, Twitter (embedded Tweet), GitHub (embedded Gist), and the sha256 value represents a hash of the snippet of inline Google Analytics JavaScript (more on base64 hash policy source).
style-src
Value: 'self' https://squalr.us https://github.githubassets.com 'unsafe-inline';
Explained: CSS can be loaded from the “self”, my production domain (needed for some staging environments my site runs on), GitHub (embedded Gist), and 'unsafe-inline'
, should generally be avoided, but needed for a dynamic CSS snippet that is embedded.
frame-src
Value: https://platform.twitter.com;
Explained: Allows for an iframe to embed Twitter (embedded Tweet).
connect-src
Value: https://www.google-analytics.com
Explained: Restricts the URLs which can be loaded using script interface, limited to Google Analytics in this case.
After making these updates, I was able to bump up my scores for both security and caching. The remaining opportunities in caching are related to Google Analytics and the caching policy that they maintain for the JavaScript library.
Conclusion
Hugo offered a great platform to spin up a blog in a few hours. Azure offers great, easy infrastructure and automation to host a blog. For anyone wanting to follow in my footsteps, I created the skeleton of my blog as a template repository: https://github.com/squalrus/hugo-on-azure.
If you have any suggestions or feedback on my approach, please reach out on Twitter @chadschulz.