<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Hugo on rooiratel</title><link>https://rooiratel.red/tags/hugo/</link><description>Stephan Snyman's personal website</description><language>en-gb</language><generator>Hugo</generator><atom:link href="https://rooiratel.red/tags/hugo/index.xml" rel="self" type="application/rss+xml"/><item><title>Redesign 2024</title><link>https://rooiratel.red/posts/redesign-2024/</link><pubDate>Sat, 30 Mar 2024 13:00:00 +0000</pubDate><guid isPermaLink="true">https://rooiratel.red/posts/redesign-2024/</guid><description>Damn, it’s been more than a year since I last posted! When I started this website I used Hugo to build my site. To save time I also used a theme to handle the front-end design of the site. But as time went on, and I started making small changes here and there, I eventually ended up in situations where the theme I was using couldn’t really accommodate the changes I made without some nasty hacks. And then I encountered situations where the theme was outright blocking me from making changes in a way that I wanted them. It was clearly time to remove the theme altogether and do the entire site without relying on a theme.</description><content:encoded><![CDATA[<p>Damn, it&rsquo;s been more than a year since I last posted! When I started this website I used Hugo to build my site. To save time I also used a theme to handle the front-end design of the site. But as time went on, and I started making small changes here and there, I eventually ended up in situations where the theme I was using couldn&rsquo;t really accommodate the changes I made without some nasty hacks. And then I encountered situations where the theme was outright blocking me from making changes in a way that I wanted them. It was clearly time to remove the theme altogether and do the entire site without relying on a theme.</p>
<p>It just so happened that when I started doing the redesign, my life got very busy. I still did little tweaks here and there, but it was not a quick change. I eventually had a free long weekend, and this new look is the result.</p>
<p>I have more free time now, and so I hope to be posting more frequently again. Let&rsquo;s see&hellip;</p>
]]></content:encoded></item><item><title>One Very Simple Way to Host a Website</title><link>https://rooiratel.red/posts/one-very-simple-way-to-host-a-website/</link><pubDate>Wed, 21 Apr 2021 18:33:46 +0200</pubDate><guid isPermaLink="true">https://rooiratel.red/posts/one-very-simple-way-to-host-a-website/</guid><description>I generally enjoy tinkering, and I like to optimise things as much as I can. However, when it came to hosting this website, I found that this habit was actually holding me back. I spent forever deciding which tech stack to use and tried various combinations of things, but I never actually got around to publishing anything. Finally, I decided to just pick something that was simple but that still met all my needs.</description><content:encoded><![CDATA[<p>I generally enjoy tinkering, and I like to optimise things as much as I can. However, when it came to hosting this website, I found that this habit was actually holding me back. I spent forever deciding which tech stack to use and tried various combinations of things, but I never actually got around to publishing anything. Finally, I decided to just pick something that was simple but that still met all my needs.</p>
<h2 id="step-1--static-site-generator">Step 1 : Static Site Generator</h2>
<p>In the beginning, I was debating whether I should build a dynamic or static site. Since this is just a basic website that is mainly comprised of my blog, I realised that there would be no reason for me to have a dynamic site.</p>
<p>Okay &mdash; so there are many static site generators out there. I quickly settled on <a href="https://gohugo.io">Hugo</a>. I didn&rsquo;t benchmark it or anything, but I liked it&rsquo;s simplicity, syntax and speed. Moreover, I especially liked that it has a built-in mini-webserver that you can use to view a draft version of your website on your local machine. I converted the few posts I&rsquo;d written in markdown to a basic site and liked what it looked like.</p>
<h2 id="step-2--hosting-provider">Step 2 : Hosting Provider</h2>
<p>I don&rsquo;t really mind where my website is hosted. The important thing is that the provider is reliable, reasonably priced, and has an easy-to-use interface. I ended up using <a href="https://www.digitalocean.com/">DigitalOcean</a> &mdash; I was familiar with them from small projects in the past, and they offered really good prices for what I needed. Finally, they also met my deal-breaker requirement: supporting IPv6. See my other <a href="/posts/non-tech-reasons-for-ipv6/">post</a> about that.</p>
<h2 id="step-3--domain-name-registrar">Step 3 : Domain Name Registrar</h2>
<p>Nothing special here. I don&rsquo;t think one is particularly better than the other. I ended up using <a href="https://porkbun.com">Porkbun</a>, since they had the best prices for the <code>.tld</code> I wanted to use.</p>
<h2 id="step-4--web-server">Step 4 : Web Server</h2>
<p>I know Apache really well, and I can get around with nginx. But I&rsquo;m so glad I stumbled upon <a href="https://caddyserver.com/">Caddy</a>. It may not scale as well as something like nginx, but it is perfect for a small website. And it has two killer features:</p>
<ol>
<li>It has a <em>very</em> simple config file</li>
<li>It automatically obtains/renews ssl certs for you</li>
</ol>
<p>The first one is great and already had me convinced. However, the second one is just crazy! I am quite capable of setting up a bot to get certs from Let&rsquo;s Encrypt and later renew them. But not having to bother with that and simply letting my webserver do it for me feels futuristic, to say the least.</p>
<h2 id="step-5--web-log-analyser">Step 5 : Web Log Analyser</h2>
<p>I was strongly considering <a href="https://matomo.org/">Matomo</a>, as it&rsquo;s a nice open-source alternative to Google Analytics. Before settling though, I decided to look around and see what other options there were. I quite liked <a href="https://www.goatcounter.com/">GoatCounter</a> as well; but in the end, I settled on <a href="https://goaccess.io/">GoAccess</a> for two simple reasons: I can install it from a regular Linux package manager and didn&rsquo;t need to set up a database.</p>
<h2 id="step-6--putting-it-all-together">Step 6 : Putting It All Together</h2>
<h3 id="nameservers">Nameservers</h3>
<p>After buying your domain name, point the authoritative nameservers on your domain name registrar&rsquo;s website to DigitalOcean&rsquo;s nameservers: <code>ns1.digitalocean.com</code>, <code>ns2.digitalocean.com</code>, and <code>ns3.digitalocean.com</code>.</p>
<h3 id="create-a-digitalocean-droplet">Create a DigitalOcean droplet</h3>
<p>I selected the following options:</p>
<ul>
<li>Latest Fedora Linux distro</li>
<li>Basic plan</li>
<li>Regular Intel CPU with SSD</li>
<li>$5/month option</li>
<li>Datacenter location doesn&rsquo;t matter. Probably choose the one that&rsquo;s geographically located closest to you or your intended audience.</li>
<li>I ticked the IPv6 and Monitoring options (Both are free)</li>
<li>I selected ssh login instead of password login.</li>
</ul>
<p>Finally, I added my ssh key and assigned the droplet to my default project.</p>
<h3 id="dns-records">DNS Records</h3>
<p>Once the droplet was created, I went to the &ldquo;Domains&rdquo; setting for it and added the A, AAAA and NS records. See below:
<picture>
  
  

  

  
    

    <source srcset="/images/dns_records.avif" type="image/avif" >

    
    

    

  

  <figure>
    <img
      src="/images/dns_records.png"
      alt="DNS Records"
      loading="lazy"
      decoding="async"
      width="1212"
      height="866"
    />
	<figcaption></figcaption>
  </figure>
</picture>
</p>
<h3 id="server-setup">Server setup</h3>
<p>ssh into your server and do a quick <code>dnf update</code> to get the system up to date. Then install the packages below:</p>
<ul>
<li><code>goacess</code></li>
<li><code>caddy</code></li>
</ul>
<h4 id="caddy-setup">Caddy setup</h4>
<p>Create a Caddy file. You can store it anywhere, but typically it is located at <code>/etc/caddy/Caddyfile</code></p>
<p>Mine looks something like this:</p>
<pre tabindex="0"><code>www.example.com {
        redir https://example.com{uri}
}

example.com {
        root * /var/www/html
        encode zstd gzip
        file_server
        # 404 path below must be relative to the root dir difined below
        handle_errors {
            @404 {
                expression {http.error.status_code} == 404
            }
            handle @404 {
                rewrite * 404.html
                file_server
            }
        }

        header {
                Strict-Transport-Security &#34;max-age=31536000; includeSubDomains; preload&#34;
                X-Xss-Protection &#34;1; mode=block&#34;
                X-Content-Type-Options &#34;nosniff&#34;
                X-Frame-Options &#34;DENY&#34;
                Content-Security-Policy &#34;upgrade-insecure-requests&#34;
                Referrer-Policy &#34;strict-origin-when-cross-origin&#34;
                Cache-Control &#34;public, max-age=31557600, must-revalidate&#34;
        }

        log {
                output file /var/log/caddy_access.log {
                        # roll_disabled
                        roll_size     5000MiB
                        # roll_keep     &lt;num&gt;
                        # roll_keep_for &lt;days&gt;
                }
        }
}
</code></pre><p>The first section redirects the pointless www subdomain to the correct URL. The second section points to the root directory where your website content will be stored and enables compression. The handle_errors subsection redirects you to the 404.html page if there is an HTTP 404 response. In the header subsection, I enabled some security headers. Finally, in the log subsection, I told Caddy where to store its log file, and I set the log rotation settings.</p>
<p>Now, create a systemd service for running Caddy and enable it. Save it at <code>/etc/systemd/system/caddy.service</code>
Mine looks something like this:</p>
<pre tabindex="0"><code>[Unit]
Description=Caddy web server
Documentation=https://caddyserver.com/docs
After=network.target

[Service]
User=root
LimitNOFILE=8192
Environment=STNORESTART=yes
ExecStart=/usr/bin/caddy run -config /etc/caddy/Caddyfile
Restart=on-failure

[Install]
WantedBy=multi-user.target
</code></pre><h4 id="goaccess-setup">GoAccess setup</h4>
<p>Run the following command to generate a report from your Caddy logs : <code>goaccess /var/log/caddy_access.log -o /var/www/html/stats.html --log-format=CADDY --real-time-html --daemonize</code></p>
<p>If you browse to <code>https://example.com/stats.html</code>, you can read the nicely formatted report that GoAccess generated, detailing things like most visited pages, number of visitors, geolocation of visitors, TLS version etc.</p>
<p>You can also tweak these settings (log files, output file, log format etc. and much more) in the <code>goaccess.conf</code> file that is normally located at <code>/etc/goaccess/goacces.conf</code>, but I&rsquo;m happy with the default settings.</p>
<h3 id="actually-put-your-content-online">Actually put your content online</h3>
<p>Once you are happy with how your website is looking on your local machine (using Hugo to preview it), execute the <code>hugo</code> command, and it will generate the final HTML output in the <code>public</code> subdirectory.</p>
<p>Now, you can <code>rsync</code> the output onto your server. And just like that, your website is live!</p>
<p><code>rsync --progress -avzP -e &quot;ssh -i ~/.ssh/your_ssh_key&quot; /path/to/hugo/root/dir/public/ root@example.com:/var/www/html</code></p>
<h2 id="conclusion">Conclusion</h2>
<p>It was a long explanation, but I got this all up and running in, like, 20 minutes. It&rsquo;s really fast and simple. And I&rsquo;ll probably be using this setup for a long time thanks to the very low maintenance requirements.</p>
]]></content:encoded></item></channel></rss>