Ever thought of hosting your own website from the comfort of your own home—on a machine you already own? In this post, I’ll walk you through how I transformed my old laptop into a fully functional web server and used it to host my personal portfolio: mrzaizai2k.com.
This is my website:
This isn’t just a guide—it’s also a story. Whether you're trying to save money, repurpose old gear, or just learn something cool, you’ll find something valuable here.
📚 Table of Contents
- 💡 Why I Chose to Self-Host
- 🎓 What You’ll Learn
- 🛠 Tech Stack
- 🚀 Initial Setup
- 🐳 Containerize It with Docker
- 🌍 Open to the World: Cloudflare Tunnel vs. Port Forwarding
- 📈 Analytics Integration
- 📈 What’s Next: SEO Optimization
- 🔗 References
Why I Chose to Self Host
A while ago, I found myself with an old laptop that nobody wanted to buy at a fair price. The resale value? A joke. But giving it away felt wasteful. So instead, I decided to turn it into something useful.
This is my laptop:
That little spark of curiosity turned into a full-blown DIY web hosting setup. And now, that same machine proudly serves my personal site: mrzaizai2k.com.
What You'll Learn
By the end of this post, you’ll know how to:
✅ Build and run a portfolio website with React & Node
✅ Use Docker to containerize and simplify deployments
✅ Host it on your own machine securely using Cloudflare Tunnel
✅ Track visitors with Google Analytics
✅ Save money and learn valuable devops skills
Tech Stack
- React.js – Frontend framework
- Node.js – Backend JS runtime
- CSS3 – Styling
- Docker – Containers for easy deployment
- Nginx – Reverse proxy & lightweight protection
- Cloudflare Tunnel – Secure external access
Initial Setup
Start by cloning the repo and installing dependencies:
git clone https://github.com/mrzaizai2k/Portfolio.git
cd Portfolio
cd frontend
npm install
cd ..
Then, set up your .env file with your Google Analytics Measurement ID:
REACT_APP_GA4_MEASUREMENT_ID=G-XXXXXX
Containerize It with Docker
Docker makes things fast, repeatable, and clean.
Start your app:
docker-compose up -d
Visit: http://localhost:80
Stop the server:
docker-compose down
✨ Bonus: Live updates are supported thanks to volume mounts!
Open to the World: Cloudflare Tunnel vs. Port Forwarding
At this point, your site works locally—but how do you show it to the world?
You might think of opening a port on your router (port forwarding), but that’s not always practical.
My Thought Process
I first considered the usual router method. But here’s the thing:
- 🏠 Not all ISPs allow port forwarding (especially CG-NAT networks).
- 🧳 What if I move or switch networks? I’d have to reconfigure everything.
- 🛑 Security concerns—open ports are always a risk.
So instead, I used Cloudflare Tunnel. It creates an encrypted tunnel from your machine to the internet—no port configuration required.
🔍 Comparison Table
| Feature | Port Forwarding | Cloudflare Tunnel |
|---|---|---|
| 🔐 Security | Exposes open ports (less secure) | Encrypted, Cloudflare-protected |
| 🌐 ISP Compatibility | Not always allowed (CG-NAT issues) | Works with any ISP |
| 🛠 Router Access | Requires router login | No router access needed |
| 🚚 Flexibility (Change WiFi) | Needs reconfiguration | Works anywhere, instantly |
| 🌍 DNS Routing | Manual setup | Auto-managed with cloudflared
|
✅ Winner: Cloudflare Tunnel—secure, flexible, and dead-simple to set up.
Setup Instructions
Install & auth:
chmod +x cloudflare/install_cloudflared.sh
./cloudflare/install_cloudflared.sh
cloudflared tunnel login
Create a tunnel:
cloudflared tunnel create <Tunnel-NAME>
Configure it:
# config.yml
tunnel: <Tunnel-UUID>
credentials-file: /root/.cloudflared/<Tunnel-UUID>.json
ingress:
- hostname: mrzaizai2k.com
service: http://localhost:80
originRequest:
noTLSVerify: true
- service: http_status:404
Start and bind DNS:
To run the tunnel in the background, I installed Cloudflared service and started using following command.
cloudflared tunnel route dns <Tunnel-NAME> mrzaizai2k.com
cloudflared service install
systemctl start cloudflared
And that’s it—your local machine is now live to the world! 💥
Analytics Integration
Want to know who’s visiting your site?
- Create a Google Analytics account
- Set up a new property and web stream
- Grab your Measurement ID
- Paste it into your
.env:
REACT_APP_GA4_MEASUREMENT_ID=G-XXXXXX
Here’s what mine looks like:
And don’t forget—Cloudflare gives you real-time traffic insights too:
What’s Next: SEO Optimization
You’ve built and launched your site, but can people find it?
I’ll be diving deep into SEO optimization in my next post—where I’ll show you how I achieved loading scores like this:
Want your portfolio to rank higher on Google? Curious how to speed up your site and get that sweet, sweet organic traffic?
🔮 I’ll be revealing all the secrets soon—meta tags, schema markup, speed hacks, and more.
👉 Make sure to follow me so you don’t miss that post!
If you found this story helpful or inspiring:
💬 Like, Comment, and Share this post
🌟 Star the GitHub repo: mrzaizai2k/Portfolio
🌐 Visit my live site: mrzaizai2k.com




