Hosting my website on a VPS — A Practical Guide#
This post is both a story and a how‑to: how I set up and now host probablyworks.nl on my own VPS using Docker, Caddy, and Hugo.
If you want full control, HTTPS by default, and a setup that scales from a side project to something serious — this is for you.
Why host your own site?#
Static hosting platforms are great, until you want:
- Full control over your stack
- Custom routing or multiple apps on one server
- Zero vendor lock‑in
- To actually understand how your site is served
A VPS gives you all of that — and with modern tooling, it’s not scary anymore.
What we’re building#
End result:
- A VPS running Ubuntu
- Docker + Docker Compose
- A Hugo static site (Hugo Book + custom landing page)
- Caddy as the web server
- Automatic HTTPS (Let’s Encrypt)
- A real domain:
probablyworks.nl
All reproducible. All documented.
1. Get a VPS#
Any provider will do. Requirements are modest:
- Ubuntu 24.04 (other versions and distro’s will also work)
- Public IPv4 address
- SSH access
Once created, log in via the provider console (not SSH yet).
2. Enable SSH access#
Install and start OpenSSH:
sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now sshCreate a non‑root user:
adduser [username]
usermod -aG sudo [username]From here on, everytime you see username, replace it with your own created username.
Add your SSH key to:
/home/username/.ssh/authorized_keysFix permissions:
chmod 700 /home/username/.ssh
chmod 600 /home/username/.ssh/authorized_keys
chown -R username:username /home/username/.sshNow log in as:
ssh username@YOUR_SERVER_IPOnce this works, disable root SSH login.
3. Install Docker#
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-pluginAllow your user to run Docker:
sudo usermod -aG docker username
exitLog back in and test:
docker run hello-world4. Clone your website repo#
git clone git@github.com:YOURNAME/YOURREPO.git
cd YOURREPOThis repo contains:
- Hugo source
- A multi‑stage Dockerfile
- A Docker Compose setup with Caddy
5. Configure Hugo for a subpath#
The site is served at:
https://probablyworks.nl/Obvisouly, the website you’re on now. So in the next part, replace this website with your own.
So Hugo must know this.
In hugo.toml:
baseURL = "https://probablyworks.nl/"
languageCode = "en-us"
title = "Tom's playground"
theme = ["hugo-book"]
[params]
BookSection = "blog"
BookBaseURL = "/blog"
BookSearch = true
BookToC = true
BookCustomCSS = ["css/custom.css"]This is critical for Hugo Book to load CSS, JS, and navigation correctly.
6. Configure Caddy for production#
Your Caddyfile should look like this:
{$DOMAIN} {
root * /usr/share/caddy
file_server
encode zstd gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
}
}
www.{$DOMAIN} {
redir https://{$DOMAIN}{uri}
}No manual TLS config. Caddy handles HTTPS automatically.
7. Point your domain to the VPS#
At your DNS provider:
A probablyworks.nl → YOUR_SERVER_IP
A www.probablyworks.nl → YOUR_SERVER_IPRemove any AAAA records unless you really want IPv6.
Verify from the server:
dig probablyworks.nl +short8. Start the site#
Create a .env file next to docker-compose.yml:
DOMAIN=probablyworks.nl
ACME_EMAIL=admin@probablyworks.nlThen run:
docker compose build --no-cache
docker compose up -d
docker compose logs -fYou should see Caddy obtaining certificates.
9. You’re live#
Open:
You now have:
- A fully static site
- Automatic HTTPS
- A reproducible Docker setup
- Zero platform lock‑in
Final thoughts#
This setup scales surprisingly far:
- Add more sites behind Caddy
- Add CI/CD with GitHub Actions
- Add monitoring or backups
- Move providers without changing your stack
Happy hosting.