<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dhruv malaviya</title>
    <description>The latest articles on DEV Community by Dhruv malaviya (@dhruv_malaviya_cdcc71e595).</description>
    <link>https://dev.to/dhruv_malaviya_cdcc71e595</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3964043%2Fdf5eaffb-4a72-4192-97c9-e06ca85c2406.JPG</url>
      <title>DEV Community: Dhruv malaviya</title>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhruv_malaviya_cdcc71e595"/>
    <language>en</language>
    <item>
      <title>I Gave an AI Agent Root Access. Nothing Broke.</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Tue, 25 Aug 2026 12:35:43 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/i-gave-an-ai-agent-root-access-nothing-broke-3hmc</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/i-gave-an-ai-agent-root-access-nothing-broke-3hmc</guid>
      <description>&lt;p&gt;How I sandbox LLM agents in disposable Firecracker microVMs on Krova Cloud — no public IP, one-command lifecycle, and why containers weren't a real boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why containers weren't enough&lt;/strong&gt;&lt;br&gt;
The standard advice — "run the agent in a Docker container, drop privileges" — fails in one specific way: containers share a kernel. Every container on that host is one kernel bug away from its neighbors. That's exactly why Firecracker exists. AWS built it to run other people's code at scale because namespaces weren't a real boundary.&lt;/p&gt;

&lt;p&gt;So the agent gets a microVM. Own kernel, own rootfs, own everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The setup&lt;/strong&gt;&lt;br&gt;
On Krova Cloud each microVM is called a Cube. Whole provisioning is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm i -g @krovacloud/cli

krova cubes create agent-1 --cpu 2 --ram 4 --disk 40 --image ubuntu-24.04
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;✓ Cube provisioned  ·  booted &lt;span class="k"&gt;in &lt;/span&gt;0.9s
&lt;span class="go"&gt;
krova ssh agent-1
&lt;/span&gt;&lt;span class="gp"&gt;root@agent-1:~#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things matter here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No public IP. The Cube sits on a private NAT'd network. There's no address to scan, no port 22 on the internet, no inbound surface. Check for yourself from inside:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@agent-1:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip &lt;span class="nt"&gt;-brief&lt;/span&gt; addr
&lt;span class="go"&gt;lo               UNKNOWN        127.0.0.1/8
&lt;/span&gt;&lt;span class="gp"&gt;eth0             UP             10.0.x.x/24   #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;private. that&lt;span class="s1"&gt;'s it.
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;root@agent-1:~#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt;
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;only listeners &lt;span class="k"&gt;*&lt;/span&gt;you&lt;span class="k"&gt;*&lt;/span&gt; started — nothing is reachable from outside
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traffic only enters through ports you explicitly open, and those can be IP-allowlisted. For an agent box, I open nothing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's disposable. Boots in under a second, billed by the minute. So I stopped treating it as a pet: each agent session gets a fresh Cube, and when the session ends it's deleted. No leftover cron jobs, no stale credentials sitting in a long-lived environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The session lifecycle I actually run&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;CUBE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"agent-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# fresh box per session&lt;/span&gt;
krova cubes create &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUBE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--cpu&lt;/span&gt; 2 &lt;span class="nt"&gt;--ram&lt;/span&gt; 4 &lt;span class="nt"&gt;--disk&lt;/span&gt; 40 &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu-24.04

&lt;span class="c"&gt;# credentials injected at runtime as short-lived env vars,&lt;/span&gt;
&lt;span class="c"&gt;# never baked into the image&lt;/span&gt;
krova ssh &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUBE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# session over? nothing to clean up&lt;/span&gt;
krova cubes delete &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUBE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when I automate it from CI instead of my laptop, it's the v1 API — idempotency key included so retries don't double-provision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://krova.cloud/api/v1/spaces/&lt;span class="nv"&gt;$SPACE&lt;/span&gt;/cubes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-KEY: &lt;/span&gt;&lt;span class="nv"&gt;$KROVA_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Idempotency-Key: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;uuidgen&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "agent-session-42",
    "image": "ubuntu-24.04",
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 40 }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A session that lives 20 minutes on a 2 vCPU / 4 GB Cube costs a few cents, minute-billed. Cheaper than the coffee I drink while it runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The parts I still don't trust (read this)&lt;/strong&gt;&lt;br&gt;
Isolation is not the same as safety. Let me be blunt, because this is where people get hurt:&lt;/p&gt;

&lt;p&gt;A microVM stops the agent from escaping to your other workloads. It does not stop it from wrecking its own box.&lt;br&gt;
It does not stop it from using credentials you handed it. AdministratorAccess AWS keys + a bulletproof sandbox = a very secure machine making a very expensive mistake.&lt;br&gt;
So the boring controls still apply, on top of the VM:&lt;/p&gt;

&lt;p&gt;Scoped, short-lived tokens — injected at runtime, never in the image&lt;br&gt;
No shared volumes with anything you care about&lt;br&gt;
Egress restricted where it matters (the agent doesn't need your whole network)&lt;br&gt;
The VM is the blast radius. Credential scoping is the actual control. Krova gives you the boundary — the hygiene inside it is still your job, same as any self-hosted box.&lt;/p&gt;

&lt;p&gt;Anyone telling you "just sandbox it and you're done" is selling something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway&lt;/strong&gt;&lt;br&gt;
I used to think agent safety was a model problem. A big chunk of it is an infrastructure problem you can solve today with 2018-era technology:&lt;/p&gt;

&lt;p&gt;Give it a real boundary (own kernel, not namespaces)&lt;br&gt;
Give it no address (no public IP)&lt;br&gt;
Throw it away when you're done&lt;br&gt;
That's the whole trick.&lt;/p&gt;

&lt;p&gt;How are you sandboxing agents right now — containers, microVMs, or "vibes and hope"? And has anyone actually measured escape risk on their current setup? Would love to compare notes in the comments.&lt;/p&gt;

</description>
      <category>microvm</category>
      <category>devops</category>
      <category>cloudsecurity</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Stopped Sharing Servers With Strangers</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Fri, 21 Aug 2026 16:32:27 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/i-stopped-sharing-servers-with-strangers-3dcf</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/i-stopped-sharing-servers-with-strangers-3dcf</guid>
      <description>&lt;p&gt;I used to not think about who else was running on my host.&lt;/p&gt;

&lt;p&gt;Then one day it hit me: my VPS, my containers, my database — all of it was sharing a Linux kernel with workloads from people I'd never met. Their bugs, their breaches, their noisy neighbors were all one kernel vulnerability away from being my problem.&lt;/p&gt;

&lt;p&gt;It's not paranoia. It's just architecture.&lt;/p&gt;

&lt;p&gt;The shared kernel reality&lt;br&gt;
Most cloud hosting looks like this under the hood:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

┌─────────────────────────────┐
│        Host Kernel          │  ← shared by everyone
├─────────┬─────────┬─────────┤
│ Tenant  │ Tenant  │   You   │
│    A    │    B    │         │
└─────────┴─────────┴─────────┘


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Containers give you process isolation. They don't give you kernel isolation. Dirty Pipe, runc escapes, privilege escalation chains — they all exploit the same truth: break the kernel, and the walls between tenants get flexible.&lt;/p&gt;

&lt;p&gt;Most of the time, it's fine. Cloud providers are good at what they do. But "mostly fine" isn't the same as "isolated."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I switched to&lt;/strong&gt;&lt;br&gt;
I started using Krova Cloud, which gives every workload its own Firecracker microVM called a Cube.&lt;/p&gt;

&lt;p&gt;Each Cube boots its own kernel. Its own userspace. Its own private network. No public IP by default.&lt;/p&gt;

&lt;p&gt;Spin one up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Bash

npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @krovacloud/cli

krova cubes create myapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cpu&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ram&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disk&lt;/span&gt; 40 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu-24.04

krova ssh myapp
root@myapp:~#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No shared kernel. No security groups. No public IP.&lt;/p&gt;

&lt;p&gt;If you prefer the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Bash

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://krova.cloud/api/v1/spaces/&lt;span class="nv"&gt;$SPACE&lt;/span&gt;/cubes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-KEY: &lt;/span&gt;&lt;span class="nv"&gt;$KROVA_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Idempotency-Key: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;uuidgen&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "myapp",
    "image": "ubuntu-24.04",
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 40 },
    "sshPublicKey": "ssh-ed25519 AAAA...",
    "region": "eu-central"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What changed&lt;/strong&gt;&lt;br&gt;
The differences are subtle but real:&lt;/p&gt;

&lt;p&gt;No more shared-kernel CVEs keeping me up at night&lt;br&gt;
No more wondering if a noisy neighbor is causing latency spikes&lt;br&gt;
No public IP for bots to scan and brute-force&lt;br&gt;
My workload, my kernel, my rules&lt;br&gt;
I also stopped thinking about firewall rules as the main line of defense. When there's no public IP, the attack surface drops dramatically.&lt;/p&gt;

&lt;p&gt;For admin access, I open a port mapping locked to my IP:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;krova ports add myapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 22 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allowed-ips&lt;/span&gt; 203.0.113.10/32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything else stays unreachable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I run on Cubes now&lt;/strong&gt;&lt;br&gt;
Side project APIs&lt;br&gt;
A Postgres database&lt;br&gt;
CI runners&lt;br&gt;
Anything that processes user-submitted files&lt;br&gt;
Experiments I don't fully trust yet&lt;br&gt;
For each of these, I ask one question: does this need to share a kernel with anyone? If no, a Cube feels right.&lt;/p&gt;

&lt;p&gt;For trusted internal microservices, I still use containers. The density and speed are worth the trade. But for anything where isolation matters, I reach for a microVM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost reality&lt;/strong&gt;&lt;br&gt;
A 2 vCPU / 4 GB RAM / 40 GB disk Cube on Krova runs about $10/month. Comparable to — sometimes cheaper than — a VPS with a public IP.&lt;/p&gt;

&lt;p&gt;The hardware isn't the expensive part. The peace of mind is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The honest catch&lt;/strong&gt;&lt;br&gt;
Krova doesn't replace AWS, GCP, or Azure for complex multi-service platforms. It doesn't have a hundred managed services. It doesn't pretend to.&lt;/p&gt;

&lt;p&gt;What it gives you is a clean, isolated place to run a server. For some workloads, that's exactly enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
If you want to see what no-public-IP isolation feels like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Bash

npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @krovacloud/cli
krova signup
krova cubes create &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--cpu&lt;/span&gt; 1 &lt;span class="nt"&gt;--ram&lt;/span&gt; 2 &lt;span class="nt"&gt;--disk&lt;/span&gt; 20 &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu-24.04
krova ssh &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Bash

ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing public. No shared kernel. Just your own small server in the cloud.&lt;/p&gt;

&lt;p&gt;Do you think about who else is running on your host? Or is it one of those things you stopped worrying about? Let me know.&lt;/p&gt;

</description>
      <category>cloudsecurity</category>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>microvm</category>
    </item>
    <item>
      <title>Why I Run My Postgres on a microVM Now</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Wed, 19 Aug 2026 05:21:55 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-run-my-postgres-on-a-microvm-now-19f4</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-run-my-postgres-on-a-microvm-now-19f4</guid>
      <description>&lt;p&gt;&lt;strong&gt;A quick note on scope:&lt;/strong&gt; This post walks through a simple self-hosted Postgres setup on a &lt;a href="https://krova.cloud" rel="noopener noreferrer"&gt;Krova Cloud&lt;/a&gt; Cube — perfect for side projects and small workloads. If you're running production with strict RPO/RTO requirements, skip to the production section. Backups are not optional.&lt;/p&gt;

&lt;p&gt;I used to be the person who told everyone to use a managed database.&lt;/p&gt;

&lt;p&gt;"Don't self-host Postgres," I'd say. "You're not a DBA. Let AWS handle backups and replication."&lt;/p&gt;

&lt;p&gt;Then my managed bill started climbing. And I realized I wasn't using 90% of the features I was paying for. And I started wondering if there was a middle ground between "managed service" and "container on a shared host."&lt;/p&gt;

&lt;p&gt;There is. It's called a microVM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem with how we run databases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Databases hold the data you actually care about. Yet we routinely:&lt;/p&gt;

&lt;p&gt;Run them on the same server as the app&lt;br&gt;
Leave them in containers on shared kernels&lt;br&gt;
Expose port 5432 to the internet because it's "convenient"&lt;br&gt;
Pay managed service prices for single-node setups that don't need half the features&lt;br&gt;
I've done all of these. Most of us have.&lt;/p&gt;

&lt;p&gt;A database doesn't need to be reachable from the internet. It doesn't need to share a kernel with strangers. It needs isolation, stable resources, and a sane backup strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's a microVM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A microVM is a tiny virtual machine. It boots its own kernel. It has its own userspace. It's isolated by hardware virtualization, like any real VM.&lt;/p&gt;

&lt;p&gt;The difference is speed. Firecracker — the open-source microVM tech from AWS — can boot a VM in under a second. Fast enough that microVMs feel as lightweight as containers, but with real isolation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;container:  shared kernel, fast, soft boundary&lt;br&gt;
microVM:    own kernel, fast, real VM boundary&lt;br&gt;
managed DB: someone else's problem, expensive, shared infrastructure&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Krova Cloud Cubes&lt;/strong&gt;&lt;br&gt;
Krova Cloud gives you Firecracker microVMs called Cubes. Each one has its own kernel and no public IP by default.&lt;/p&gt;

&lt;p&gt;Creating a database Cube:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @krovacloud/cli

krova cubes create db-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cpu&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ram&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disk&lt;/span&gt; 80 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu-24.04

krova ssh db-1
root@db-1:~#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No VPC. No security groups. No public IP.&lt;/p&gt;

&lt;p&gt;If you prefer the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://krova.cloud/api/v1/spaces/&lt;span class="nv"&gt;$SPACE&lt;/span&gt;/cubes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-KEY: &lt;/span&gt;&lt;span class="nv"&gt;$KROVA_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Idempotency-Key: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;uuidgen&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "db-1",
    "image": "ubuntu-24.04",
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 80 },
    "sshPublicKey": "ssh-ed25519 AAAA...",
    "region": "eu-central"
  }'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Installing Postgres&lt;/strong&gt;&lt;br&gt;
Once you're SSH'd in, it's just a normal Ubuntu server:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; postgresql postgresql-contrib
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;postgresql
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the user and database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"CREATE USER app WITH PASSWORD 'your-strong-password';"&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"CREATE DATABASE app_db OWNER app;"&lt;/span&gt;
Edit /etc/postgresql/16/main/postgresql.conf to listen on the private
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;interface:&lt;/p&gt;

&lt;p&gt;conf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;listen_addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'localhost,10.0.0.4'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And /etc/postgresql/16/main/pg_hba.conf to allow the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;host&lt;/span&gt;    &lt;span class="err"&gt;app_db&lt;/span&gt;    &lt;span class="err"&gt;app&lt;/span&gt;    &lt;span class="err"&gt;10.0.0.0/24&lt;/span&gt;    &lt;span class="err"&gt;scram-sha-256&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Postgres:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. Your database is running on a real VM with its own kernel, on a private network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connecting from your app&lt;/strong&gt;&lt;br&gt;
Your app runs in another Cube. You connect using the database Cube's private IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL = "postgresql://app:your-strong-password@10.0.0.4:5432/app_db"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No public IP. No exposed port. The database only talks to your app.&lt;/p&gt;

&lt;p&gt;For admin access, open an IP-allowlisted SSH mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;krova ports add db-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 22 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allowed-ips&lt;/span&gt; 203.0.113.10/32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backups&lt;/strong&gt;&lt;br&gt;
This is where self-hosting gets serious. A managed service gives you backups. A microVM gives you the tools to build your own.&lt;/p&gt;

&lt;p&gt;For a small project, a daily &lt;code&gt;pg_dump&lt;/code&gt; to encrypted object storage is a starting point:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; postgres app_db | &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"/backup/app_db-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y%m%d&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.sql.gz"&lt;/span&gt;
&lt;span class="c"&gt;# encrypt and upload to your preferred storage&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost comparison&lt;br&gt;
For 2 vCPU, 4 GB RAM, 80 GB disk:&lt;/p&gt;

&lt;p&gt;Managed Postgres-&amp;gt;&lt;br&gt;
Approximate monthly cost:$50–200+&lt;br&gt;
Notes:Backups, replication, monitoring included&lt;/p&gt;

&lt;p&gt;VPS with public IP-&amp;gt;&lt;br&gt;
Approximate monthly cost:$20–50&lt;br&gt;
Notes:Shared kernel, public attack surface&lt;/p&gt;

&lt;p&gt;Krova Cloud Cube-&amp;gt;&lt;br&gt;
Approximate monthly cost:~$10&lt;br&gt;
Notes:Own kernel, no public IP, per-minute billing&lt;/p&gt;

&lt;p&gt;markdown&lt;br&gt;
Prices vary, but the gap is real. Just remember: the Cube is the cheap part. The operational work — backups, patching, monitoring, recovery — is the real cost of self-hosting, regardless of platform.&lt;/p&gt;

&lt;p&gt;For a side project or small SaaS, the savings add up. For mission-critical workloads, budget for the operational layer too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side project vs. production&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simple setup in this post is perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Side projects&lt;/li&gt;
&lt;li&gt;Small SaaS apps&lt;/li&gt;
&lt;li&gt;Learning and experimentation&lt;/li&gt;
&lt;li&gt;Workloads where you want full control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production, you don't need to leave Krova — you need to add operations on top of it. WAL archiving, PITR, automated failover, and mature monitoring can all run on Cubes. Krova handles the isolation and networking. You handle the database operations.&lt;/p&gt;

&lt;p&gt;If your team doesn't have the bandwidth for that operational work, a managed service is the right call. That's a staffing decision, not a platform limitation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real reason I switched&lt;/strong&gt;&lt;br&gt;
It wasn't just cost. It was isolation.&lt;/p&gt;

&lt;p&gt;I don't want my database sharing a kernel with random workloads. I don't want port 5432 discoverable on the internet. I don't want to rely on a firewall rule I might misconfigure at 2 AM.&lt;/p&gt;

&lt;p&gt;A microVM gives me a real boundary. Krova Cloud makes it easy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
If you want to experiment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @krovacloud/cli
krova signup
krova cubes create db-test &lt;span class="nt"&gt;--cpu&lt;/span&gt; 1 &lt;span class="nt"&gt;--ram&lt;/span&gt; 2 &lt;span class="nt"&gt;--disk&lt;/span&gt; 20 &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu-24.04
krova ssh db-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Postgres, create a database, and notice that nothing is publicly reachable.&lt;/p&gt;

&lt;p&gt;Do you self-host Postgres? Use a managed service? I'd love to hear where you draw the line — and why.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>devops</category>
      <category>microvm</category>
    </item>
    <item>
      <title>Stop Hardening Your Server. Start Hiding It.</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Wed, 12 Aug 2026 12:39:49 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/stop-hardening-your-server-start-hiding-it-442o</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/stop-hardening-your-server-start-hiding-it-442o</guid>
      <description>&lt;p&gt;I used to be proud of my server hardening skills.&lt;/p&gt;

&lt;p&gt;SSH keys, fail2ban, UFW, SELinux, read-only root, the whole thing. I could lock down a VPS in twenty minutes and sleep soundly.&lt;/p&gt;

&lt;p&gt;Then I checked the auth logs on a fresh server and saw thousands of brute-force attempts in 24 hours. The server had been online for maybe six hours.&lt;/p&gt;

&lt;p&gt;I wasn't being targeted. I was just visible.&lt;/p&gt;

&lt;p&gt;That's when I started wondering: what if the best security isn't better hardening — it's not being findable in the first place?&lt;/p&gt;

&lt;p&gt;The public IP problem&lt;br&gt;
Every VPS gives you a public IPv4 address by default. It's convenient. It's also an invitation.&lt;/p&gt;

&lt;p&gt;Bots scan the entire internet constantly. If you have SSH on port 22 and a public IP, you're getting hit. It's not personal. It's automatic.&lt;/p&gt;

&lt;p&gt;I had done everything "right":&lt;/p&gt;

&lt;p&gt;Key-based SSH only&lt;br&gt;
fail2ban&lt;br&gt;
UFW with minimal ports&lt;br&gt;
Automatic updates&lt;br&gt;
Non-root user&lt;br&gt;
But the attempts never stopped. Because my server had an address.&lt;/p&gt;

&lt;p&gt;My app didn't need one. My users hit a domain. My database shouldn't be reachable from outside. Admin access was just for me. The public IP was solving almost nothing while creating a permanent target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hiding the server instead&lt;/strong&gt;&lt;br&gt;
I moved the project to Krova Cloud, which gives you Firecracker microVMs called Cubes. The default: no public IP.&lt;/p&gt;

&lt;p&gt;Your Cube sits on a private network. Web traffic comes through managed ingress with automatic HTTPS. SSH is only available through an explicit port mapping locked to your IP.&lt;/p&gt;

&lt;p&gt;Creating one:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;`npm i -g &lt;a class="mentioned-user" href="https://dev.to/krovacloud"&gt;@krovacloud&lt;/a&gt;/cli&lt;/p&gt;

&lt;p&gt;krova cubes create myapp \&lt;br&gt;
  --cpu 2 \&lt;br&gt;
  --ram 4 \&lt;br&gt;
  --disk 40 \&lt;br&gt;
  --image ubuntu-24.04&lt;/p&gt;

&lt;p&gt;krova ssh myapp&lt;br&gt;
root@myapp:~#`&lt;/p&gt;

&lt;p&gt;No VPC. No security groups. No public IP.&lt;/p&gt;

&lt;p&gt;If you prefer the API:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;curl -X POST &lt;a href="https://krova.cloud/api/v1/spaces/$SPACE/cubes" rel="noopener noreferrer"&gt;https://krova.cloud/api/v1/spaces/$SPACE/cubes&lt;/a&gt; \&lt;br&gt;
  -H "X-API-KEY: $KROVA_KEY" \&lt;br&gt;
  -H "Idempotency-Key: $(uuidgen)" \&lt;br&gt;
  -d '{&lt;br&gt;
    "name": "myapp",&lt;br&gt;
    "image": "ubuntu-24.04",&lt;br&gt;
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 40 },&lt;br&gt;
    "sshPublicKey": "ssh-ed25519 AAAA...",&lt;br&gt;
    "region": "eu-central"&lt;br&gt;
  }'&lt;br&gt;
&lt;strong&gt;What changed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After 48 hours, I checked the auth logs.&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;`# Before (public VPS)&lt;br&gt;
Failed password for root from 185.x.x.x&lt;br&gt;
Failed password for root from 103.x.x.x&lt;br&gt;
Failed password for root from 45.x.x.x&lt;br&gt;
...thousands more&lt;/p&gt;

&lt;h1&gt;
  
  
  After (Krova Cube)
&lt;/h1&gt;

&lt;h1&gt;
  
  
  nothing`
&lt;/h1&gt;

&lt;p&gt;No brute-forces. No port scans. No 2 AM anxiety about whether I left something exposed.&lt;/p&gt;

&lt;p&gt;The server still works. Users still reach the API through the domain. HTTPS still terminates at Krova's ingress. But the machine itself doesn't exist on the public internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Admin access without a public IP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need SSH, you open a port mapping and lock it to your IP:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;krova ports add myapp \&lt;br&gt;
  --protocol tcp \&lt;br&gt;
  --port 22 \&lt;br&gt;
  --allowed-ips 203.0.113.10/32&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Only your IP can reach it. Everyone else sees nothing.&lt;/p&gt;

&lt;p&gt;For web traffic, point your domain at Krova's ingress. They handle TLS and hide the origin. Your app doesn't need to know it's not directly exposed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus: real isolation&lt;/strong&gt;&lt;br&gt;
Krova Cubes are Firecracker microVMs, so each one boots its own kernel. Not shared with other tenants. Not shared with the host.&lt;/p&gt;

&lt;p&gt;For a small side project, that's probably more isolation than necessary. But after reading one too many container escape write-ups, I prefer a real VM boundary for anything I care about.&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VPS:     public IP + shared kernel&lt;br&gt;
Container: maybe public IP + definitely shared kernel&lt;br&gt;
Cube:    no public IP + own kernel&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway&lt;/strong&gt;&lt;br&gt;
Hardening is good. Hiding is better.&lt;/p&gt;

&lt;p&gt;A server without a public address can't be brute-forced. Can't be port-scanned. Can't be accidentally exposed by a bad firewall rule.&lt;/p&gt;

&lt;p&gt;We've accepted public IPs as the default because they're familiar. But most apps don't need their machine to be reachable from the whole internet. They need a domain, TLS, and a way for the owner to admin things.&lt;/p&gt;

&lt;p&gt;Everything else is attack surface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
If you're curious, Krova signup doesn't require a card and the first $5 top-up doubles to $10:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -g @krovacloud/cli&lt;br&gt;
krova signup&lt;br&gt;
krova cubes create test --cpu 1 --ram 2 --disk 20 --image ubuntu-24.04&lt;br&gt;
krova ssh test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inside the Cube, run:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ss -tlnp&lt;/code&gt;&lt;br&gt;
Nothing public. That's the whole point.&lt;/p&gt;

&lt;p&gt;Am I wrong about public IPs? Is hardening still the better default? Tell me why , I genuinely want to hear the counterarguments.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your Side Project Doesn't Need a Public IP. Here's the Proof.</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Mon, 10 Aug 2026 11:08:53 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/your-side-project-doesnt-need-a-public-ip-heres-the-proof-2mem</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/your-side-project-doesnt-need-a-public-ip-heres-the-proof-2mem</guid>
      <description>&lt;p&gt;I used to think every server needed a public IP. It's just... how servers work, right?&lt;/p&gt;

&lt;p&gt;Then I moved my side project , a small Node.js API with a Postgres database , to Krova Cloud. Cubes don't get public IPs by default. Within a day, I realized I'd been accepting a bunch of nonsense I didn't have to.&lt;/p&gt;

&lt;p&gt;No more SSH brute-forces. No open ports accidentally exposed. No anxiety about whether my firewall rules were perfect.&lt;/p&gt;

&lt;p&gt;Here's what happened.&lt;/p&gt;

&lt;p&gt;The problem with public IPs&lt;br&gt;
I ran my project on a cheap VPS for two years. It worked. But one bored afternoon I checked the auth logs:&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Failed password for root from 185.x.x.x&lt;br&gt;
Failed password for root from 103.x.x.x&lt;br&gt;
Failed password for root from 45.x.x.x&lt;/code&gt;&lt;br&gt;
Thousands of attempts per day. From everywhere.&lt;/p&gt;

&lt;p&gt;I had key-based SSH. I had fail2ban. I had UFW. But the attempts never stopped because my server's address was public. That's the whole job of a public IP — be findable.&lt;/p&gt;

&lt;p&gt;The thing is, my app didn't need to be findable. My domain was. My users hit the API through the domain. The server itself just needed to exist.&lt;/p&gt;

&lt;p&gt;Krova Cloud: a server without a public address&lt;br&gt;
Krova Cloud gives you Firecracker microVMs called Cubes. Each Cube has:&lt;/p&gt;

&lt;p&gt;Its own kernel&lt;br&gt;
No public IP&lt;br&gt;
A private network&lt;br&gt;
Managed ingress for web traffic&lt;br&gt;
IP-allowlisted port mappings for admin access&lt;br&gt;
Creating one looks like this:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;`npm i -g &lt;a class="mentioned-user" href="https://dev.to/krovacloud"&gt;@krovacloud&lt;/a&gt;/cli&lt;/p&gt;

&lt;p&gt;krova cubes create fileapi \&lt;br&gt;
  --cpu 2 \&lt;br&gt;
  --ram 4 \&lt;br&gt;
  --disk 40 \&lt;br&gt;
  --image ubuntu-24.04&lt;/p&gt;

&lt;p&gt;krova ssh fileapi&lt;br&gt;
root@fileapi:~#`&lt;br&gt;
That's the whole setup. No VPC. No security groups. No public IP.&lt;/p&gt;

&lt;p&gt;If you prefer APIs:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -X POST https://krova.cloud/api/v1/spaces/$SPACE/cubes \&lt;br&gt;
  -H "X-API-KEY: $KROVA_KEY" \&lt;br&gt;
  -H "Idempotency-Key: $(uuidgen)" \&lt;br&gt;
  -d '{&lt;br&gt;
    "name": "fileapi",&lt;br&gt;
    "image": "ubuntu-24.04",&lt;br&gt;
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 40 },&lt;br&gt;
    "sshPublicKey": "ssh-ed25519 AAAA...",&lt;br&gt;
    "region": "eu-central"&lt;br&gt;
  }'&lt;/code&gt;&lt;br&gt;
Migrating the app&lt;br&gt;
My stack was simple:&lt;/p&gt;

&lt;p&gt;Node.js API running on port 3000&lt;br&gt;
Postgres on the same machine&lt;br&gt;
Nginx as a reverse proxy with HTTPS&lt;br&gt;
On Krova, I kept the same setup but pointed my domain at Krova's managed ingress instead of a public IP. HTTPS was handled automatically. The origin stayed hidden.&lt;/p&gt;

&lt;p&gt;For SSH, I opened a port mapping locked to my home IP:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;krova ports add fileapi \&lt;br&gt;
  --protocol tcp \&lt;br&gt;
  --port 22 \&lt;br&gt;
  --allowed-ips 203.0.113.10/32&lt;/code&gt;&lt;br&gt;
Only I can reach SSH. Everyone else sees the domain and the API. The server itself is invisible.&lt;/p&gt;

&lt;p&gt;The result&lt;br&gt;
After 48 hours, I checked the auth logs.&lt;/p&gt;

&lt;p&gt;Zero SSH attempts.&lt;/p&gt;

&lt;p&gt;Not "reduced." Not "better." Zero. Because there's no address to attack.&lt;/p&gt;

&lt;p&gt;My API response times were the same. My users didn't notice anything. My deploy process barely changed. But the background noise of the internet trying to break in just... stopped.&lt;/p&gt;

&lt;p&gt;What about isolation?&lt;br&gt;
I mentioned Cubes are Firecracker microVMs. That means each one boots its own kernel.&lt;/p&gt;

&lt;p&gt;For a tiny side project, that's probably overkill. But honestly? I like overkill when it comes to isolation. I've read enough container escape write-ups to prefer a real VM boundary for anything I care about.&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VPS:        public IP + shared kernel with other tenants&lt;br&gt;
Container:  maybe public IP + definitely shared kernel&lt;br&gt;
Krova Cube: no public IP + own kernel&lt;/code&gt;&lt;br&gt;
For me, that's an easy trade.&lt;/p&gt;

&lt;p&gt;Is this for every project?&lt;br&gt;
No.&lt;/p&gt;

&lt;p&gt;If you're building a complex multi-region microservices platform, use AWS or GCP. Krova is simpler, which means it does less.&lt;/p&gt;

&lt;p&gt;But for side projects, small SaaS apps, CI runners, databases, or anything where "give me an isolated server" is enough, this is the cleanest setup I've found.&lt;/p&gt;

&lt;p&gt;Try it yourself&lt;br&gt;
If you're curious, signup doesn't need a card and the first $5 top-up doubles to $10:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -g @krovacloud/cli&lt;br&gt;
krova signup&lt;br&gt;
krova cubes create test --cpu 1 --ram 2 --disk 20 --image ubuntu-24.04&lt;br&gt;
krova ssh test&lt;/code&gt;&lt;br&gt;
Once inside, run:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ss -tlnp&lt;/code&gt;&lt;br&gt;
Nothing is listening publicly. That's the whole point.&lt;/p&gt;

&lt;p&gt;The lesson&lt;br&gt;
We accept public IPs as the default because they're familiar. But most apps don't need their server to be addressable from the entire internet. They need a domain, TLS, and a way for the owner to admin things.&lt;/p&gt;

&lt;p&gt;Deleting the public IP didn't just reduce my attack surface. It removed the background anxiety that came with it.&lt;/p&gt;

&lt;p&gt;Have you run anything without a public IP? Did it feel wrong at first, or immediately better? Drop a comment — I'd love to hear.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>sideprojects</category>
      <category>microvm</category>
    </item>
    <item>
      <title>Cloud Infrastructure Security in 2025: Why I Started Treating Every App Like a Fortress</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Sat, 11 Jul 2026 10:51:57 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/cloud-infrastructure-security-in-2025-why-i-started-treating-every-app-like-a-fortress-5dgb</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/cloud-infrastructure-security-in-2025-why-i-started-treating-every-app-like-a-fortress-5dgb</guid>
      <description>&lt;p&gt;A practical look at container escape risks, public-IP scanning, and how Firecracker microVMs on &lt;strong&gt;Krova Cloud&lt;/strong&gt; changed how I think about cloud infrastructure security.&lt;/p&gt;

&lt;p&gt;The moment I stopped trusting my own stack&lt;br&gt;
A few months ago, I got that Slack message nobody wants:&lt;/p&gt;

&lt;p&gt;"One of our containers is acting weird. High CPU. Unknown process. Can you check?"&lt;/p&gt;

&lt;p&gt;It turned out to be a cryptominer. Not because someone hacked our app. Not because we leaked secrets. But because another tenant on the same host had a vulnerable container, and the attacker escaped into the shared kernel.&lt;/p&gt;

&lt;p&gt;We didn't do anything wrong. We followed the playbook: updated images, minimal privileges, read-only root filesystems. But we were still sitting on the same kernel as everyone else.&lt;/p&gt;

&lt;p&gt;That incident made me ask a question I'd never seriously considered:&lt;/p&gt;

&lt;p&gt;What if the real cloud security problem isn't our configuration - it's the architecture underneath?&lt;/p&gt;

&lt;p&gt;This post is the answer I found. It's about why I started thinking of every app as its own fortress, and how platforms like Krova Cloud make that practical.&lt;/p&gt;

&lt;p&gt;The two lies we tell ourselves about cloud security&lt;br&gt;
Lie #1: "Containers are isolated enough"&lt;br&gt;
Containers isolate processes. They don't isolate kernels.&lt;/p&gt;

&lt;p&gt;Every container on a host shares the same Linux kernel. That's by design — it's why containers are fast and lightweight. But it also means a single kernel vulnerability can compromise every container on that machine.&lt;/p&gt;

&lt;p&gt;Recent CVEs like Dirty Pipe, CVE-2022-0847, and privilege-escalation chains have shown this repeatedly. You don't need a zero-day. You need one kernel bug and one noisy neighbor.&lt;/p&gt;

&lt;p&gt;┌─────────────────────────────────────┐&lt;br&gt;
│           Host Kernel               │  ← one shared kernel&lt;br&gt;
├─────────────┬─────────────┬─────────┤&lt;br&gt;
│ Container 1 │ Container 2 │   Your  │&lt;br&gt;
│   (tenant)  │   (tenant)  │   app   │&lt;br&gt;
└─────────────┴─────────────┴─────────┘&lt;br&gt;
If an attacker breaks out of any container, they can potentially touch yours.&lt;/p&gt;

&lt;p&gt;Lie #2: "A public IP is just how servers work"&lt;br&gt;
The second lie is that every server needs a public IP address.&lt;/p&gt;

&lt;p&gt;It doesn't. But VPS providers hand them out by default because it's convenient. The problem? That IP is now on the internet 24/7, being scanned, brute-forced, and probed by bots.&lt;/p&gt;

&lt;p&gt;Within minutes of launching a typical VPS, you'll see:&lt;/p&gt;

&lt;p&gt;SSH brute-force attempts&lt;br&gt;
Port scans on every service&lt;br&gt;
Automated exploit attempts&lt;br&gt;
Your security model becomes: "I have a public address, and I hope my firewall rules are perfect."&lt;/p&gt;

&lt;p&gt;Spoiler: they usually aren't.&lt;/p&gt;

&lt;p&gt;What if isolation meant a real kernel?&lt;br&gt;
This is where microVMs come in.&lt;/p&gt;

&lt;p&gt;A microVM is a lightweight virtual machine. Unlike a container, each microVM boots its own kernel. Unlike a traditional VM, it starts in milliseconds - fast enough to spin up and tear down like a container.&lt;/p&gt;

&lt;p&gt;The technology behind this is Firecracker, the same isolation engine AWS uses for Lambda and Fargate. It's designed for:&lt;/p&gt;

&lt;p&gt;Strong isolation (full VM boundary)&lt;br&gt;
Fast startup (sub-second boot)&lt;br&gt;
Low overhead (minimal resource usage)&lt;br&gt;
High density (many VMs on one host)&lt;/p&gt;

&lt;p&gt;┌─────────────────────────────────────────────┐&lt;br&gt;
│              Host Hardware                  │&lt;br&gt;
├─────────────────┬───────────────────────────┤&lt;br&gt;
│   VM 1          │   VM 2        │   Your   │&lt;br&gt;
│  own kernel     │  own kernel   │   app    │&lt;br&gt;
└─────────────────┴───────────────┴──────────┘&lt;br&gt;
Each VM has its own kernel. A kernel bug in one can't reach another.&lt;/p&gt;

&lt;p&gt;How Krova Cloud turns microVMs into a security model&lt;br&gt;
That's the theory. Krova Cloud is the practice.&lt;/p&gt;

&lt;p&gt;Krova Cloud calls its microVMs Cubes. Each Cube is a Firecracker microVM with a few security-first design choices that directly solve the problems I mentioned:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcsavu8pqurjl05i2igfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcsavu8pqurjl05i2igfm.png" alt=" " width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the part that matters most? It's not just secure , it's usable.&lt;/p&gt;

&lt;p&gt;Spinning up a Cube: from zero to root in seconds&lt;br&gt;
Here's what provisioning looks like with the Krova CLI:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;`# Install the CLI&lt;br&gt;
npm i -g &lt;a class="mentioned-user" href="https://dev.to/krovacloud"&gt;@krovacloud&lt;/a&gt;/cli&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a Cube
&lt;/h1&gt;

&lt;p&gt;krova cubes create web-1 \&lt;br&gt;
  --cpu 2 \&lt;br&gt;
  --ram 4 \&lt;br&gt;
  --disk 40 \&lt;br&gt;
  --image ubuntu-24.04&lt;/p&gt;

&lt;h1&gt;
  
  
  SSH in with full root access
&lt;/h1&gt;

&lt;p&gt;krova ssh web-1&lt;br&gt;
root@web-1:~#`&lt;br&gt;
No VPCs. No security groups. No IAM roles. No launch templates. Just a real VM, isolated by hardware virtualization, booted in under a second.&lt;/p&gt;

&lt;p&gt;If you prefer code, the REST API is just as simple:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -X POST https://krova.cloud/api/v1/spaces/$SPACE/cubes \&lt;br&gt;
  -H "X-API-KEY: $KROVA_KEY" \&lt;br&gt;
  -H "Idempotency-Key: $(uuidgen)" \&lt;br&gt;
  -d '{&lt;br&gt;
    "name": "web-1",&lt;br&gt;
    "image": "ubuntu-24.04",&lt;br&gt;
    "resources": { "vcpu": 2, "ramGb": 4, "diskGb": 40 },&lt;br&gt;
    "sshPublicKey": "ssh-ed25519 AAAA...",&lt;br&gt;
    "region": "eu-central"&lt;br&gt;
  }'&lt;/code&gt;&lt;br&gt;
Same result: one isolated Cube, own kernel, no public IP.&lt;/p&gt;

&lt;p&gt;What "no public IP" actually means for security&lt;br&gt;
This is the part that took me a while to fully appreciate.&lt;/p&gt;

&lt;p&gt;When a Cube has no public IP, it literally doesn't exist on the public internet. There's no address to scan. No port to probe. No brute-force target.&lt;/p&gt;

&lt;p&gt;Inbound traffic only reaches your Cube through Krova Cloud's managed ingress layer:&lt;/p&gt;

&lt;p&gt;Web traffic enters through a TLS-terminated edge&lt;br&gt;
Your custom domain points to that edge, not to your Cube&lt;br&gt;
The Cube origin stays hidden&lt;br&gt;
Non-web services use explicit port mappings with IP allowlists&lt;br&gt;
text&lt;/p&gt;

&lt;p&gt;Internet  →  Krova Ingress (TLS, DDoS-mitigated)&lt;br&gt;
                  ↓&lt;br&gt;
            Hidden origin&lt;br&gt;
                  ↓&lt;br&gt;
            Your Cube (private IP)&lt;br&gt;
Compare that to a standard VPS:&lt;/p&gt;

&lt;p&gt;text&lt;/p&gt;

&lt;p&gt;Internet  →  Your public IP&lt;br&gt;
                  ↓&lt;br&gt;
            Your server (ssh, db, api all exposed)&lt;br&gt;
The difference is night and day. With no public IP, the attacker can't attack what they can't find.&lt;/p&gt;

&lt;p&gt;Mapping Krova's design to real cloud security principles&lt;br&gt;
Let's translate the Cube architecture into the security fundamentals we all know:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defense in depth
A Cube isn't just one layer of isolation. It's several:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hardware virtualization via KVM&lt;br&gt;
Separate kernel per VM&lt;br&gt;
Jailer sandbox around the hypervisor&lt;br&gt;
No public IP&lt;br&gt;
Stateful default-deny firewall&lt;br&gt;
IP-allowlisted port mappings&lt;br&gt;
Managed TLS ingress&lt;br&gt;
That's defense in depth without you configuring any of it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Least privilege
By default, nothing is reachable. You have to explicitly open a port. And when you do, you can lock it to a specific IP range.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# Example: open SSH only from your office IP&lt;br&gt;
krova ports add web-1 \&lt;br&gt;
  --protocol tcp \&lt;br&gt;
  --port 22 \&lt;br&gt;
  --allowed-ips 203.0.113.0/24&lt;/code&gt;&lt;br&gt;
This is least privilege applied to networking.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attack surface reduction
No public IP means no SSH brute-forcing. No open database ports scanned by Shodan. No accidental exposure because someone misconfigured a security group.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The attack surface is reduced by architecture, not by hoping humans never make mistakes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Isolation of failure
If one Cube is compromised, the blast radius is that Cube. Not the host. Not other tenants. Not your entire stack.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When microVMs make sense (and when they don't)&lt;br&gt;
I'm not here to say containers are dead. They're not. But I think we overuse them for workloads that need real isolation.&lt;/p&gt;

&lt;p&gt;MicroVMs are a great fit for:&lt;br&gt;
User-submitted code (judge0-style platforms, coding interviews)&lt;br&gt;
AI agents that run arbitrary shell commands&lt;br&gt;
CI/CD runners that should start clean every time&lt;br&gt;
Multi-tenant SaaS where each customer needs isolation&lt;br&gt;
Databases and stateful services that benefit from a real kernel&lt;br&gt;
Anything handling untrusted data&lt;br&gt;
Containers are still fine for:&lt;br&gt;
Internal microservices with trusted code&lt;br&gt;
Development environments&lt;br&gt;
Workloads where density and speed matter more than isolation&lt;br&gt;
Teams already heavily invested in Kubernetes&lt;br&gt;
The key is choosing the right isolation model for the risk.&lt;/p&gt;

&lt;p&gt;A cloud security checklist for 2025&lt;br&gt;
Whether you use Krova Cloud, AWS, Azure, or a mix, here's my current checklist:&lt;/p&gt;

&lt;p&gt;Markdown&lt;/p&gt;

&lt;p&gt;□ Assume shared kernels can be compromised — isolate high-risk workloads&lt;br&gt;
□ Avoid public IPs unless absolutely necessary&lt;br&gt;
□ Use IP allowlists for any administrative access&lt;br&gt;
□ Enable MFA for all cloud consoles and SSH jump hosts&lt;br&gt;
□ Rotate access keys every 90 days (or use temporary credentials)&lt;br&gt;
□ Block public access on all storage buckets by default&lt;br&gt;
□ Scan repos for leaked secrets before every merge&lt;br&gt;
□ Centralize logs and set alerts for root login, IAM changes, and public exposure&lt;br&gt;
□ Test your incident response plan before you need it&lt;br&gt;
□ Review your architecture choices as often as your code&lt;br&gt;
The last one is the hardest — and the most important.&lt;/p&gt;

&lt;p&gt;Why this changed how I build&lt;br&gt;
Before the cryptominer incident, I thought cloud security was about configuration: the right IAM policies, the right firewall rules, the right patches.&lt;/p&gt;

&lt;p&gt;I still think those matter. But I now believe the foundation matters more.&lt;/p&gt;

&lt;p&gt;If your architecture assumes a shared kernel and a public IP, you're asking your configuration to be perfect forever. That's a losing game.&lt;/p&gt;

&lt;p&gt;If your architecture gives every workload its own kernel and hides it from the public internet, you've made security the default. That's a much better place to operate from.&lt;/p&gt;

&lt;p&gt;That's why I started using Krova Cloud for workloads where isolation matters. Not because it's a magic bullet, but because it aligns the default architecture with good security hygiene.&lt;/p&gt;

&lt;p&gt;Try it yourself&lt;br&gt;
If you're curious, you can spin up a Cube for free (signup doesn't require a card, and the first $5 top-up doubles to $10):&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -g @krovacloud/cli&lt;br&gt;
krova signup&lt;br&gt;
krova cubes create security-test --cpu 1 --ram 2 --disk 20 --image ubuntu-24.04&lt;br&gt;
krova ssh security-test&lt;/code&gt;&lt;br&gt;
Once inside, run ss -tlnp and notice something beautiful: there are no public listening ports. Your server exists, but it's invisible to the internet.&lt;/p&gt;

&lt;p&gt;Final thoughts&lt;br&gt;
Cloud infrastructure security isn't just about tools and checklists. It's about architecture.&lt;/p&gt;

&lt;p&gt;Containers gave us speed. microVMs give us speed and isolation.&lt;/p&gt;

&lt;p&gt;Platforms like Krova Cloud make that isolation practical for everyday developers. And in a world where kernel bugs and automated scanning are constants, I think that's worth paying attention to.&lt;/p&gt;

&lt;p&gt;What's your take? Are you still comfortable with shared kernels for sensitive workloads? Or are you already exploring microVMs and Firecracker? Drop a comment — I'd love to hear what's working for you.&lt;/p&gt;

&lt;p&gt;Resources&lt;br&gt;
&lt;a href="//krova.cloud"&gt;Krova Cloud&lt;/a&gt;&lt;br&gt;
&lt;a href="https://krova.cloud/security" rel="noopener noreferrer"&gt;Krova Cloud Security&lt;/a&gt;&lt;br&gt;
&lt;a href="https://firecracker-microvm.github.io/" rel="noopener noreferrer"&gt;Firecracker microVMs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aws.amazon.com/blogs/aws/firecracker-lightweight-virtualization-for-serverless-computing/" rel="noopener noreferrer"&gt;AWS Lambda under the hood&lt;/a&gt;&lt;br&gt;
&lt;a href="https://csrc.nist.gov/publications/detail/sp/800-190/final" rel="noopener noreferrer"&gt;NIST SP 800-190: Application Container Security Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading. &lt;br&gt;
If you found this helpful, hit the ❤️ and follow for more cloud security and infrastructure posts.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>5 Cloud Security Mistakes That'll Get You Hacked (And How to Fix Them)</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Wed, 01 Jul 2026 09:14:17 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/5-cloud-security-mistakes-thatll-get-you-hacked-and-how-to-fix-them-402a</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/5-cloud-security-mistakes-thatll-get-you-hacked-and-how-to-fix-them-402a</guid>
      <description>&lt;p&gt;&lt;strong&gt;5 Cloud Security Mistakes That'll Get You Hacked&lt;br&gt;
A friend's startup got breached last month.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cause? Public S3 bucket with customer data.&lt;/p&gt;

&lt;p&gt;Fix time? 5 minutes.&lt;/p&gt;

&lt;p&gt;Damage? $50K + lost customer trust.&lt;/p&gt;

&lt;p&gt;Don't be that startup. Here are the 5 mistakes I see every week&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Wildcard IAM Policies ❌&lt;/strong&gt;&lt;br&gt;
JSON&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{ "Action": "*", "Resource": "*" }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix — Be specific:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "Action": ["s3:GetObject", "s3:PutObject"],&lt;br&gt;
  "Resource": "arn:aws:s3:::my-bucket/*"&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Public Storage Buckets ❌&lt;/strong&gt;&lt;br&gt;
Fix — Block public access:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws s3control put-public-access-block \&lt;br&gt;
    --account-id 123456789012 \&lt;br&gt;
    --public-access-block-configuration \&lt;br&gt;
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. No Encryption ❌&lt;br&gt;
Fix — Enable default encryption:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;hcl&lt;/p&gt;

&lt;p&gt;`resource "aws_s3_bucket_server_side_encryption_configuration" "example" {&lt;br&gt;
  bucket = aws_s3_bucket.my_bucket.id&lt;/p&gt;

&lt;p&gt;rule {&lt;br&gt;
    apply_server_side_encryption_by_default {&lt;br&gt;
      sse_algorithm = "aws:kms"&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Missing MFA ❌&lt;br&gt;
Fix — Enforce via SCP:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JSON&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "Effect": "Deny",&lt;br&gt;
  "Action": "*",&lt;br&gt;
  "Resource": "*",&lt;br&gt;
  "Condition": {&lt;br&gt;
    "BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}&lt;br&gt;
  }&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. No Monitoring ❌&lt;br&gt;
Fix — Quick security scan:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;`#!/bin/bash&lt;br&gt;
echo "🔍 Checking public S3 buckets..."&lt;br&gt;
aws s3api list-buckets --query 'Buckets[].Name' --output text | while read bucket; do&lt;br&gt;
    aws s3api get-public-access-block --bucket $bucket 2&amp;gt;/dev/null || echo "⚠️  $bucket: No public access block!"&lt;br&gt;
done&lt;/p&gt;

&lt;p&gt;echo "🔒 Checking open security groups..."&lt;br&gt;
aws ec2 describe-security-groups \&lt;br&gt;
    --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" \&lt;br&gt;
    --query 'SecurityGroups[].GroupName' --output text&lt;/p&gt;

&lt;p&gt;echo "👤 Checking MFA..."&lt;br&gt;
aws iam list-users --query 'Users[].UserName' --output text | while read user; do&lt;br&gt;
    aws iam list-mfa-devices --user-name $user --query 'MFADevices' --output text | grep -q . || echo "⚠️  $user: No MFA!"&lt;br&gt;
done`&lt;/p&gt;

&lt;p&gt;**Quick Tools&lt;br&gt;
**Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install prowler&lt;br&gt;
prowler aws --checks cis_2.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Do This NOW&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Enable S3 Block Public Access&lt;/li&gt;
&lt;li&gt; Turn on default encryption&lt;/li&gt;
&lt;li&gt; Enable MFA on root account&lt;/li&gt;
&lt;li&gt; Run Prowler scan
TL;DR: Least privilege + Encryption + MFA + Monitoring = 95% fewer breaches.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like this? ❤️ Follow for more quick DevOps tips.&lt;/p&gt;

&lt;h1&gt;
  
  
  cloudsecurity #aws #devops
&lt;/h1&gt;

</description>
      <category>cloudsecurity</category>
      <category>aws</category>
      <category>devops</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>4 AWS Infrastructure Gotchas That Will Get Your Account Hacked (And How to Fix Them in Terraform)</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:03:23 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/4-aws-infrastructure-gotchas-that-will-get-your-account-hacked-and-how-to-fix-them-in-terraform-3jm5</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/4-aws-infrastructure-gotchas-that-will-get-your-account-hacked-and-how-to-fix-them-in-terraform-3jm5</guid>
      <description>&lt;p&gt;We’ve all heard the horror stories: a developer pushes a quick Terraform module on Friday afternoon, and wakes up Monday to a $14,000 AWS bill because bots turned their staging environment into a Monero mining cluster.&lt;/p&gt;

&lt;p&gt;The terrifying part about AWS security isn't sophisticated zero-day exploits—it’s default misconfigurations.&lt;/p&gt;

&lt;p&gt;Before you run terraform apply today, audit your code against these 4 bite-sized security fixes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Kill Wildcard (*) IAM Permissions&lt;/strong&gt;&lt;br&gt;
When you hit a 403 Access Denied error, it’s tempting to test with "Action": "&lt;em&gt;", "Resource": "&lt;/em&gt;". If committed, a single app vulnerability lets attackers wipe your AWS account.&lt;/p&gt;

&lt;p&gt;The Fix: Always hardcode least-privilege API actions and scope down to exact resource ARNs:&lt;br&gt;
hcl&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Action   = ["dynamodb:GetItem", "dynamodb:Query"]&lt;br&gt;
Resource = "arn:aws:dynamodb:us-east-1:123456789012:table/prod-users"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Lock Down S3 Buckets Explicitly&lt;/strong&gt;&lt;br&gt;
Automated scanners enumerate millions of bucket names per hour. If you don't explicitly block public access, your uploads will be discovered and dumped.&lt;/p&gt;

&lt;p&gt;The Fix: Always attach an explicit public access block to every bucket:&lt;br&gt;
hcl&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resource "aws_s3_bucket_public_access_block" "lockdown" {&lt;br&gt;
  bucket                  = aws_s3_bucket.app_bucket.id&lt;br&gt;
  block_public_acls       = true&lt;br&gt;
  block_public_policy     = true&lt;br&gt;
  ignore_public_acls      = true&lt;br&gt;
  restrict_public_buckets = true&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Never Open DB Ports to 0.0.0.0/0&lt;/strong&gt;&lt;br&gt;
Opening port 5432 (PostgreSQL) or 3306 (MySQL) to 0.0.0.0/0 so you can connect your local DB GUI invites automated brute-force bots within 10 minutes.&lt;/p&gt;

&lt;p&gt;The Fix: Keep databases in private subnets. Only allow ingress from your app server's Security Group ID:&lt;br&gt;
hcl&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source_security_group_id = aws_security_group.app_server_sg.id&lt;/code&gt;&lt;br&gt;
(Need local GUI access? Use AWS SSM Port Forwarding to tunnel in without open inbound ports).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ditch Static CI/CD Access Keys&lt;/strong&gt;&lt;br&gt;
Stop generating AWS IAM Users with static .env Secret Access Keys for GitHub Actions deployments.&lt;/p&gt;

&lt;p&gt;The Fix: Switch to OpenID Connect (OIDC) federation. Let GitHub Actions assume a temporary AWS IAM Role dynamically per run, generating short-lived tokens that expire immediately after deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛡️ The 5-Second Pre-Commit Check&lt;/strong&gt;&lt;br&gt;
Catch these footguns automatically before pushing code by running an open-source scanner in your terminal:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# Instantly flags open SGs, missing crypto, and wildcards&lt;br&gt;
trivy config ./terraform-dir&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What is your favorite CLI tool for catching cloud infrastructure bugs? Drop it in the comments! 👇 (Hit 🦄 if this reminded you to check your security groups today).&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Why I Switched to Krova.cloud - Better Security, No Overselling, 40% Cheaper</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Thu, 11 Jun 2026 06:44:15 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-switched-to-krovacloud-better-security-no-overselling-40-cheaper-23fm</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-switched-to-krovacloud-better-security-no-overselling-40-cheaper-23fm</guid>
      <description>&lt;p&gt;Hey Devs 👋&lt;/p&gt;

&lt;p&gt;Tired of paying premium prices for oversold, shared-kernel cloud infrastructure? Same. Let me introduce you to Krova.cloud — here's why it caught my attention:&lt;/p&gt;

&lt;p&gt;🔐 No Shared Kernel Each VM (called a Cube) runs its own isolated kernel via Firecracker microVM technology - same tech behind AWS Lambda. No shared kernel = no cross-tenant risk. Real isolation, not container-level illusions.&lt;/p&gt;

&lt;p&gt;🌐 No Public IP Exposure Your Cube doesn't sit naked on the internet. &lt;/p&gt;

&lt;p&gt;💾 Backups Done Right&lt;/p&gt;

&lt;p&gt;✅ RAID 1 mirrored disks - drive failure won't kill your server&lt;br&gt;
✅ Snapshots built-in - not a paid add-on&lt;br&gt;
✅ Backups stored on separate redundant storage&lt;br&gt;
📊 RAM &amp;amp; Disk - Sold 1:1 Most providers thin-provision their hardware and oversell it. Krova sells every GB of RAM and disk 1:1 with actual hardware. What you pay for is genuinely yours. No noisy neighbors. No surprise slowdowns.&lt;/p&gt;

&lt;p&gt;💸 Price? 40%+ cheaper than AWS Lightsail, DigitalOcean &amp;amp; Vultr. Per-hour billing. No hidden fees. Custom-sized VMs - no forced bundles.&lt;/p&gt;

&lt;p&gt;Free $5 credits to start - no credit card needed 👉 krova.cloud 🙌&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>security</category>
      <category>linux</category>
    </item>
    <item>
      <title>Krova: a security-first “VPS” where your server has no public IP by default</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Thu, 11 Jun 2026 05:19:33 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/krova-a-security-first-vps-where-your-server-has-no-public-ip-by-default-55m1</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/krova-a-security-first-vps-where-your-server-has-no-public-ip-by-default-55m1</guid>
      <description>&lt;p&gt;Most “I got hacked” (or “why is this box getting hammered?”) stories I’ve seen start with the same default: &lt;em&gt;every server gets a public IP&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been working on &lt;strong&gt;Krova&lt;/strong&gt; — cloud compute that flips that default.&lt;/p&gt;

&lt;p&gt;The 4 ideas (quick)&lt;br&gt;
1) &lt;strong&gt;No public IP per server by default&lt;/strong&gt;&lt;br&gt;
A Krova “Cube” (server) lives on a private NAT’d network. There isn’t a public IP sitting out there waiting to get scanned.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;No shared kernel&lt;/strong&gt;&lt;br&gt;
Each Cube runs as a &lt;strong&gt;Firecracker microVM&lt;/strong&gt; with its &lt;strong&gt;own kernel&lt;/strong&gt; - not shared-kernel containers.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Snapshots + restore/rollback&lt;/strong&gt;&lt;br&gt;
Built-in snapshots so “snapshot before upgrade → rollback if needed” is a normal workflow.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;1:1 RAM + disk (no overselling)&lt;/strong&gt;&lt;br&gt;
If you provision 4GB RAM + 40GB disk, that’s &lt;strong&gt;reserved 1:1&lt;/strong&gt; on the host (no thin-provisioning surprises).&lt;/p&gt;

&lt;p&gt;What “using it” looks like&lt;br&gt;
1) Create a Cube (pick vCPU/RAM/disk) and SSH in as root.&lt;br&gt;
2) Deploy normally (systemd, Docker, packages -&lt;br&gt;
3) Expose only what you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attach &lt;code&gt;api.yourdomain.com&lt;/code&gt; → port &lt;code&gt;8080&lt;/code&gt; (HTTPS)&lt;/li&gt;
&lt;li&gt;open SSH (or Postgres) via a TCP mapping, allowlisted to your IP/VPN
4) Snapshot before risky changes. Restore if it breaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re curious, the site is here:&lt;br&gt;
&lt;code&gt;https://krova.cloud/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7dtq76xng6tz9j835qj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7dtq76xng6tz9j835qj.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d love feedback from folks who run infra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is “no public IP by default” a win, or does it break too many real-world workflows?&lt;/li&gt;
&lt;li&gt;What would you want to see from snapshots/backups before trusting a newer provider?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>vps</category>
      <category>security</category>
    </item>
    <item>
      <title>Why I built my cloud platform on micro-VMs instead of containers (a security story)</title>
      <dc:creator>Dhruv malaviya</dc:creator>
      <pubDate>Wed, 03 Jun 2026 07:55:21 +0000</pubDate>
      <link>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-built-my-cloud-platform-on-micro-vms-instead-of-containers-a-security-story-6lm</link>
      <guid>https://dev.to/dhruv_malaviya_cdcc71e595/why-i-built-my-cloud-platform-on-micro-vms-instead-of-containers-a-security-story-6lm</guid>
      <description>&lt;p&gt;Containers are great until you remember they all share one kernel. For a lot of workloads that's fine. But the moment you're running untrusted code, multi-tenant jobs, or anything you wouldn't want leaking into its neighbours, a single kernel exploit is the whole game. That worry is exactly why I made an early architecture call for my platform, Krova &lt;a href="//krova.cloud"&gt;krova&lt;/a&gt;: no shared-kernel containers.&lt;/p&gt;

&lt;p&gt;Enter Firecracker&lt;br&gt;
Firecracker is the open-source micro-VM monitor AWS built to run Lambda and Fargate. Each instance is a real hardware-virtualized VM (KVM under the hood) with its own kernel, but it boots in around 125ms and carries almost none of the weight of a traditional VM. You get the isolation boundary of a VM with something close to the start-up feel of a container.&lt;/p&gt;

&lt;p&gt;That trade-off is perfect for security-minded, ephemeral work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hypervisor-level isolation. Tenants are separated at the virtualization boundary, not by namespaces over a shared kernel.&lt;/li&gt;
&lt;li&gt;Tiny attack surface. Firecracker deliberately ships a minimal device model, far less exposed than a full VM stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How Krova uses it&lt;/p&gt;

&lt;p&gt;Every machine on Krova (a "Cube") is its own Firecracker micro-VM with its own kernel. They get private internal networking rather than a public IP each, ingress is explicit port mapping, and you can sleep or destroy a Cube the instant you're done. So "run something untrusted, then make it vanish" is the default path, not a thing you bolt on.&lt;/p&gt;

&lt;p&gt;And because they boot in about a second and keep their disk between sleeps, the security model doesn't cost you convenience, which is usually the part that makes people skip isolation in the first place.&lt;/p&gt;

</description>
      <category>security</category>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
