Files
blog/DEPLOYMENT.md

5.9 KiB

Deployment Guide for LXC Container

This guide explains how to deploy this Hugo website to an LXC container running Arch Linux (or similar). The site is built as a static site and served via nginx.

Prerequisites

  • LXC container with Arch Linux (or adjust package manager commands for your distribution)
  • SSH access to the container
  • Git installed on container
  • Domain name dustin.coffee pointing to container's IP address (or adjust baseURL in hugo.toml)

Step 1: Install Hugo Extended on LXC

Important: This theme requires Hugo extended version ≥ 0.123.0. Ubuntu's default apt repository provides an outdated version (v0.123.7). You must install a newer extended version.

Copy the install-hugo.sh script to your container and run it:

# On your container, as root or with sudo:
chmod +x install-hugo.sh
./install-hugo.sh

Option B: Manual installation for Ubuntu/Debian

# Remove old Hugo if installed
sudo apt remove -y hugo

# Add Hugo APT repository
ARCH=$(dpkg --print-architecture)
echo "deb [arch=${ARCH} signed-by=/etc/apt/keyrings/hugo.gpg] https://hugo-apt.8hob.io latest main" | sudo tee /etc/apt/sources.list.d/hugo.list
sudo chmod 644 /etc/apt/sources.list.d/hugo.list

# Add signing key
sudo mkdir -p /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/hugo.gpg https://hugo-apt.8hob.io/signing-key
sudo chmod 644 /etc/apt/keyrings/hugo.gpg

# Pin repository priority
echo 'Package: hugo
Pin: origin "hugo-apt.8hob.io"
Pin-Priority: 520' | sudo tee /etc/apt/preferences.d/hugo
sudo chmod 644 /etc/apt/preferences.d/hugo

# Install Hugo Extended
sudo apt update
sudo apt install -y hugo

# Install git (required for Hugo modules)
sudo apt install -y git

Verify installation

Check that you have the extended version:

hugo version
hugo env | grep HUGO_EXTENDED
# Should show: HUGO_EXTENDED=true

If hugo version shows v0.123.7 or earlier, the installation failed. Try Option B or install the binary manually from Hugo releases.

Step 2: Clone Repository

Clone your git repository to a directory, e.g., /srv/www/dustin.coffee:

sudo mkdir -p /srv/www
sudo chown $USER:$USER /srv/www
cd /srv/www
git clone <your-git-repo-url> dustin.coffee
cd dustin.coffee

Step 3: Build Static Site

Generate the static site:

hugo --minify

The built site will be in the public/ directory.

Step 4: Install and Configure nginx

Install nginx:

sudo pacman -S nginx

Create nginx configuration file at /etc/nginx/sites-available/dustin.coffee (create directory if needed):

server {
    listen 80;
    listen [::]:80;
    server_name dustin.coffee www.dustin.coffee;

    root /srv/www/dustin.coffee/public;
    index index.html;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

    location / {
        try_files $uri $uri/ =404;
    }

    # Cache static assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }
}

Enable the site by creating a symlink:

sudo ln -s /etc/nginx/sites-available/dustin.coffee /etc/nginx/sites-enabled/
sudo nginx -t  # Test configuration
sudo systemctl restart nginx

Install certbot:

sudo pacman -S certbot certbot-nginx

Obtain certificate:

sudo certbot --nginx -d dustin.coffee -d www.dustin.coffee

Certbot will automatically update nginx configuration.

Step 6: Automation Script

Create a deployment script deploy.sh in the repository root:

#!/bin/bash
# deploy.sh - rebuild and copy site

set -e

cd /srv/www/dustin.coffee

# Pull latest changes
git pull

# Build site
hugo --minify

# Optional: restart nginx if configuration changed
# sudo systemctl reload nginx

echo "Deployment completed at $(date)"

Make it executable:

chmod +x deploy.sh

Now after SSH-ing into the container, you can run ./deploy.sh to update the site.

Step 7: Systemd Service (Alternative: Hugo Server)

If you prefer to run Hugo as a server (not recommended for production), create a systemd service:

Create /etc/systemd/system/hugo-dustin.service:

[Unit]
Description=Hugo Server for dustin.coffee
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/srv/www/dustin.coffee
ExecStart=/usr/bin/hugo server --bind 0.0.0.0 --port 1313 --baseURL=https://dustin.coffee/
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then enable and start:

sudo systemctl daemon-reload
sudo systemctl enable hugo-dustin
sudo systemctl start hugo-dustin

Notes

  • Update the baseURL in hugo.toml if your domain changes.
  • The site uses a custom theme personal; ensure all theme files are committed to git.
  • Blog posts are stored in content/posts/ as markdown files.
  • To add new blog posts, create markdown files in content/posts/ on your development machine, push to git, then run the deploy script on the container.

Troubleshooting

  • If nginx shows 404, ensure the public/ directory exists and contains built files.
  • If Hugo fails to build, check Hugo version matches the one used in development.
  • Check nginx error logs: sudo journalctl -u nginx
  • Check Hugo build logs: run hugo --verbose

Updating

To update the site after making changes on your development machine:

  1. Push changes to your git server
  2. SSH into LXC container
  3. Navigate to site directory: cd /srv/www/dustin.coffee
  4. Run git pull then ./deploy.sh (or just hugo --minify)