<!-- title: Deploying a website built with Hugo -->
<!-- slug: deploying-hugo-site -->
<!-- categories: Personal domain, Self-hosting -->
<!-- date: 2020-02-12T00:00:00Z -->

<p>
  I have <a href="/blog/2019/12/your-corner-of-the-internet/">previously talked</a> about creating a
  personal website, in this post I will talk about hosting it. More specifically, I'm going to
  explain how to host a website built with Hugo.</p>
<!-- /p -->

<h2>Hosting without a server</h2>

<p>
  If you don't have a server or don't want to be in charge of one, you can let GitLab host your
  website. You can either do it with your own domain or use the one GitLab will assign you based on
  your username. If you want to do it this way, take a look at <a
  href="https://gitlab.com/pages/hugo">their example</a>, you only need to add that
  <code>.gitlab-ci.yml</code> file to your repository and GitLab will do the rest.</p>
<!-- /p -->

<p>
  There are other services that will host a static site for free like Netlify (which supports Hugo)
  or services that host a site given the HTML files such as Neocities—in this case, you would need
  to run Hugo locally and upload the output files.</p>
<!-- /p -->

<h2>Hosting with a server</h2>

<p>
  If you have a server or would like to run one, you can host your website there. Let's see how to
  do it using Apache. First of all, we will install Apache and Hugo on our server and clone our
  site's repository somewhere. In my case, my Hugo directory is found in the <code>/srv</code>
  directory and the actual files that should be served are in the <code>public</code> folder inside
  the directory<sup id="fnref1"><a href="#fn1">1</a></sup>. Therefore, the directory I want to serve
  is <code>/srv/&lt;hugo_directory&gt;/public</code> (created by Hugo).</p>
<!-- /p -->

<p>
  Before we begin, let's edit Apache's configuration to deny access to the default folders. I am not
  sure if this is actually necessary as you will be setting up site root directories, but I like to
  restrict any access and then grant it on a per-site basis. Go to the Apache configuration file
  found at <code>/etc/apache2/apache2.conf</code> and comment the lines with the following content
  (put a <code>#</code> at the start of the line):</p>
<!-- /p -->

<pre><code><!--
     -->&lt;Directory /var/www/&gt;
<!-- -->  Options Indexes FollowSymLinks
<!-- -->  AllowOverride None
<!-- -->  Require all granted
<!-- -->&lt;/Directory&gt;

<!-- -->&lt;Directory /srv/&gt;
<!-- -->  Options Indexes FollowSymLinks
<!-- -->  AllowOverride All
<!-- -->  Require all granted
<!-- -->&lt;/Directory&gt;</code></pre>

<p>
  That will restrict access to the specified directories (which will not be public from now on). In
  order to grant access to the desired folder, we'll create a file under
  <code>/etc/apache2/sites-available</code> with the site's configuration. I like to name the files
  after the (sub)domain, so I would put my apache configuration in the file
  <code>/etc/apache2/sites-available/&lt;domain_name&gt;.conf</code>, with the following
  configuration:</p>
<!-- /p -->

<pre><code><!--
     -->&lt;VirtualHost *:80&gt;
<!-- -->    ServerName &lt;domain_name&gt;
<!-- -->    DocumentRoot /srv/&lt;hugo_directory&gt;/public
<!-- -->    ErrorLog ${APACHE_LOG_DIR}/error-&lt;domain_name&gt;.log
<!-- -->    CustomLog ${APACHE_LOG_DIR}/access-&lt;domain_name&gt;.log combined

<!-- -->    &lt;Directory &quot;/srv/&lt;hugo_directory&gt;/public&quot;&gt;
<!-- -->        Options FollowSymLinks
<!-- -->        AllowOverride None
<!-- -->        Require all granted

<!-- -->        ErrorDocument 403 /404.html
<!-- -->        ErrorDocument 404 /404.html
<!-- -->    &lt;/Directory&gt;
<!-- -->&lt;/VirtualHost&gt;</code></pre>

<p>
  What is happening here? We are creating a virtual host for incoming connections on port 80
  (default HTTP port) that will respond to requests to the <code>&lt;domain_name&gt;</code> domain
  (specified on the <code>ServerName</code>). The root folder for the domain will be
  <code>/srv/&lt;hugo_directory&gt;/public</code> (so if you access
  <code>http://&lt;domain_name&gt;/blog/index.html</code>, it will serve with the file found at
  <code>/srv/&lt;hugo_directory&gt;/public/blog/index.html</code>). After that, we set up the error
  and access log files (the domain part of the name is not necessary, especially if you are only
  hosting one service).</p>
<!-- /p -->

<p>
  The second part of the file looks similar to the commented lines above, and they actually do the
  same job, we just have them in this file which makes it easier to keep track of which directories
  is each site depending on and their permissions. In this case, we allow Apache to follow symbolic
  links and we give access to our files to any user on the web (we won't ask for a password). On top
  of that, I specified a custom 404 file (which will also be served when the visitor is trying to
  access a restricted file or directory, which gives error 403).</p>
<!-- /p -->

<p>Configuration ready! We'll need to activate it using the following command as the root user:</p>

<pre><code>a2ensite &lt;domain_name&gt;.conf</code></pre>

<p>
  And just make sure your DNS is pointing to the server. Everything should work now! However, we are
  serving our page through HTTP, we <a href="https://doesmysiteneedhttps.com/">definitely</a> want
  HTTPS. It might sound unnecessary since we don't have any forms on our website (no data to be
  encrypted), but HTTPS also guarantees site authenticity (protects you against man-in-the-middle
  attacks) and normalizes the use of encryption on the web.</p>
<!-- /p -->

<p>
  In order to set up HTTPS, we need a certificate. I use one issued by <a
  href="https://letsencrypt.org">Let's Encrypt</a>, which are free and very easy to use (and they
  are renewed automatically). To do so, I use <a href="https://certbot.eff.org/">Certbot</a>,
  developed by the <a href="https://www.eff.org/">EFF</a>. To use it, go to the Certbot's page,
  install it on your server and follow the instructions on the website. Make sure you enable
  redirection to HTTPS!</p>
<!-- /p -->

<p>
  It takes about 2 minutes to set up and now people will connect to your site using HTTPS. You can
  see that a new file has been created at
  <code>/etc/apache2/sites-available/&lt;domain_name&gt;-le-ssl.conf</code> by Certbot to configure
  the HTTPS site, plus a couple of lines will be added to the configuration file on port 80 to
  redirect to the encrypted site.</p>
<!-- /p -->

<p>Your site is ready!</p>

<!-- footnotes -->
<hr />

<ol>
  <li id="fn1">
    It is also a common practice to put it under <code>/var/www</code>. <a href="#fnref1"
    title="Jump back to footnote 1 in the text">&#8617;</a></li>
  <!-- /li -->
</ol>