This tutorial is out of date and no longer maintained.
Hugo is a fast and easy-to-use static site generator written in Go and available across multiple platforms. Static site generators are a great choice for blogs and other content that do not require dynamic content pulled from a database. Choices like Hugo allow you to simplify your stack, write in user-friendly markdown, and handle updates and custom content without needing the bloat of a full content management solution.
In this guide, we will cover how to install and use Hugo on an Ubuntu 14.04 server. This will allow us to configure a static site, create content, and publish on the same server or deploy to a production location.
To follow along with this guide, you will need access to an Ubuntu 14.04 server. On this server, you will need to have a non-root user with sudo
privileges configured in order to perform administrative tasks. You can find out how to create a sudo
user by following our Ubuntu 14.04 initial server setup guide.
Hugo is not available in Ubuntu’s default repositories. However, packages are available on GitHub for various architectures and distributions.
Before we begin, we should check the architecture of our Ubuntu machine so that we can be sure to download the correct package. On your server, type:
- uname -i
If you see the following, you are running a 64-bit installation of Ubuntu:
Outputx86_64
If, instead, your output looks like this, it means that you are working with Ubuntu’s 32-bit version:
Outputi686
We will use this information below.
Visit the Hugo releases page to find the latest version stable of Hugo (the one closest to the top). If you scroll down past the feature announcement text, you should find a section called “Downloads”.
Next, we need to copy the link location for the appropriate installation package. The correct package will depend on the server architecture that you found above.
amd64.deb
and copy the link location.i386.deb
and copy the link location.On your server, logged in as your user with sudo
privileges, move into a directory that you have write permission in. Use the wget
command and paste the link location you copied to download Hugo:
- cd ~
- wget https://github.com/spf13/hugo/releases/download/v0.14/hugo_0.14_amd64.deb
Now, you can install the package with dpkg
by typing:
- sudo dpkg -i hugo*.deb
Test that the installation was successful by asking Hugo to print its software version:
- hugo version
Hugo should print its current software version:
OutputHugo Static Site Generator v0.14 BuildDate: 2015-05-25T21:29:16-04:00
The main Hugo application should now be installed. However, there are a few additional pieces of software that we should install to help us get up and running.
The main Hugo package does not include any themes. Hugo themes define how the actual site content is rendered for users. The easiest way to get Hugo themes is to clone the Hugo themes git
repository, which provides many preconfigured themes. We will need to install git
for this process.
We can find git
in Ubuntu’s default repositories. Update the local package index and then install git
by typing:
- sudo apt-get update
- sudo apt-get install git
Next, we can clone the Hugo themes repository. The repository on GitHub is organized with each individual theme included as a submodule.
Because submodules would significantly complicate the version control for the actual content for our site, we will actually just clone the themes to our home directory. We can then create a symbolic link to the themes within our site directory. This will also allow us to easily share the theme directory if we have multiple sites.
Clone the themes repository to your home directory by typing:
- git clone --recursive https://github.com/spf13/hugoThemes ~/themes
We will also install a piece of Python software called Pygments. This provides server-side syntax highlighting logic for any code blocks that would be included on our rendered pages. We can install Pygments easily with pip
, Python’s package manager.
We can get pip
from the default repositories by typing:
- sudo apt-get install python-pip
Once apt
finishes, we can use pip
to install the Pygments
by typing:
- sudo pip install Pygments
This will allow us to include syntax highlighted code blocks supporting over 300 languages in our post content if we choose. You can find out more on the project’s page.
One last thing that we will do before getting started working on our first site is to generate Hugo’s bash
autocomplete functions. We can do this by typing:
- sudo hugo gen autocomplete
Afterwards, we can source the system-wide completion configuration so that our current shell can use the auto-complete functions without logging out and logging back in:
- . /etc/bash_completion
Now, if you type hugo
followed by a few taps of the TAB key, you will see the commands that Hugo knows about:
- hugo [TAB][TAB][TAB]
Outputbenchmark config gen help new undraft
check convert gendoc list server version
Now that we are all set up, we can go ahead and create our first Hugo site. Hugo has a generator that can create a skeleton of the files and directories it needs to function.
We can create a new site in your home directory by typing:
- hugo new site ~/my-website
Move into your new Hugo site and take a look around:
- cd ~/my-website
- ls -F
You will see the directory structure and the primary configuration file used to build the Hugo site:
Outputarchetypes/ config.toml content/ data/ layouts/ public/ static/
Let’s go ahead and link the ~/themes
directory that we cloned into our new site. In order to make this link more flexible for possible deployment, we will create a relative symbolic link. If you deploy your Hugo repository to a remote server, you will just have to make sure to clone the themes directory into Hugo’s parent directory again:
- ln -s ../themes .
- ls -l
Outputtotal 28
drwxrwxr-x 2 demouser demouser 4096 Nov 5 11:25 archetypes
-rw-rw-r-- 1 demouser demouser 210 Nov 5 11:55 config.toml
drwxrwxr-x 3 demouser demouser 4096 Nov 5 11:38 content
drwxrwxr-x 2 demouser demouser 4096 Nov 5 11:25 data
drwxrwxr-x 2 demouser demouser 4096 Nov 5 11:25 layouts
drwxrwxr-x 13 demouser demouser 4096 Nov 5 11:25 public
drwxrwxr-x 2 demouser demouser 4096 Nov 5 11:25 static
lrwxrwxrwx 1 demouser demouser 9 Nov 5 14:21 themes -> ../themes
As you can see above, the themes directory in our current directory is actually just a link to the themes repository we cloned to our home directory.
Before we configure our settings and create some content, we should make our new site into a Git repository.
Make sure that you are in your site directory and initialize a new get
repository by typing:
- cd ~/my-website
- git init
OutputInitialized empty Git repository in /home/demouser/my-website/.git/
Next, set up the basic git
configuration items needed to commit code to a repository. The easiest way to do this is with the git config --global
command. We need to set our name and email address so that git
can record our information as a committer correctly:
- git config --global user.name "Your Name"
- git config --global user.email "user@email.com"
By default, git
will not commit any empty directories to the repository. Hugo, at times, requires these directories to be present even if they don’t have any content in them. To work around this, we can include a hidden .gitkeep
file in each of these empty directories. This is enough for git
to commit the directory without affecting the actual functionality for Hugo.
We can add a hidden .gitkeep
file to each of our top-level directories (other than the actual .git
hidden directory) by typing:
- for DIR in `ls -p | grep /`; do touch ${DIR}.gitkeep; done
We can see that a hidden .gitkeep
file has been added to all of our top-level directories by typing:
- find . -name .gitkeep
Output./data/.gitkeep
./layouts/.gitkeep
./archetypes/.gitkeep
./static/.gitkeep
./content/.gitkeep
We also want to make sure that our rendered site content is not added into source control. The actual HTML, JavaScript, and CSS assets should be generated fresh on each deployment, not kept in source control itself. We can tell git
to ignore the public
directory where generated content would be stored by adding that location to a .gitignore
file:
- echo "public" >> .gitignore
Now, we can commit our clean site skeleton to the repository by adding all of the content in the current directory and then committing:
- git add .
- git commit -m 'Initial commit, pre-configuration.'
Let’s adjust Hugo’s main configuration file to set up the way that Hugo will build our site.
Open the config.toml
file in your editor:
- nano config.toml
Inside, you will find a few items that we need to adjust:
baseurl = "http://replace-this-with-your-hugo-site.com/"
languageCode = "en-us"
title = "My New Hugo Site"
As the file suffix indicates, this file is written using the TOML language. This is a simple configuration language that mainly uses keys, values, and sections.
The first item that we should change is the baseurl
item. This is used to construct URLs when the site is built. Change this to reference the domain name or public IP address of your server. You should also edit the value assigned to the title
. This is used to set the tab or window title for your site and is used on the page for certain themes:
baseurl = "http://your_domain_or_IP/"
languageCode = "en-us"
title = "Your Site Name"
There are a few additional settings we should add to this file. First, we can set our preferred text editor. That way, when we generate new pages, the page template will be opened in our editor, ready to work.
We should also set a default theme. We will use a theme called “nofancy” to get started. You can override this later on the command line to test out alternatives and then edit the configuration file when you find one that suits you. We will also set our preferred code block styling:
baseurl = "http://your_domain_or_IP/"
languageCode = "en-us"
title = "Your Site Name"
newContentEditor = "nano"
theme = "nofancy"
pygmentsStyle = "native"
You can find some more information about available settings on this page. For now, save and close the file.
Let’s commit our configuration changes before continuing:
- git add .
- git commit -m 'Initial configuration complete'
We’re now ready to start creating site content. Content in Hugo is written using easy-to-use markup languages. Page metadata is provided in a special section on each page called “front matter” using the same configuration syntaxes available for the main configuration file.
We can generate new content with Hugo by using the hugo new
command followed by the path to the content we want to produce. By default, Hugo content is written in Markdown. In order for Hugo to correctly generate HTML from our Markdown pages, we need to create files that end with the .md
extension.
The pages that will be linked to from the homepage and the relative paths that your pages will need are largely dictated by your theme. View the theme’s page on GitHub to learn more about what it expects. Our “nofancy” theme has a link for an “about” page. Let’s start off by creating that page:
- hugo new about.md
A new page will be created in the content
directory called about.md
. Since we set the newContentEditor
option in our configuration file, the file should automatically be opened with your preferred editor. It should look like this to start:
+++
categories = ["misc"]
date = "2015-11-05T16:58:58-05:00"
title = "about"
+++
The settings and metadata for the page are configured in the “front matter” for the page, the section marked off on either side by lines of “+++”. The front matter included by default is often defined by the theme that you are using.
Our current theme includes three items in the front matter of generated pages. You can adjust these or add additional items as you’d like. The general variables available to Hugo can be found here. Your chosen theme might also use its own front matter variables. Check out your theme’s README in the Hugo theme repository to get specifics about your theme.
Some important general front matter items are:
For now, let’s just edit the title of our “About” page:
+++
categories = ["misc"]
date = "2015-11-05T16:58:58-05:00"
title = "About Me"
+++
Now, we can add Markdown text below the bottom “+++”. This will be translated to the body HTML text. We will add a few paragraphs, a heading, and a picture licensed under Creative Commons made available from Eva Hejda that we liked:
+++
categories = ["misc"]
date = "2015-11-05T16:58:58-05:00"
title = "About Me"
+++
Hello and welcome to my site!
## A Bit About Me
I like alpacas and I'm a fan of static sites.
![Great alpaca picture](https://upload.wikimedia.org/wikipedia/commons/c/c4/Alpaka_33444.jpg)
When you are finished, save and close the file.
We created the about.md
page in the root of our content directory because that is where our theme expects it to be. However, most of our posts will be best kept in a post
subdirectory (some themes look for posts in a posts
subdirectory instead).
Let’s create a first post in the “posts” directory. Hugo will automatically create any leading directories it needs when generating pages:
- hugo new post/My-First-Post.md
If we use dashes in the Markdown filename, they will be converted to spaces for the auto-filled title:
+++
categories = ["misc"]
date = "2015-11-05T17:52:41-05:00"
title = "My First Post"
+++
Fill in any missing metadata and add some markdown to the page. We will add a code example here so that you can see the code highlighting that the Pygments tool provides. To do this, instead of using regular Markdown triple backticks to enclose a code block, we place the code between two highlight tags that look like this:
{{< highlight language >}}
code_goes_here
{{< /highlight >}}
This will apply the Pygment styling to the code within. Keep in mind that certain themes include CSS files that will override the Pygment style choices. The <pre>
tag often has additional styling applied that can override the background color for the Pygment theme. Our particular theme doesn’t suffer from this issue however.
Inside our page, the completed content will look like this:
+++
categories = ["misc"]
date = "2015-11-05T17:52:41-05:00"
title = "My First Post"
+++
This is my first post on the site. I hope that you like it!
## Welcome Function
Here is a little Python function to welcome you:
{{< highlight python >}}
def hello_world():
print "Hello there!"
{{< /highlight >}}
Save and close the file when you are finished. If you need to edit these pages later, you can find them in the content
directory of your Hugo site.
Let’s commit our new pages to our git
repository:
- git add .
- git commit -m 'First pages of our site'
Hugo can take your Markdown files, apply the settings defined in your configuration and theme, and render the actual HTML pages that will be shown to visitors.
To build your site, you can simply type:
- hugo
This will generate your pages and put all of the rendered content into the public
directory on your server. If you wish, you can transfer the contents of this directory to your web server to deploy and serve your content.
Note
Hugo does not clean up the output directory after each build. This means that there is a possibility of stale content being left in the public
directory from a previous build. The Hugo developers recommend that you delete the public
directory after each build (especially before moving to production) so that the content can all be recreated fresh.
Hugo also includes a web server of its own. While you might not want to use it to serve your production traffic, it is an excellent way to view your working copies and test the rendering prior to deploying your pages.
To make your pages available on your Hugo server, use the hugo server
command. This will render your pages (there is no need to run the hugo
command beforehand) and then start the web server.
We will use the --bind
option to specify that we wish to make the site available on all interfaces (if you have installed Hugo locally, you can remove this). We also need to include the --bindUrl
option. We set this in our configuration file, but it isn’t picked up by the server in the current version of Hugo. Set this to your website’s domain name or IP address:
- rm -r public
- hugo server --bind=0.0.0.0 --baseUrl=http://your_domain_or_IP/
If you set draft = true
in any of your pages, or set the date
to a future time in some of your content, you can build and preview those pages by including the -D
and -F
flags respectively:
- rm -r public
- hugo server --bind=0.0.0.0 --baseUrl=http://your_domain_or_IP/ -D -F
Now, if you visit your server’s domain name or IP address in your web browser and append the :1313
port specification to the end, you will see your rendered site:
- http://your_domain_or_IP:1313
We can click on our first post to check out our rendered Markdown. Our Pygments style has been applied to the code block:
If we click on the “About” link, we will be taken to our "About Me page:
As you can see, our theme is fairly basic but it functions exactly as we expected.
If you would like to try out alternative themes, you can add the --theme=
option to the end of your server line:
- rm -r public
- hugo server --bind=0.0.0.0 --baseUrl=http://your_domain_or_IP/ --theme=redlounge
Keep in mind that each theme has its own expectations about your directory structure and configuration settings. You might need to adjust some things to get each new theme to work correctly.
If you would like to use Hugo to serve content on port 80 like a conventional web server, you will have to add the --port
option to your command line. You will also have to prepend sudo
to the command since ports below 1024 are restricted for normal users:
rm -r public
sudo hugo server --bind=0.0.0.0 --baseUrl=http://your_domain_or_IP/ --theme=redlounge --port=80
You should now be able to visit your site in a browser window without the port number appended.
After running the Hugo server with sudo
, you will have to preface the rm
command with sudo
as well:
- sudo rm -r public
Hugo is a great way to get a site off of the ground quickly and easily. Static sites offer a less resource-intensive alternative to the traditional CMS sites. The majority of users do not need database-driven content and do not use the extra features that content management systems provide. With Hugo, you can focus your energy on creating content instead of administering a complex system.
Our next guide will take this setup a step further by covering how to deploy a Hugo site using Git Hooks.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
"Enable Hugo Bash Auto-Completion
One last thing that we will do before getting started working on our first site is to generate Hugo’s bash autocomplete functions. We can do this by typing:
$ sudo hugo genautocomplete "
It should be
$ sudo hugo gen<space>autocomplete
@jellingwood Hello, as @pupsvonuchka said there is a little typo here => get != git ;-)
And as @kevingimbel suggests, is it possible for you to update this great tutorial ?
Indeed this one is pretty old now (2015) but I’m sure that folks would appreciate it a lot.
Since this was written in 2015 a lot has changed.
Hugo received an issue report the other day because the tutorial shows installing v0.14 (newest release is v0.42.2), see https://github.com/gohugoio/hugo/issues/4900
Is it possible to update the tutorial? Hugo has a lot of different options for installations, see http://gohugo.io/getting-started/installing/
For Ubuntu you can now either use Snap (
snap install hugo
) or classic apt (sudo apt-get install hugo
).This comment has been deleted
You can now use this as the new github repository. wget https://github.com/spf13/hugo/releases/download/v0.16/hugo_0.16-1_amd64.deb
@jellingwood “Make sure that you are in your site directory and initialize a new
get
repository by typing:”It should be
git
.