<?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[My Blogs]]></title><description><![CDATA[My Blogs]]></description><link>https://canant.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6ab4b7d2178e567f641c2b4b/8ffae00f-a936-405b-853c-ebe453078a35.jpg</url><title>My Blogs</title><link>https://canant.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 11 Oct 2026 16:58:52 GMT</lastBuildDate><atom:link href="https://canant.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The $5 VPS Setup Every Vibe Coder Needs (Skill Included)]]></title><description><![CDATA[AI has made building fast. I can go from an idea to a working prototype in an evening.
Getting it online is still where most of those prototypes die. The app runs on localhost, the demo is a screen re]]></description><link>https://canant.hashnode.dev/the-5-vps-setup-every-vibe-coder-needs-skill-included</link><guid isPermaLink="true">https://canant.hashnode.dev/the-5-vps-setup-every-vibe-coder-needs-skill-included</guid><category><![CDATA[vibe coding]]></category><category><![CDATA[self-hosted]]></category><category><![CDATA[Docker]]></category><category><![CDATA[skills]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Anant Chaudhary]]></dc:creator><pubDate>Thu, 24 Sep 2026 08:56:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ab4b7d2178e567f641c2b4b/d47dad54-6b22-4fe2-9ee6-36ef542a6116.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AI has made building fast. I can go from an idea to a working prototype in an evening.</p>
<p>Getting it <strong>online</strong> is still where most of those prototypes die. The app runs on <code>localhost</code>, the demo is a screen recording, and nobody else ever clicks on it. The feedback you actually need, from a real person using the real thing, never happens.</p>
<p>My answer to this has become boring on purpose: <strong>rent one small server, and set it up once, properly, so that every future idea is a subdomain away from being live.</strong></p>
<hr />
<h2>Why a server, and not another platform</h2>
<p>Hosting platforms are great until you have five experiments, a database, a background worker and a cache. Then you're juggling five dashboards, five free tiers and five sets of limits.</p>
<p>A small VPS costs about as much as a coffee a month and gives you:</p>
<ul>
<li><p><strong>One place for everything.</strong> Ten prototypes, their databases and their queues, all on one box.</p>
</li>
<li><p><strong>Real URLs in minutes.</strong> <code>idea-one.yourdomain.com</code>, <code>idea-two.yourdomain.com</code>. Send the link, get feedback the same day.</p>
</li>
<li><p><strong>No surprises.</strong> No per-app pricing and no cold starts. Nothing gets paused because it's on a free tier.</p>
</li>
<li><p><strong>Understanding.</strong> You learn what "deployed" actually means, which makes you better at the rest of your job.</p>
</li>
</ul>
<p>The catch, and the reason most people don't do this, is fear. And that fear is justified.</p>
<h2>The internet will find your server in minutes</h2>
<p>Put a server online and bots start knocking within minutes. They try passwords on SSH, look for open databases and hunt for admin panels. On my server, the logs showed bots probing the admin login page <strong>every single day</strong>.</p>
<p>Most "deploy to a VPS" tutorials open a web port, open a database port, put an admin panel on the internet, and call it done. It works, and it's also an open invitation.</p>
<p>So here is the setup I'm proposing instead. You don't need to become a DevOps engineer to run it. You just need to understand the picture.</p>
<h2>The architecture, in one picture</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6ab4b7d2178e567f641c2b4b/a754cf31-c6d1-41d0-8836-59e132a79ca8.png" alt="" style="display:block;margin:0 auto" />

<p>Here are the five ideas that make this safe, without the jargon.</p>
<h3>1. Your server has no front door</h3>
<p>Normally, a web server waits for visitors to connect to it, so it has to leave a door open (ports 80 and 443).</p>
<p>With a <strong>Cloudflare Tunnel</strong>, the direction is flipped. A small program on your server, <code>cloudflared</code>, calls <strong>out</strong> to Cloudflare and keeps that line open. Visitors go to Cloudflare, and Cloudflare passes their requests down the line your server opened.</p>
<p>It's the difference between leaving your door unlocked for deliveries and phoning the courier yourself. Nothing on your server is waiting for strangers. Your server's real address never even shows up in DNS; anyone looking it up sees only Cloudflare.</p>
<p>The only door left open is SSH, and that one takes keys only, with no passwords and no root login.</p>
<h3>2. A receptionist decides where each visitor goes</h3>
<p><strong>Traefik</strong> sits behind the tunnel and routes by name. <code>idea-one.yourdomain.com</code> goes to one container and <code>idea-two.yourdomain.com</code> to another.</p>
<p>This is the part that makes it great for prototyping. <strong>Launching a new idea means starting a container with a label that says which subdomain it answers to.</strong> There's no new server, no new certificate and no new firewall rule. Cloudflare handles HTTPS.</p>
<h3>3. The receptionist doesn't get the master key</h3>
<p>To know which containers exist, Traefik needs to talk to Docker. The obvious way is to hand it Docker's control socket. But full access to that socket is effectively <strong>root on your machine</strong>, and Traefik is the one component that talks to the internet all day.</p>
<p>So Traefik talks to Docker through a small guard (a "socket proxy") that only allows <strong>read</strong> requests: <em>what's running, and on which subdomain.</em> It can't create, start or change anything. If Traefik were ever compromised, the attacker would get a read-only view, not your server.</p>
<h3>4. Databases live in a back room with no windows</h3>
<p>Postgres and Redis sit on a private network that <strong>has no route to the internet</strong>, in either direction. Your apps can reach them, and nobody else can. The database also gets an account that can only work with its own tables, not an all-powerful admin account.</p>
<h3>5. The admin panel isn't on the internet at all</h3>
<p>Tools like Portainer are handy, but by design they can do anything to your server. Instead of putting a login page in front of that, take it off the internet entirely. It listens only on the server itself, and you reach it from your laptop through an SSH tunnel.</p>
<p>The strongest protection isn't a better lock. It's not having that door on the street at all.</p>
<p><strong>The result:</strong> from the internet, my server has exactly one open port, SSH. There's no web port, no database port and no admin panel. Everything else comes in through the tunnel, gets routed by name, and lands in a container that can only reach what it needs.</p>
<h2>"It's green" does not mean "it's safe"</h2>
<p>This is the lesson I most want vibe coders to take away.</p>
<p>While building this, I found things that <strong>looked perfectly healthy and weren't protected at all</strong>:</p>
<ul>
<li><p>Redis was set up with a password, and its health check said <em>healthy</em>. It was actually accepting connections with <strong>no password</strong>, because it couldn't read its password file and treated the empty result as "no password required."</p>
</li>
<li><p>The firewall said "deny everything," while Docker quietly bypassed it and exposed a port to the whole internet anyway.</p>
</li>
<li><p>A setting that was supposed to stop the proxy from starting containers was switched on and simply didn't work.</p>
</li>
</ul>
<p>None of these threw an error. AI-written setup scripts and copy-pasted tutorials fail the same way: the config reads correctly, the dashboard is green, and the door is open.</p>
<p>So the rule I now follow is: <strong>don't trust the config, test the behaviour.</strong> Knock on the door the way an attacker would, and see if it opens.</p>
<h2>I turned the whole thing into a skill</h2>
<p>I've packaged the whole thing as an <strong>AI agent skill</strong>: a set of instructions that an assistant like Claude Code follows to set this up on <em>your</em> server, with <em>your</em> domain. It asks you for the few things it needs, builds the setup step by step, and, most importantly, <strong>checks each step by actually trying to break it</strong> before it moves on.</p>
<p>I've tested it on a brand-new, empty server. About 30 minutes later it was hardened, my old site and database were restored onto it from a backup, and it was live, with every check passing.</p>
<p>You don't need to memorise the commands. What matters is understanding the picture above well enough to know when something is wrong. The skill handles the typing.</p>
<h2>Try it on your own server</h2>
<p><strong>What you need</strong></p>
<ul>
<li><p>A VPS with a fresh Ubuntu install (24.04 or newer). Any provider works, and the cheapest plan is plenty to start with.</p>
</li>
<li><p>A domain whose DNS is managed by Cloudflare. The free plan is enough.</p>
</li>
<li><p>An AI coding agent that supports skills, such as Claude Code, Cursor or Codex.</p>
</li>
<li><p>SSH access to the server. If all you have is the provider's root password, the skill helps you switch to a key.</p>
</li>
</ul>
<p><strong>1. Install the skill</strong> (one command, on your laptop):</p>
<pre><code class="language-bash">npx skills add anant-c/skills --skill vps-setup-for-vibe-coders
</code></pre>
<p><strong>2. Ask your agent for it</strong>, in plain words:</p>
<blockquote>
<p><em>"Help me set up my new VPS. The SSH alias is</em> <code>myserver</code> <em>and the domain is</em> <code>example.com</code><em>."</em></p>
</blockquote>
<p><strong>3. Answer a few questions.</strong> Which domain, what you're deploying, and whether you want an admin panel. That's the whole interview.</p>
<p><strong>4. Click twice in Cloudflare when it asks.</strong> First, create a tunnel and paste its token back to the agent. Second, add two routes, <code>example.com</code> and <code>*.example.com</code>, both pointing at <code>http://traefik:80</code>. Then switch on <strong>Always Use HTTPS</strong>.</p>
<p><strong>5. Read the report at the end.</strong> The skill scans your server from the outside, where the only open port should be SSH, and runs a 19-point health check. Then it tells you plainly what it <em>didn't</em> cover, such as off-site backups.</p>
<p>After that, launching a new idea is one sentence to your agent: <em>"deploy this app at idea-one.example.com."</em></p>
<p><strong>Links</strong></p>
<ul>
<li><p>On skills.sh: <a href="https://skills.sh/anant-c/skills/vps-setup-for-vibe-coders">skills.sh/anant-c/skills/vps-setup-for-vibe-coders</a></p>
</li>
<li><p>Source on GitHub: <a href="https://github.com/anant-c/skills/tree/main/skills/vps-setup-for-vibe-coders">github.com/anant-c/skills</a></p>
</li>
</ul>
<p>A skill runs with your agent's permissions, so read it before you run it. It's plain Markdown and takes about ten minutes to skim, and the traps file alone is worth reading.</p>
<hr />
<h2>This is the first of a series, if you want it</h2>
<p>Here's what I want to build: <strong>one piece of infrastructure per post.</strong> First the intuition, explained so you don't need a CS degree to follow it. Then a skill that sets it up for you and <strong>proves it's safe by trying to break it.</strong></p>
<p>Because vibe coding shouldn't force you to choose between shipping fast and shipping safe. Developers get to move faster. Vibe coders get to ship something real, not a demo held together by hallucinated config and a green checkmark that's lying to them.</p>
<p><strong>What should I break down next?</strong></p>
]]></content:encoded></item></channel></rss>