The idea of building a personal site started back in September last year. I got a student-discounted instance from Alibaba Cloud (2 cores, 2GB RAM), and even went through the hassle of registering a domain name: changyi.fun
.
At first, I used WordPress. It worked — until it didn’t. I remember in one of my security classes, the professor specifically called out WordPress for being notoriously insecure. Around the same time, I tried to set up an SSL certificate (in the most complicated way possible via DNS challenge), and ended up completely breaking the site. I didn’t know back then that there were simpler ways.
After that, the site just sat there, broken and abandoned.
Phase One: The Ghost of WordPress Past
Fast forward to this week — I landed an internship, had some free time, and figured it was time to revive my personal site. So I started fresh by wiping the old WordPress setup.
Here came the first headache: even after resetting the server, visiting my domain still showed the old broken redirect page.
I checked the instance — no process was listening on port 80. Eventually, I realized it was just a stale browser cache issue. That previous fallback page probably didn’t set any cache expiry headers. After manually clearing my cache, problem solved.
Phase Two: Finding the Right Tool
Next, I started evaluating frameworks.
I first tried Halo, an open-source CMS that’s somewhat like WordPress, with a nice UI and admin panel. It worked smoothly, and the themes looked better than WordPress.
But then:
- It didn’t support English themes well
- Language switching wasn’t intuitive
- The admin system felt over-engineered for my simple needs
Enter Hugo: Static, Simple, and Just Enough
Eventually, I stumbled upon Hugo — and it was exactly what I wanted:
- Clean, simple, and modular
- Highly customizable
- Great theme support (I’m using PaperMod, which has solid documentation)
- Blazing fast static site generator
- Easy to back up via GitHub — no database, no risk of losing content
(Shout out to the 4 blog posts I lost forever on WordPress. Rest in peace.)
CI/CD Setup: Push to GitHub, Deploy to Server
Once the Hugo site was up locally, I wanted a basic CI/CD flow:
Every time I push to GitHub, I want my server to automatically pull the changes and update the site.
There were two options:
- GitHub Actions (but configuring it to SSH into my instance and copy files felt like too much hassle)
- GitHub Webhooks (simpler, server does the work)
So I built a tiny Python server that listens on port 9000
and executes a deploy script when it receives a POST
request.
Then I registered it as a systemd service to keep it running in the background. It worked like a charm.
Hardening the Setup: Security First
HTTPS + SSL
Since I had previously broken WordPress trying to manually install SSL, I was nervous.
Turns out: you don’t need your old certificate or private key — you just need to prove domain ownership.
With certbot
and the nginx plugin, it took one line:
sudo certbot --nginx -d changyi.fun
And boom — HTTPS was on. No pain, no tears.
Secure Webhook Access
To avoid exposing port 9000, I used Nginx as a reverse proxy to route /deploy to the internal Python server (bound to 127.0.0.1).
I also added a shared secret token for HMAC signature validation:
GitHub signs the payload using the shared secret
My Python server verifies the X-Hub-Signature-256 header
If the signature matches, the script runs
Super lightweight. Super secure.
Key Takeaways
-
Don’t over-engineer things. Use the simplest tool that meets your needs.
-
As a developer, stay close to your code. Fancy GUIs can slow you down or abstract away the wrong parts.
-
Expect small surprises. Even something as silly as browser caching can waste an hour. What matters is your ability to debug and stay calm.
And now… it’s live!
If you’re seeing this post — congrats, the whole pipeline worked.
Thanks for reading :)