commit 2db2781f0c2806243868fe401a266d85ef8d0025
parent f3b741abb857ae55a9e6b8108e9d365534facf25
Author: oscarbenedito <>
Date:   Wed, 12 Feb 2020 19:46:35 +0100

New entry: deploying hugo site

Mcontent/blog/ | 2+-
Mcontent/blog/ | 2+-
Acontent/blog/ | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlayouts/archive/single.html | 6+++---
4 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/content/blog/ b/content/blog/ @@ -1,7 +1,7 @@ --- title: "New website hosting servers" categories: incidental -tags: ["Website", "Personal domain", "Hosting services", "Autistici/Inventati"] +tags: ["Website", "Personal website", "Personal domain", "Hosting services", "Autistici/Inventati"] --- Until yesterday, this website had been hosted by [GitLab]( (using GitLab Pages). For some time now the fact that they used servers owned by Google bothered me, so I have been looking for a new host for a while. diff --git a/content/blog/ b/content/blog/ @@ -1,7 +1,7 @@ --- title: "Your corner of the Internet" categories: technology -tags: ["Personal domain", "Decentralization", "DIY", "Website", "Hugo"] +tags: ["Personal domain", "Personal website", "Decentralization", "DIY", "Website", "Hugo"] lastmod: 2019-12-06 --- We tend to have online accounts across different social networks and services. We upload our projects in some sites, we post on different ones and we follow different people on all of them. Our online identities—along with everything we share—are all over the place, but there is a way to solve this (and many other problems): personal websites. diff --git a/content/blog/ b/content/blog/ @@ -0,0 +1,72 @@ +--- +title: "Deploying a website built with Hugo" +categories: technology +tags: ["Personal website", "Personal domain", "Personal server", "Hosting services", "Self-hosting"] +--- +I have [previously talked]({{< ref "/blog/" >}}) 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. + +## Hosting without a server + +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 [their example](, you only need to add that `.gitlab-ci.yml` file to your repository and GitLab will do the rest. + +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. + +## Hosting with a server + +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 `/srv` directory and the actual files that should be served are in the `public` folder inside the directory[^var]. Therefore, the directory I want to serve is `/srv/<hugo_directory>/public` (created by Hugo). + +[^var]: It is also a common practice to put it under `/var/www`. + +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 `/etc/apache2/apache2.conf` and comment the lines with the following content (put a `#` at the start of the line): + +```apache +<Directory /var/www/> + Options Indexes FollowSymLinks + AllowOverride None + Require all granted +</Directory> + +<Directory /srv/> + Options Indexes FollowSymLinks + AllowOverride All + Require all granted +</Directory> +``` + +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 `/etc/apache2/sites-available` 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 `/etc/apache2/sites-available/<domain_name>.conf`, with the following configuration: + +```apache +<VirtualHost *:80> + ServerName <domain_name> + DocumentRoot /srv/<hugo_directory>/public + ErrorLog ${APACHE_LOG_DIR}/error-<domain_name>.log + CustomLog ${APACHE_LOG_DIR}/access-<domain_name>.log combined + + <Directory "/srv/<hugo_directory>/public"> + Options FollowSymLinks + AllowOverride None + Require all granted + + ErrorDocument 403 /404.html + ErrorDocument 404 /404.html + </Directory> +</VirtualHost> +``` + +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 `<domain_name>` domain (specified on the `ServerName`). The root folder for the domain will be `/srv/<hugo_directory>/public` (so if you access `http://<domain_name>/blog/index.html`, it will serve with the file found at `/srv/<hugo_directory>/public/blog/index.html`). 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). + +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). + +Configuration ready! We'll need to activate it using the following command as the root user: + +```bash +a2ensite <domain_name>.conf +``` + +And just make sure your DNS is pointing to the server. Everything should work now! However, we are serving our page through HTTP, we [definitely]( 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. + +In order to set up HTTPS, we need a certificate. I use one issued by [Let's Encrypt](, which are free and very easy to use (and they are renewed automatically). To do so, I use [Certbot](, developed by the [EFF]( 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! + +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 `/etc/apache2/sites-available/<domain_name>-le-ssl.conf` 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. + +Your site is ready! diff --git a/layouts/archive/single.html b/layouts/archive/single.html @@ -8,7 +8,7 @@ <main> <article> <div class="post-content"> - <h2>Posts</h2> + <h2>Posts ({{ len (where (where .Site.Pages "Dir" "==" "blog/") "IsPage" true) }})</h2> {{ range .Site.Params.active_years }} {{ $y := . }} <h4>{{ . }}</h4> @@ -20,13 +20,13 @@ {{ end }} </ul> {{ end }} - <h2>Categories</h2> + <h2>Categories ({{ len .Site.Taxonomies.categories }})</h2> <ul> {{ range .Site.Taxonomies.categories }} <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title | title }}</a> ({{ .Count }} {{ if eq .Count 1}}entry{{ else }}entries{{ end }})</li> {{ end }} </ul> - <h2>Tags</h2> + <h2>Tags ({{ len .Site.Taxonomies.tags }})</h2> <ul> {{ range .Site.Taxonomies.tags }} <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a> ({{ .Count }} {{ if eq .Count 1}}entry{{ else }}entries{{ end }})</li>