Hosting This Website

Jan 25, 2026 Update: Jan 25, 2026 1100 Words

Gonna quickly outline this:

I chose to do this in the most complicated way possible. It’s a learning process!

Bought a domain on porkbun Renting a VPS on racknerd

Firstly I knew I should get source control going. I figured this would be a good opportunity to (re)learn git, so I checked out the process getting that hosted on my shiny new VPS. I followed this guide.

I did have to add some .gitkeep files (make sure empty directories submit) as well as a .gitignore (don’t submit /public). Make sure you set that stuff up first, then you can submit your Hugo site.

On the VPS (remote server)

mkdir git
cd git
mkdir websitename.git
cd websitename.git/
git init --bare

Local (in this case a Windows machine using powershell)

cd ~/websitename
git init
git add .
git commit -m 'initial commit'
git remote add origin sshuser@sshIP:/home/usernameOnServer/git/websitename.git
git push origin main
git status

Hey, here is a fun side note: many tutorials you find have the default branch name as “master” - yeah, we don’t do that here. Git apparently now defaults to main, which caused my unobservant ass some grief.

VScode automagically has git support and is pretty self explanatory on how to use it if you have any source control experience. I tested with a quick test push and it seemed to work ok.

OK, where to actually host the site? Well, for simplicity I figured I’d use the same VPS the git is on. Easy, right? nginx is a super lightweight webserver, so I can use that to host. But how to actually get the files on the VPS, you know, as regular ole files not in a repo? Wait, if they are in a repo, couldn’t I automatically detect when the files are submitted and run Hugo on the VPS itself?

Turns out, yeah dawg, that is a thing. In my infinite wisdom I decided that I wanted to be one of the cool kids / hacker elite by actually implementing CD myself rather than use github or whatever. C’mon, it’s just a git hook, right? How bad could it be?

Actually, the git hook is conceptually simple. I mostly followed this fellow again. You write a lil file: $GITREPO/hooks/post-receive (this is on the git server ) Shamelessly reposting their code here:

#!/bin/bash

export GIT_WORK_TREE=/home/username/www/websitename

echo `pwd`
echo "Generating site with Hugo"

# Create the directory and all subdirectories if they don't exist.
mkdir -p $GIT_WORK_TREE
chmod 755 $GIT_WORK_TREE

# Check out the contents of the repository and extract the files to $GIT_WORK_TREE
git checkout -f master

# Remove any files already in the public directory, a fresh copy will be generated by hugo
rm -rf $GIT_WORK_TREE/public

# Generate the site with hugo
cd $GIT_WORK_TREE && /usr/bin/hugo                                                                                                            

# Fix any permission problems.
find $GIT_WORK_TREE/public -type f -print | xargs -d '\n' chmod 644
find $GIT_WORK_TREE/public -type d -print | xargs -d '\n' chmod 755

echo "Hugo site generation complete"

The tutorial warns about permission stuff, but on first trial things seemed to work ok. The site files appeared at “/home/username/www/websitename” when I submitted. Success?

I moved onto hosting. I installed nginx, a super lightweight webserver, and figured it would be easy. Immediately ran into some problems.

Firstly, I was already running Pangolin on the server with the hopes of one day getting my jellyfin server accessible remotely. This “reverse proxy” service thing essentially takes incoming port 80 or 443 requests (presumably from domain / subdomain stuff) and routs the traffic just about anywhere, including remote setups. Cool. But, complicated.

nginx immediately complained that port 80 was occupied and wouldn’t run. I did some research and found that you can define a different port in the /etc/nginx/sites-available/default (or you can define a different file? Who knows) so I picked a random different port and with some effort told pangolin to route traffic there.

server {
       listen randomport;
       listen [::]:randomport;

       root /home/username/www/website/public;
       index index.html; # Hugo generates HTML

       location / {
               try_files $uri $uri/ =404; # no idea lol
       }
}

Well, it didn’t work. Why?

Permissions. Permissions permissions permissions.

All these services need, like, full access to the public files, I guess? And stackoverflow is overflowing with ancient posts about linux permissions and users and whatnot. It is a nightmare, and I wish I could accurately tell you what I did to get it working. Essentially I think I changed the user that nginx was running as, but apparently that is bad practice? I dunno man.

I finally was able to get the service running. In pangolin, you have to set up a local site (easy) then set the resource routing to 172.17.0.1 to access the local machine (not intuitive but kinda obvious in hindsight). The site works!

…but of course the ssl crap isn’t working right. Some pages display ok, but others are “unsecure”. But why? I’m running the whole thing through pangolin, it is supposed to do it!

Turns out in my navbar I had set the links… wrong?

    <div class="navbar-start">
      <a class="navbar-item" href="/about">
        About
      </a>
      <a class="navbar-item" href="/posts">
        Blog
      </a>

They have to be set like this:

    <div class="navbar-start">
      <a class="navbar-item" href="/about/">
        About
      </a>
      <a class="navbar-item" href="/posts/">
        Blog
      </a>

Yeah.

Of course this meant I needed to update the code. No big deal, right? Time to test the “Continuous Deployment”.

Yeah, naw, of course it broke. Took me a while but I finally found out that my git hook from earlier ALSO lacked permission to actually remove the files from the public folder (you know, to rebuild them?). Some more chown nonsense later and it works. And by some, I mean I had to make 7 additional “test” commits before things started kicking.

But yeah, it works now! I think! Writing all this is a test of adding a file. Can’t wait for the file to have the wrong permissions. Honestly I kinda expect it.

Good lord did I have trouble with this. I… I don’t really know how the cool hacker kids do their thing. Messing around with all the terminals and ssh shit and bash and whatnot really tests both my patience and memory. As I write this (just after successfully getting the damn thing online) I’ve got like 18 tabs open over 3 windows, 3 terminals, couple of notepad++ along with vsCode itself- total mess. I dunno if you just get better overtime with remembering where such and such config file lives and whatever the hell “chown” actually does. I feel like a fucking chown, maybe that is why they call it that.

Anyways, gotta try this out, I’ll organize the post later!