<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[rj codes]]></title><description><![CDATA[rj codes]]></description><link>https://rjcodes.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 11:49:33 GMT</lastBuildDate><atom:link href="https://rjcodes.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I'm Running My Live Website Straight From My Own Laptop — Here's How]]></title><description><![CDATA[My website is not on any paid server. It's running right now on the laptop sitting on my desk at home — and anyone on the internet can visit it. Here is…]]></description><link>https://rjcodes.hashnode.dev/i-m-running-my-live-website-straight-from-my-own-laptop-here-s-how</link><guid isPermaLink="true">https://rjcodes.hashnode.dev/i-m-running-my-live-website-straight-from-my-own-laptop-here-s-how</guid><category><![CDATA[SelfHosting]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[oraclecloud]]></category><dc:creator><![CDATA[Rajnish Yadav]]></dc:creator><pubDate>Sat, 18 Apr 2026 06:07:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69dde84ddf3c2326fedf2b8e/e5d25681-3ae0-41e1-b212-61d39bfecfe6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>My website is not on any paid server. It's running right now on the laptop sitting on my desk at home — and anyone on the internet can visit it. Here is the full free setup using Rathole and an Oracle Cloud free VPS.</em></p>
<hr />
<h2>The Problem I Wanted To Solve</h2>
<p>I had a website (React frontend + Node.js backend + MongoDB) running on my <strong>Ubuntu laptop at home</strong>. I wanted to share it with the world — give a public link to friends, clients, and testers.</p>
<p>But there was a big problem: <strong>CG-NAT</strong>.</p>
<p>My internet provider (ISP) does not give me a real public IP address. They put hundreds of customers behind one shared IP. This is called <strong>Carrier-Grade NAT (CG-NAT)</strong>. Because of this:</p>
<ul>
<li>I cannot do normal port forwarding from my router.</li>
<li>Tools like ngrok work, but the free version gives random URLs and has limits.</li>
<li>Buying a VPS to host the full website is expensive and slow to set up.</li>
</ul>
<p>I wanted something that is:</p>
<ol>
<li><strong>Free</strong></li>
<li><strong>Permanent</strong> (same IP every time)</li>
<li><strong>Fast</strong> (because the website actually runs on my powerful laptop, not a tiny VPS)</li>
<li><strong>Simple</strong> to maintain</li>
</ol>
<p>The answer: <strong>Rathole + Oracle Cloud Free Tier VPS.</strong></p>
<hr />
<h2>What Is Rathole? (In One Line)</h2>
<p>Rathole is a small, fast program that creates a <strong>tunnel</strong> between a cheap VPS (with a public IP) and your home computer. People visit the VPS IP, and Rathole quietly forwards their request to your laptop.</p>
<p>Think of it like this:</p>
<pre><code>Visitor  →  VPS Public IP (Oracle)  →  [Rathole Tunnel]  →  My Laptop at Home
</code></pre>
<p>The visitor never knows the website is actually running in my bedroom.</p>
<hr />
<h2>What You Need Before Starting</h2>
<ol>
<li>A laptop or PC at home running <strong>Ubuntu</strong> (I used Ubuntu 20.04).</li>
<li>Your website / app running locally (mine runs on ports 3000 frontend, 4000 backend, 27017 MongoDB).</li>
<li>A <strong>free Oracle Cloud account</strong> (<a href="https://www.oracle.com/cloud/free/">https://www.oracle.com/cloud/free/</a>).</li>
<li>Basic terminal knowledge (copy-paste commands).</li>
<li>About 1–2 hours of patience the first time.</li>
</ol>
<p>That's it. No domain needed (you can add one later). No money needed.</p>
<hr />
<h2>The Big Picture (5 Stages)</h2>
<ol>
<li>Create a free VPS on Oracle Cloud and get a public IP.</li>
<li>Open the right ports in Oracle's firewall.</li>
<li>Install Rathole <strong>server</strong> on the VPS.</li>
<li>Install Rathole <strong>client</strong> on the laptop.</li>
<li>Start everything and test from your phone's mobile data.</li>
</ol>
<p>Let's go.</p>
<hr />
<h2>Stage 1: Create a Free Oracle Cloud VPS</h2>
<p>Oracle gives you a small Linux server <strong>forever free</strong>. It has only 1 GB RAM and 1 CPU — which sounds tiny, but <strong>we don't need power here</strong>. The VPS only forwards traffic. The real work happens on your laptop.</p>
<h3>Steps</h3>
<ol>
<li>Go to <a href="https://www.oracle.com/cloud/free/">https://www.oracle.com/cloud/free/</a> and sign up. (Credit card needed for verification, but they will not charge.)</li>
<li>In the Oracle Console, go to <strong>Compute → Instances → Create Instance</strong>.</li>
<li>Fill the form:<ul>
<li><strong>Name:</strong> <code>rathole-server</code></li>
<li><strong>Image:</strong> Ubuntu 22.04</li>
<li><strong>Shape:</strong> <code>VM.Standard.E2.1.Micro</code> (this is the "Always Free" one — make sure it says "Always Free Eligible")</li>
<li><strong>SSH Key:</strong> Click "Generate a key pair for me" and <strong>download both keys</strong>. Save them somewhere safe. You will not be able to download them again.</li>
</ul>
</li>
<li>Click <strong>Create</strong>. Wait 1–2 minutes.</li>
<li>After the instance starts, <strong>copy the Public IP address</strong>. It will look something like <code>203.0.113.45</code>. Write yours down — you will use it many times. (In this guide I will use <code>YOUR_VPS_IP</code> as a placeholder — replace it with your actual IP everywhere.)</li>
</ol>
<h3>Set permission on your SSH key (on your laptop)</h3>
<pre><code class="language-bash">chmod 400 ~/Downloads/ssh-key.key
</code></pre>
<p>Without this, SSH will refuse to use the key (security rule).</p>
<hr />
<h2>Stage 2: Open the Ports in Oracle's Firewall</h2>
<p>Oracle has <strong>two firewalls</strong> — this is the part where most beginners get stuck. You must open ports in <strong>both</strong>.</p>
<h3>Firewall 1: Oracle Security List (cloud-side)</h3>
<ol>
<li>Go to <strong>Networking → Virtual Cloud Networks</strong>.</li>
<li>Open your VCN → <strong>Security Lists → Default Security List</strong>.</li>
<li>Click <strong>Add Ingress Rules</strong> and add these rules one by one:</li>
</ol>
<table>
<thead>
<tr>
<th>Purpose</th>
<th>Source CIDR</th>
<th>Protocol</th>
<th>Port Range</th>
</tr>
</thead>
<tbody><tr>
<td>SSH</td>
<td><code>0.0.0.0/0</code></td>
<td>TCP</td>
<td>22</td>
</tr>
<tr>
<td>Rathole control</td>
<td><code>0.0.0.0/0</code></td>
<td>TCP</td>
<td>2333</td>
</tr>
<tr>
<td>Frontend ports</td>
<td><code>0.0.0.0/0</code></td>
<td>TCP</td>
<td>3000-3020</td>
</tr>
<tr>
<td>Backend ports</td>
<td><code>0.0.0.0/0</code></td>
<td>TCP</td>
<td>4000-4020</td>
</tr>
<tr>
<td>MongoDB</td>
<td><code>0.0.0.0/0</code></td>
<td>TCP</td>
<td>27017</td>
</tr>
</tbody></table>
<blockquote>
<p>⚠️ <strong>VERY IMPORTANT:</strong> The Source CIDR must be <code>0.0.0.0/0</code> (means "anyone on the internet"). By default Oracle suggests <code>10.0.0.0/8</code>, which only allows internal traffic. <strong>This was the mistake that wasted 2 hours of my life.</strong> Double-check it.</p>
</blockquote>
<p>I used port ranges (3000–3020, 4000–4020) instead of single ports so I have spare slots for future projects without coming back here.</p>
<p>We will set up Firewall 2 (iptables on the VPS) in Stage 3.</p>
<hr />
<h2>Stage 3: Install Rathole on the VPS (Server Side)</h2>
<h3>Step 1: SSH into the VPS</h3>
<pre><code class="language-bash">ssh -i ~/Downloads/ssh-key.key ubuntu@YOUR_VPS_IP
</code></pre>
<p>(Replace the IP with yours.) If it asks "Are you sure you want to continue?", type <code>yes</code>.</p>
<h3>Step 2: Update the system</h3>
<pre><code class="language-bash">sudo apt update &amp;&amp; sudo apt upgrade -y
sudo apt install unzip -y
</code></pre>
<h3>Step 3: Download Rathole v0.4.8</h3>
<pre><code class="language-bash">cd /tmp
wget https://github.com/rapiz1/rathole/releases/download/v0.4.8/rathole-x86_64-unknown-linux-musl.zip
</code></pre>
<blockquote>
<p><strong>Why exactly v0.4.8 musl?</strong> The "musl" version is a single static file — no extra libraries needed. It works on old and new Ubuntu the same way. Also, the <strong>server and client must be the same version</strong>, otherwise they will not talk to each other.</p>
</blockquote>
<h3>Step 4: Install it</h3>
<pre><code class="language-bash">unzip rathole-x86_64-unknown-linux-musl.zip
sudo mv rathole /usr/local/bin/
sudo chmod +x /usr/local/bin/rathole
rathole --version    # should print: rathole 0.4.8
</code></pre>
<h3>Step 5: Create the server config</h3>
<pre><code class="language-bash">mkdir -p ~/rathole &amp;&amp; cd ~/rathole
nano server.toml
</code></pre>
<p>Paste this (change the token to your own secret):</p>
<pre><code class="language-toml">[server]
bind_addr = "0.0.0.0:2333"
default_token = "my_secret_token_12345"

[server.services.frontend-3000]
type = "tcp"
bind_addr = "0.0.0.0:3000"
token = "my_secret_token_12345"

[server.services.backend-4000]
type = "tcp"
bind_addr = "0.0.0.0:4000"
token = "my_secret_token_12345"

[server.services.mongodb]
type = "tcp"
bind_addr = "0.0.0.0:27017"
token = "my_secret_token_12345"
</code></pre>
<p>What this means in plain English:</p>
<ul>
<li><code>bind_addr = "0.0.0.0:2333"</code> → The server listens on port 2333 for the client (your laptop) to connect.</li>
<li>Each <code>[server.services.xxx]</code> block says: "When someone visits this port on the VPS, forward it through the tunnel."</li>
<li><code>token</code> is a password so random strangers can't hijack your tunnel.</li>
</ul>
<p>Save (Ctrl+O, Enter) and exit (Ctrl+X).</p>
<h3>Step 6: Open ports in Firewall 2 (iptables on the VPS)</h3>
<p>This is the <strong>second firewall</strong>. Oracle's Ubuntu image comes with iptables blocking everything by default.</p>
<pre><code class="language-bash">sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 2333 -j ACCEPT
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 3000:3020 -j ACCEPT
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 4000:4020 -j ACCEPT
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 27017 -j ACCEPT

sudo apt install iptables-persistent -y
sudo netfilter-persistent save
</code></pre>
<p>The last line <strong>saves the rules so they survive a reboot</strong>. If you skip this, your tunnel will break the next time the VPS restarts.</p>
<h3>Step 7: Make Rathole start automatically (systemd service)</h3>
<pre><code class="language-bash">sudo nano /etc/systemd/system/rathole-server.service
</code></pre>
<p>Paste:</p>
<pre><code class="language-ini">[Unit]
Description=Rathole Server
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/rathole
ExecStart=/usr/local/bin/rathole /home/ubuntu/rathole/server.toml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
</code></pre>
<p>Save and exit. Then:</p>
<pre><code class="language-bash">sudo systemctl daemon-reload
sudo systemctl enable rathole-server
sudo systemctl start rathole-server
sudo systemctl status rathole-server
</code></pre>
<p>You should see <strong>active (running)</strong> in green. If yes, the VPS side is done. Type <code>exit</code> to leave the SSH session.</p>
<hr />
<h2>Stage 4: Install Rathole on Your Laptop (Client Side)</h2>
<p>Open a terminal on your <strong>home laptop</strong> (not the VPS).</p>
<h3>Step 1: Install the same Rathole version</h3>
<pre><code class="language-bash">cd /tmp
wget https://github.com/rapiz1/rathole/releases/download/v0.4.8/rathole-x86_64-unknown-linux-musl.zip
unzip rathole-x86_64-unknown-linux-musl.zip
sudo mv rathole /usr/local/bin/
sudo chmod +x /usr/local/bin/rathole
rathole --version
</code></pre>
<h3>Step 2: Test that the VPS is reachable</h3>
<pre><code class="language-bash">nc -zv YOUR_VPS_IP 2333
</code></pre>
<p>It should say <code>succeeded!</code>. If it says <code>refused</code> or hangs, go back and recheck <strong>both firewalls</strong> (Stage 2 and Stage 3 Step 6). Don't move on until this works.</p>
<h3>Step 3: Create the client config</h3>
<pre><code class="language-bash">mkdir -p ~/rathole &amp;&amp; cd ~/rathole
nano client.toml
</code></pre>
<p>Paste (use the <strong>same token and same IP</strong> as your server):</p>
<pre><code class="language-toml">[client]
remote_addr = "YOUR_VPS_IP:2333"
default_token = "my_secret_token_12345"

[client.services.frontend-3000]
type = "tcp"
local_addr = "127.0.0.1:3000"

[client.services.backend-4000]
type = "tcp"
local_addr = "127.0.0.1:4000"

[client.services.mongodb]
type = "tcp"
local_addr = "127.0.0.1:27017"
</code></pre>
<p>In plain English:</p>
<ul>
<li><code>remote_addr</code> → where the VPS is.</li>
<li>Each <code>[client.services.xxx]</code> block says: "When the VPS sends traffic for this service, deliver it to this local port on my laptop."</li>
<li>The <strong>service names must match exactly</strong> between server and client (<code>frontend-3000</code>, <code>backend-4000</code>, <code>mongodb</code>).</li>
</ul>
<h3>Step 4: Start your website locally</h3>
<p>Before starting the tunnel, your actual app must be running on your laptop:</p>
<pre><code class="language-bash"># Frontend (React/Vite)
cd ~/my-website/frontend &amp;&amp; npm run dev

# Backend (Node.js)
cd ~/my-website/backend &amp;&amp; npm start

# MongoDB usually runs as a service already
sudo systemctl status mongod
</code></pre>
<h3>Step 5: Start Rathole client</h3>
<pre><code class="language-bash">rathole ~/rathole/client.toml
</code></pre>
<p>You should see logs like:</p>
<pre><code>[INFO] Control channel established
[INFO] Service frontend-3000: Heartbeat established
[INFO] Service backend-4000: Heartbeat established
[INFO] Service mongodb: Heartbeat established
</code></pre>
<p>🎉 <strong>The tunnel is live.</strong></p>
<hr />
<h2>Stage 5: Test From the Real Internet</h2>
<p>This is the fun part. Open your <strong>mobile phone</strong>, <strong>turn off WiFi</strong>, and use <strong>mobile data</strong> (so you are testing from a real outside connection, not your home network).</p>
<p>In your phone browser, visit:</p>
<pre><code>http://YOUR_VPS_IP:3000
</code></pre>
<p>If your website loads — <strong>congratulations</strong>, you are now self-hosting from your bedroom. 🚀</p>
<p>Test the backend too:</p>
<pre><code>http://YOUR_VPS_IP:4000/api/health
</code></pre>
<hr />
<h2>Make the Client Auto-Start on Your Laptop Too</h2>
<p>Right now, if you close the terminal or reboot, the tunnel dies. Fix it the same way as the server:</p>
<pre><code class="language-bash">sudo nano /etc/systemd/system/rathole-client.service
</code></pre>
<pre><code class="language-ini">[Unit]
Description=Rathole Client
After=network.target

[Service]
Type=simple
User=YOUR_USERNAME
WorkingDirectory=/home/YOUR_USERNAME/rathole
ExecStart=/usr/local/bin/rathole /home/YOUR_USERNAME/rathole/client.toml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
</code></pre>
<p>Replace <code>YOUR_USERNAME</code> with your actual Linux username (run <code>whoami</code> to find out).</p>
<pre><code class="language-bash">sudo systemctl daemon-reload
sudo systemctl enable rathole-client
sudo systemctl start rathole-client
sudo systemctl status rathole-client
</code></pre>
<p>Now Rathole starts every time you boot your laptop. (You still need your dev servers running, of course.)</p>
<hr />
<h2>Mistakes I Made (So You Don't Have To)</h2>
<ol>
<li><strong>Source CIDR was 10.0.0.0/8 instead of 0.0.0.0/0</strong> in Oracle Security List. Nothing worked from the outside. Took me 2 hours to find.</li>
<li><strong>Forgot the second firewall (iptables) on the VPS.</strong> Oracle's Ubuntu image silently blocks ports even after you open them in the cloud console.</li>
<li><strong>Mismatched Rathole versions</strong> between server and client. Always use the same version on both sides.</li>
<li><strong>Forgot to save iptables rules.</strong> After a VPS reboot, the tunnel was broken. <code>netfilter-persistent save</code> fixes this.</li>
<li><strong>Started Rathole client before starting the local app.</strong> The tunnel works, but visitors get "connection refused". Always run your app first.</li>
<li><strong>Used CORS with <code>localhost</code> only</strong> in the backend. Once the site is on a public IP, you must allow that IP in CORS, otherwise the frontend will silently fail to call the backend.</li>
</ol>
<hr />
<h2>Why This Setup Is So Good</h2>
<ul>
<li><strong>Free forever.</strong> Oracle Always Free + Rathole open source = ₹0/month.</li>
<li><strong>Fast.</strong> Your website actually runs on your powerful laptop (16 GB RAM, SSD), not a 1 GB VPS. The VPS is just a postman.</li>
<li><strong>Permanent IP.</strong> Same address every time, no random ngrok URLs.</li>
<li><strong>Private.</strong> Your data stays on your hardware. The VPS never sees decrypted traffic if you add HTTPS later.</li>
<li><strong>Scalable.</strong> Want to host 5 more projects? Just add new service blocks in <code>server.toml</code> and <code>client.toml</code> and reload. I kept ports 3001–3020 spare for exactly this.</li>
</ul>
<hr />
<h2>What's Next</h2>
<p>Things I plan to add later, and maybe write follow-up blogs about:</p>
<ol>
<li><strong>A free domain</strong> (from DuckDNS or Freenom) so visitors don't have to type an IP.</li>
<li><strong>HTTPS with Let's Encrypt</strong> using Caddy or Nginx on the VPS as a reverse proxy in front of Rathole.</li>
<li><strong>A second tunnel</strong> for SSH so I can access my home laptop from anywhere.</li>
<li><strong>Monitoring</strong> with a simple uptime ping, so I know if the tunnel ever drops.</li>
</ol>
<hr />
<h2>Final Thought</h2>
<p>Before this setup, I thought self-hosting was only for people with expensive servers and static IPs. Turns out, with one free VPS and a 5 MB binary called Rathole, <strong>any normal laptop with normal home internet can host real websites for the world</strong> — even from behind a CG-NAT ISP.</p>
<p>If you got stuck anywhere, the two things to check first are always:</p>
<ol>
<li><strong>Both firewalls</strong> (Oracle Security List + VPS iptables).</li>
<li><strong>Both Rathole versions match.</strong></li>
</ol>
<p>Happy tunneling. 🕳️</p>
]]></content:encoded></item></channel></rss>