Skip to content

Instantly share code, notes, and snippets.

@moisoto
Last active June 17, 2025 17:44
Show Gist options
  • Save moisoto/837fe57ec21836d4108e348c2d0221df to your computer and use it in GitHub Desktop.
Save moisoto/837fe57ec21836d4108e348c2d0221df to your computer and use it in GitHub Desktop.
Installing an Oauth2-Proxy Restricted Hugo Website

Installing an Oauth2-Proxy Restricted Hugo Website

The purpose of this document is to detail the installation procedure for a Hugo Website with restricted access via Google's Oauth2-Proxy.

Such installation will be performed on a Debian OS, however it should apply with minor modifications to any Linux server.

Preparing the Server

Upgrade Debian Packages

sudo apt update
sudo apt upgrade

Install Git

sudo apt install git

Install Go Programming Language

# Download Latest Version
wget https://golang.org/dl/go1.16.2.linux-amd64.tar.gz

# Remove Previous Installation (not needed since it's not installed)
sudo rm -rf /usr/local/go 

# Install Go into /usr/local/go
sudo tar -C /usr/local -xzf go1.16.2.linux-amd64.tar.gz

# Create folder structure
mkdir ~/go
cd ~/go && mkdir src pkg bin prj

Edit .profile to set new paths

# set PATH so it includes Go binaries if they exists
if [ -d "/usr/local/go/bin" ] ; then
    PATH="$PATH:/usr/local/go/bin"
fi

Set Time Zone

sudo timedatectl set-timezone America/New_York

Install Hugo

For Hugo, the version provided by the package manager may be too old. It's better to download the most recent version.

You can check the latest version by visiting the release page for hugo at https://github.com/gohugoio/hugo/releases.

Here's an example of how to download and install the latest version:

# Download latest version
wget https://github.com/gohugoio/hugo/releases/download/v0.147.2/hugo_extended_withdeploy_0.147.2_linux-amd64.deb

# Instal .deb package
sudo dpkg -i hugo_extended_withdeploy_0.147.2_linux-amd64.deb

In case you need to install a more recent version you can uninstall by running the following:

# Remove and leave configuration files intact
sudo dpkg -r hugo

If for some reason you need to completely delete it, including the configuration files:

# Remove including configuration files.
sudo dpkg -P hugo

Install NGINX

You can install NGINX with the standard package manager:

sudo apt install nginx

Server Configuration

This section describes detailed configuration for a subdomain called static.mywebsite.com.

The choice of using a subdomain is merely to show that you can host several static Hugo websites within a single domain. However this procedure can be applied to a static website hosted on a domain.

Configure NGINX

To configure NGINX to receive requests from a subdomain. Create a configuration file at /etc/nginx/sites-available. For example create a file called static.mywebsite.com:

server {
    listen 80;
    listen [::]:80;

    server_name static.mywebsite.com;

    root /var/www/static;

    # Add index.php to the list if you are using PHP
    index index.html index.htm;

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

You can enable this website by adding a symbolic link in /etc/nginx/sites-enabled:

sudo ln -s /etc/nginx/sites-available/static.mywebsite.com /etc/nginx/sites-enabled/

Set proper permissions for your subdomain folder and files:

sudo mkdir /var/www/static
sudo chown -R www-data:www-data /var/www/static
sudo find /var/www/static -type d -exec chmod 755 {} \;
sudo find /var/www/static -type f -exec chmod 644 {} \;

Check nginx is configured properly:

sudo nginx -t
# Should display:
#   nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
#   nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload if configured properly:

sudo systemctl reload nginx

At this point you can easily test your website by placing an index.html file at /var/www/static and visiting your domain. The next step will be to add a certificate and allow access via https.

Installing Certbot

sudo apt install certbot python3-certbot-nginx

Create a Certificate for a given domain

sudo certbot --nginx -d static.mywebsite.com

NOTE: Make sure the port 443 is open in the server where the subdomain points to.

Check your updated nginx config

When running certbot with the --nginx option it will modify the configurations you have for the corresponding domain.

You'll see certbot updated your static.mywebsite.com nginx config file to something like:

server {
    server_name static.mywebsite.com;

    root /var/www/static;
    index index.html;  # Only include relevant index file

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

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/static.mywebsite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/tstatic.mywebsite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = static.mywebsite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name static.mywebsite.com;
    listen 80;
    listen [::]:80;
    return 404; # managed by Certbot
}

At this point you can test https access by testing your config and reloading nginx:

sudo nginx -t
sudo systemctl reload nginx

Installing Google oauth2-proxy

First check the latest version of Google's OAuth2 Proxy at: https://github.com/oauth2-proxy/oauth2-proxy/releases

Proceed to download. For example:

# Download
wget https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.9.0/oauth2-proxy-v7.9.0.linux-amd64.tar.gz

# Extract
tar -xzf oauth2-proxy-v7.9.0.linux-amd64.tar.gz

Install it by:

# Move the executable file
sudo mv oauth2-proxy-v7.9.0.linux-amd64/oauth2-proxy /usr/local/bin/

# Give Executable Permissions and set root owner
sudo chmod +x /usr/local/bin/oauth2-proxy
sudo chown nobody:nogroup /usr/local/bin/oauth2-proxy

OAuth2-Proxy configuration

You need to go to Google Cloud Services and Create a New OAuth2 Client ID.

The current URL for GCS would be: https://console.cloud.google.com/auth/clients

Create a new client ID of type Web Application. And make sure you specify an Authorized Redirect URI. For example: https://static.mywebsite.com/oauth2/callback

Make note of the Provided Client ID and Secret (Google will stop storing them sometime on 2025). Then create a configuration file at /etc/oauth2-proxy/oauth2-proxy.cfg:

# OAuth2-Proxy configuration
provider = "google"
client_id = "your-client_id"
client_secret = "your-secret"
redirect_url = "https://static.mywebsite.com/oauth2/callback"
oidc_issuer_url = "https://accounts.google.com"

# Restrict access to specific users or domains
email_domains = ["somedomain.com"]

# Optionally, restrict to specific emails
authenticated_emails_file = "/etc/oauth2-proxy/allowed-emails.txt"

# Cookie settings
cookie_name = "_oauth2_proxy"
cookie_secret = "8uIvUIWvz2BdghJoqNOuczB4v+02JcsYrUewg+ugQbA="  # Generate your own with: openssl rand -base64 32
cookie_domains = ".mywebsite.com"  # Allows cookies to be shared across subdomains
cookie_secure = true  # Enforce HTTPS
cookie_httponly = true
cookie_expire = "24h"

# Upstream service (your Hugo site served by NGINX)
# upstreams = ["http://127.0.0.1:80"]  # If you want, use this instead of /dev/null
# upstreams = "file:///dev/null" # Produces error
upstreams = []  # I recommend this instead of /dev/null

# Ports and endpoints
http_address = "127.0.0.1:4180"
reverse_proxy = true

# Whitelist domains for redirects
whitelist_domains = [".mywebsite.com"]

# Enable CSRF protection
cookie_csrf_per_request = true
cookie_csrf_expire = "24h"

# Skip provider button (directly redirect to Google login)
skip_provider_button = true

Take notice of the following entries on the config file:

  • Users will authenticate via a Google usernames (because the provider and oidc_issuer_url settings). You can let users from google.com access to your website, however Google Workspace users can have any domain name. Specify those on the email_domains list (substitute "somedomain.com" for "google.com" and/or any other domain).
  • You can further restrict access by specifying a file that lists the valid specific mail addresses (in this case "/etc/oauth2-proxy/allowed-emails.txt"). Comment the authenticated_emails_file setting if you want any user from the emain_domains list to have access.

Configure NGINX to use OAuth2-Proxy

Now update your NGINX configuration file so that it authenticate users with your OAuth2 Client:

server {
    server_name static.mywebsite.com;

    root /var/www/static;
    index index.html;  # Only include relevant index file

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/static.mywebsite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/static.mywebsite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # Protect your Hugo site
    location / {
        # Hugo-friendly routing
        try_files $uri $uri/ /index.html;  # Hugo client-side routing

        # Authenticate via OAuth2-Proxy
        auth_request /oauth2/auth;  # Authenticate via OAuth2 Proxy
        error_page 401 = /oauth2/start;  # Redirect to OAuth login on 401

        # Pass user info to the backend (optional)
        auth_request_set $user $upstream_http_x_auth_request_user;
        auth_request_set $email $upstream_http_x_auth_request_email;
        proxy_set_header X-User $user;
        proxy_set_header X-Email $email;
    }

    # OAuth2-Proxy endpoint
    location /oauth2/ {
        proxy_pass http://127.0.0.1:4180;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Handle OAuth2-Proxy authentication endpoint
    location = /oauth2/auth {
        proxy_pass http://127.0.0.1:4180;
        proxy_set_header X-Forwarded-Uri /oauth2/auth;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    if ($host = static.mywebsite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name static.mywebsite.com;
    listen 80;
    listen [::]:80;
    return 404; # managed by Certbo
}

Please notice that the modified entries were the location sections of the file.

NOTE: Make sure you check the configuration and if correct then reload nginx:

sudo nginx -t
sudo systemctl reload nginx

Additional OAuth2-Proxy configuration

The following instructions are optional but desirable in order to make user experience as good as possible.

Redirecting to original URI after login

I discovered a situation when the user tried to access a specific location on the website (not the homepage URL) and a login was requested by oauth2-proxy. After the login, the user would be redirected to the home page instead of the original URI.

To fix this I added a new parameter to the nginx config file on sites-available:

server {
    server_name static.mywebsite.com;

    #...
    #...

    # Protect your Hugo site
    location / {
        #...
        #...
        error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri;
        #...
        #...
    }

    # OAuth2-Proxy endpoint
    location /oauth2/ {
        #...
        #...
        #...        
        proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
    }

    # Handle OAuth2-Proxy authentication endpoint
    location = /oauth2/auth {
        #...
        #...
        proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
    }
}

The full config now reads:

server {
    server_name static.mywebsite.com;

    root /var/www/static;
    index index.html;  # Only include relevant index file

    # Performance optimizations
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;

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

    # Cache static assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|eot|pdf)$ {
        expires 30d;  # Cache for 30 days
        access_log off;  # Reduce logging overhead
    }

    # Disable logging for static files (optional)
    access_log off;  # Or configure a specific log file

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/static.mywebsite.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/static.mywebsite.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # Protect your Hugo site
    location / {
        # Hugo-friendly routing
        try_files $uri $uri/ /index.html;  # Hugo client-side routing

        # Authenticate via OAuth2-Proxy
        auth_request /oauth2/auth;  # Authenticate via OAuth2 Proxy
        error_page 401 = /oauth2/sign_in?rd=$scheme://$host$request_uri;

        # Pass user info to the backend (optional)
        auth_request_set $user $upstream_http_x_auth_request_user;
        auth_request_set $email $upstream_http_x_auth_request_email;
        proxy_set_header X-User $user;
        proxy_set_header X-Email $email;
    }

    # OAuth2-Proxy endpoint
    location /oauth2/ {
        proxy_pass http://127.0.0.1:4180;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
    }

    # Handle OAuth2-Proxy authentication endpoint
    location = /oauth2/auth {
        proxy_pass http://127.0.0.1:4180;
        proxy_set_header X-Forwarded-Uri /oauth2/auth;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
    }

}
server {
    if ($host = static.mywebsite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    listen [::]:80;
    server_name static.mywebsite.com;
    return 404; # managed by Certbot
}

Fix lost Request URI when login failed

Now that we handle the request URI another problem arises. If the login fails we are taking to a default error page generated by Oauth2-Proxy. This page has a button that sends you to the sign-in page to retry your login.

If you click that button, the Request URI will be the error page (instead of the initial URI the user tried to access). There's no easy workaround to this. So we will need to make our own error.html page.

The easiest way to solve this is to set a fixed redirect URL in our button like this:

<a href="/oauth2/sign-in?rd=https://static.mywebsite.com/">Sign In</a>

But then, we would lose the original Request URI anyways and it would be replaced by the website home page.

However there's another way around this, albeit a more complex one that could stop working in later oauth2-proxy versions. When redirected to the error page, you will see a state parameter in the URL, something like:

https://timeline.solopin.net/oauth2/callback?
state=ZwZB4NKy9f9mjIyChfQyXBiF2pbsMiK7V2Ac7MMLnfM:https://static.mywebsite.com/documents/somesubdir/

Notice there's a colon before the original URI. We can use javascript to detect this URI and use it as a redirect:

<script>
  document.addEventListener("DOMContentLoaded", () => {
    const params = new URLSearchParams(window.location.search);
    let rd = "/"; // Fallback to root

    const state = params.get("state");
    if (state && state.includes(":")) {
      const parts = state.split(":");
      const encodedUrl = parts.slice(1).join(":"); // Handle extra colons
      try {
        rd = decodeURIComponent(encodedUrl);
        // Validate rd is within allowed domain
        const url = new URL(rd);
        if (!url.hostname.endsWith("static.mywebsite.com")) {
          rd = "/"; // Fallback if outside domain
        }
      } catch (e) {
        console.warn("Failed to decode or validate rd from state:", e);
      }
    }

    const loginUrl = `/oauth2/sign_in?rd=${encodeURIComponent(rd)}`;
    const signInLink = document.getElementById("signin-link");
    if (signInLink) {
        signInLink.setAttribute("href", loginUrl);
    } else {
        console.warn("Sign-in link not found");
    }
  });
</script>

Our complete error.html file would be:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Authentication Error</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f4f4f9;
            color: #333;
        }
        .container {
            text-align: center;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }
        h1 {
            font-size: 24px;
            color: #d9534f;
        }
        p {
            font-size: 16px;
            margin: 10px 0;
        }
        a {
            display: inline-block;
            padding: 10px 20px;
            background-color: #0275d8;
            color: #fff;
            text-decoration: none;
            border-radius: 4px;
            font-size: 16px;
        }
        a:hover {
            background-color: #025aa5;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Authentication Error</h1>
	<p>Sorry, an error occurred during authentication.</p>
        <p>Please try again or contact support if the issue persists.</p>
        <a id="signin-link" href="/oauth2/sign-in">Sign In</a>
	<!-- <a href="/oauth2/sign_in?rd=https://timeline.solopin.net/">Sign In</a> -->
    </div>
    <script>
        document.addEventListener("DOMContentLoaded", () => {
            const params = new URLSearchParams(window.location.search);
            let rd = "/"; // Fallback to root

            const state = params.get("state");
            if (state && state.includes(":")) {
                const parts = state.split(":");
                const encodedUrl = parts.slice(1).join(":"); // Handle extra colons
                try {
                    rd = decodeURIComponent(encodedUrl);
                    // Validate rd is within allowed domain
                    const url = new URL(rd);
                    if (!url.hostname.endsWith("static.mywebsite.com")) {
                        rd = "/"; // Fallback if outside domain
                    }
                } catch (e) {
                    console.warn("Failed to decode or validate rd from state:", e);
                }
            }

            const loginUrl = `/oauth2/sign_in?rd=${encodeURIComponent(rd)}`;
            const signInLink = document.getElementById("signin-link");
            if (signInLink) {
                signInLink.setAttribute("href", loginUrl);
            } else {
                console.warn("Sign-in link not found");
            }
        });
    </script>
</body>
</html>

This file will be located at /etc/oauth2-proxy/template , so we need to create the template folder and then the error.html file inside it. Make sure the owner is nobody:nogroup

cd /etc/oauth2-proxy
sudo mkdir template
sudo touch template/error.html
sudo chown nobody:nogroup template
sudo chown nobody:nogroup template/error.html

Edit your error.html to something like was previously shown.

Finally you need to add the following like to your oauth2-proxy.cfg file:

custom_templates_dir = "/etc/oauth2-proxy/templates"

The final version of your oauth2-proxy.cfg file looks like this:

# OAuth2-Proxy configuration
provider = "google"
client_id = "your-client_id"
client_secret = "your-secret"
redirect_url = "https://static.mywebsite.com/oauth2/callback"
oidc_issuer_url = "https://accounts.google.com"
custom_templates_dir = "/etc/oauth2-proxy/templates"

# Restrict access to specific users or domains
email_domains = ["somedomain.com"]

# Optionally, restrict to specific emails
authenticated_emails_file = "/etc/oauth2-proxy/allowed-emails.txt"

# Cookie settings
cookie_name = "_oauth2_proxy"
cookie_secret = "8uIvUIWvz2BdghJoqNOuczB4v+02JcsYrUewg+ugQbA="  # Generate your own with: openssl rand -base64 32
cookie_domains = ".mywebsite.com"  # Allows cookies to be shared across subdomains
cookie_secure = true  # Enforce HTTPS
cookie_httponly = true
cookie_expire = "8h"
cookie_refresh = "1h"  # Refresh if token is valid and less than 1 hour from expiry
#cookie_refres = "0s"  # Disable token refresh for strict expiration

upstreams = []  # If you want use this instead of /dev/null

# Ports and endpoints
http_address = "127.0.0.1:4180"
reverse_proxy = true

# Whitelist domains for redirects
whitelist_domains = [".mywebsite.com"]

# Enable CSRF protection
cookie_csrf_per_request = true
cookie_csrf_expire = "24h"

# Skip provider button (directly redirect to Google login)
skip_provider_button = true

Hugo Website Publishing

During the server setup you installed Hugo, however you may have noticed that we are serving an static website via NGINX and don't need the Hugo Server running. The reason for installing Hugo was to allow local building of the static website by pulling from a repository.

You may implement this in any way you wish. The general idea is as follows:

  • Have your Hugo Website in a repository that can be accessed by your server and keep a local copy of it on the server.
  • Make a script that checks for new commits on the remote repository.
  • If new commits are detected:
    • Pull them in your local repository.
    • Build your static website with Hugo.
    • Publish the updated website by copying the files from the generated public folder to the NGINX published folder (/var/www/static).

Here is a sample script for checking and publishing the remote repository of the Hugo Website:

#!/bin/bash

# Repository Path
REPO_PATH="/home/admin/repo/your-hugo-website-repository"

# Submodule path and branch
SUBMODULE_PATH="content"
BRANCH="main"

# Publish Folder
PUB_FOLDER="/var/www/static"

# Check if the publish folder exists
if [ ! -d "$PUB_FOLDER" ]; then
  echo "Error: Folder '$PUB_FOLDER' does not exist."
  exit 1
fi

# Check if the repository folder exists
if [ ! -d "$REPO_PATH" ]; then
  echo "Error: Folder '$REPO_PATH' does not exist."
  exit 1
fi
cd $REPO_PATH

# Ensure the script is run from the parent repository's root
if [ ! -d ".git" ]; then
  echo "Error: This script must be run from the root of the parent Git repository."
  exit 1
fi

# Check if the submodule exists
if [ ! -d "$SUBMODULE_PATH" ]; then
  echo "Error: Submodule at '$SUBMODULE_PATH' does not exist."
  exit 1
fi

# Navigate to the submodule
cd "$SUBMODULE_PATH" || {
  echo "Error: Failed to navigate to submodule at '$SUBMODULE_PATH'."
  exit 1
}

# Ensure the submodule is on the correct branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$CURRENT_BRANCH" != "$BRANCH" ]; then
  echo "Switching submodule to branch '$BRANCH'..."
  git checkout "$BRANCH" || {
    echo "Error: Failed to checkout branch '$BRANCH'."
    exit 1
  }
fi

# Fetch the latest changes from the remote without merging
git fetch origin || {
  echo "Error: Failed to fetch updates from remote."
  exit 1
}

# Get the current local and remote commit hashes
LOCAL_COMMIT=$(git rev-parse HEAD)
REMOTE_COMMIT=$(git rev-parse "origin/$BRANCH")

# Check if there are new commits
if [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ]; then
  echo "Submodule '$SUBMODULE_PATH' is up to date."
  exit 0
else
  echo "New commits found in submodule '$SUBMODULE_PATH'. Pulling updates..." >> /home/admin/logs/publish.log
  git pull origin "$BRANCH" || {
    echo "Error: Failed to pull updates." >> /home/admin/logs/publish.log
    exit 1
  }
  echo "Submodule '$SUBMODULE_PATH' updated successfully."
fi

if [ ! -d "$REPO_PATH" ] ; then
   echo "Failed to Publish. Repo not found." >> /home/admin/logs/publish.log
   exit
fi

cd $REPO_PATH
hugo
sudo cp -R public/* $PUB_FOLDER
sudo chown -R www-data:www-data $PUB_FOLDER
sudo find $PUB_FOLDER -type d -exec chmod 755 {} \;
sudo find $PUB_FOLDER -type f -exec chmod 644 {} \;

echo "Website Updated at: `date`" >> /home/admin/logs/publish.log

This script assumes that your Hugo content folder is located at a submodule on your Hugo Website repository. This will allow you to have your content folder as a separate repository that can be accessed by anyone that you wish to be able to publish (by making new commits to it).

Automating Website Publishing

Ideally you want changes in the content repository to be automatically published on your server. The recommended way to do this is by creating a Timer in your Debian server.

Let's say the previous publishing script is located at /home/admin/repo/update-and-publish.sh. You would first create a service file at: /etc/systemd/system/check-repo-content.service:

sudo vi /etc/systemd/system/check-repo-content.service

The content would be:

[Unit]
Description=Check for Timeline Repository Content submodule updates
After=network-online.target

[Service]
Type=oneshot
ExecStart=/bin/bash /home/admin/repo/update-and-publish.sh
User=admin

Also create a timer file at /etc/systemd/system/check-repo-content.timer:

sudo vi /etc/systemd/system/check-repo-content.timer

With content:

[Unit]
Description=Run Publish Script  check every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target

After creating these files you must activate the timer:

sudo systemctl enable check-repo-content.timer
sudo systemctl start check-repo-content.timer
sudo systemctl list-timers
sudo systemctl status check-repo-content.timer
journalctl -u check-repo-content.timer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment