Deploy Hugo Static Site on Ubuntu with Nginx

By Anurag Singh

Updated on May 28, 2025

Deploy Hugo Static Site on Ubuntu with Nginx

In this tutorial, we'll deploy Hugo static site on Ubuntu with Nginx. 

We’ve all experienced the joy of lightning-fast, rock-solid websites—and static site generators like Hugo make it remarkably easy to deliver exactly that. In this tutorial, we’ll walk through deploying a Hugo site on Ubuntu 24.04 and serving it with Nginx. Along the way we’ll explain why each step matters, share best practices, and show how to turn our Markdown-based content into a production-ready website.

Why Hugo + Nginx on Ubuntu 24.04?

Performance: Hugo pre-renders every page as a simple HTML file. No database lookups or server-side rendering means pages load in a blink.

Security: With no backend code to exploit, static sites drastically reduce your attack surface.

Maintainability: Hugo’s theming and content organization keep everything in Git, so collaborating and rolling back changes is a breeze.

Stability: Ubuntu 24.04 LTS brings the latest kernel improvements, security patches, and long-term support, making it an ideal base for production.

Scalability: Nginx excels at serving static assets and can easily handle tens of thousands of concurrent requests with minimal memory footprint.

Prerequisites

Before we begin, let’s ensure we have the following in place:

Deploy Hugo Static Site on Ubuntu with Nginx

1. Prepare our Ubuntu Server

First, let’s update packages and install fundamental utilities:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl ufw

2. Install Hugo

Ubuntu’s official repositories sometimes lag behind Hugo’s latest release. We’ll use Snap to get the current stable version:

sudo snap install hugo --channel=extended
  • The extended channel includes Sass/SCSS support for advanced theming.
  • Snap packages are automatically updated with security patches.

Verify the install:

hugo version

Similar output: 

hugo v0.147.5-7766fc62416ff95ed7768c19947ac0fcd96444cc+extended linux/amd64 BuildDate=2025-05-22T11:37:19Z VendorInfo=snap:0.147.5

3. Create a New Hugo Site

Pick a directory (for example ~/myblog) and scaffold:

hugo new site myblog

This creates:

  • A clean folder structure under myblog/
  • An empty content/, layouts/, static/, and configuration file (hugo.toml)

4. Choose and Install a Theme

Most Hugo themes are on GitHub. For demonstration, let’s use the popular “PaperMod” theme:

cd myblog
git init
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod

Then edit hugo.toml to point at our theme:

nano hugo.toml

Adjust following content:

theme = "PaperMod"
baseURL = "https://example.com/"
languageCode = "en-us"
title = "My Hugo Blog"

Note: Replace https://example.com/ your domain name.

This minimal config activates PaperMod. We’ll customize colors and menus later—but for now, our theme is in place.

5. Write Content

Hugo makes it trivial to spin up new pages:

hugo new posts/my-first-post.md

Inside content/posts/my-first-post.md 

nano content/posts/my-first-post.md

You’ll find front matter:

---
title: "My First Post"
date: 2025-05-28T10:00:00+05:30
draft: true
---
  • Set draft: false when you’re ready to publish.
  • Use Markdown for body content.

We recommend keeping all images under static/images/ so they end up at /images/... on your live site.

6. Build the Site

When our content and config are ready, run:

hugo --minify
  • --minify strips out extra whitespace and compresses HTML/CSS/JS for faster page loads.
  • By default, Hugo outputs into the public/ directory.

7. Move the site out of /root and into a web-accessible path

Move your Hugo project

sudo mv ~/myblog /var/www/myblog

Give ownership to Nginx

sudo chown -R www-data:www-data /var/www/myblog

8. Install and Configure Nginx

sudo apt install -y nginx

Open HTTP (and later HTTPS) through the firewall:

sudo ufw allow 'Nginx Full'
sudo ufw enable

Create a server block for our site at /etc/nginx/sites-available/myblog:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/myblog/public;
    index index.html;

    # Cache static assets aggressively
    location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

    # Serve everything else
    location / {
        try_files $uri $uri/ =404;
    }
}

Note: Replace example.com your domain name.

Enable it and disable the default:

sudo ln -s /etc/nginx/sites-available/myblog /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t      # Validate syntax
sudo systemctl reload nginx

9. Secure with HTTPS (Let’s Encrypt)

We strongly recommend encrypting traffic. Install Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
  • Certbot will automatically update our Nginx config with a valid certificate and set up auto-renewal.
  • Test renewal: sudo certbot renew --dry-run

10. Automate Future Builds

When we update content, we must rebuild and redeploy. On small sites, a simple script suffices:

Create /usr/local/bin/deploy-myblog.sh:

nano /usr/local/bin/deploy-myblog.sh

Add following content:

#!/usr/bin/env bash
cd /srv/hugo-sites/myblog
git pull origin main        # Fetch new content or theme updates
hugo --cleanDestinationDir --minify
sudo systemctl reload nginx

Make it executable:

sudo chmod +x /usr/local/bin/deploy-myblog.sh

Now, whenever we merge new Markdown into main, a quick ./deploy-myblog.sh keeps our live site in sync. For full CI/CD, we can later integrate GitHub Actions or GitLab CI to call this script over SSH.

10. Monitoring and Best Practices

  • Logs: Check /var/log/nginx/access.log and error.log for traffic patterns or issues.
  • Backups: Keep your Git repository mirrored—both content and configuration—so you can recover quickly.
  • Performance: Use tools like Google Lighthouse to audit page speed and accessibility.
  • Scaling: For high-traffic sites, consider fronting Nginx with a CDN (e.g., Cloudflare) to offload TLS and caching.

In this tutorial, we'v3 deployed Hugo static site on Ubuntu with Nginx.  By following these steps, we’ve turned Markdown files into a blazing-fast, secure Hugo website served by Nginx on Ubuntu 24.04. As we grow our content, this foundation will stay rock-solid, letting us focus on what matters—creating great content—while our infrastructure quietly hums along. Happy publishing!