After building your blog with Hugo + Stack, the next step is deploying it to your cloud server.
My VPS environment: Ubuntu 24.04
The setup I use:
- Caddy as the web server
- SSH + rsync to sync static files
Workflow:
Generate static files locally → One-click sync to VPS → Caddy automatically serves the new content.
Let’s go through it step by step 👇
Server Setup
Install the Caddy service:
|
|
Check if Caddy is installed successfully:
|
|
At this point, if you open http://VPS_IP in your browser, you should see the default Caddy welcome page.
Now, create a directory for your blog. I put all my site files under /var/www/sirenlingyu/:
|
|
Edit the Caddyfile configuration:
|
|
Comment out everything starting from :80 and add the following:
|
|
⚠️ Replace sirenlingyu.com with your own domain name. Make sure your domain is already pointing to your VPS. Also replace yourmail@example.com with your own email — Caddy will automatically issue an SSL certificate for you.
Before Caddy can auto-generate certificates, make sure the caddy user has permission to access its working directory:
|
|
Then reload the Caddy service:
|
|
Set Up SSH Key Login
For security reasons, I created a separate user called deploy on the VPS. This user can only access the website directory and is used purely for SSH deployment.
Create the deploy user:
|
|
Give that user access to the website directory:
|
|
On your local computer, generate a new SSH key pair:
|
|
Press Enter all the way through — it’ll generate two files: ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519.pub
Display the public key:
|
|
Then, on your VPS, add the public key to the deploy user:
|
|
Test the SSH login:
|
|
Deploy the Static Files to the Server
In your local Hugo blog directory, build the static site:
|
|
Then run rsync to deploy it:
|
|
Once that’s done, visit https://sirenlingyu.com — my blog should be live! 🎉
One-Click Deployment Script
To make updates easier, I wrote a simple deploy.sh script and placed it in the root of the blog directory:
|
|
Give it execute permission:
|
|
Now, whenever you update your blog, just run:
|
|
And that’s it — one command, fully automated deployment. 🚀