<?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: Carlos Salamanca</title>
    <description>The latest articles on DEV Community by Carlos Salamanca (@salamancacm).</description>
    <link>https://dev.to/salamancacm</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%2F3628066%2F9c502f26-39d7-4934-b289-e47176f08759.jpg</url>
      <title>DEV Community: Carlos Salamanca</title>
      <link>https://dev.to/salamancacm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salamancacm"/>
    <language>en</language>
    <item>
      <title>I kept seeing weird stuff on my VPS, so I built a tool to stop guessing</title>
      <dc:creator>Carlos Salamanca</dc:creator>
      <pubDate>Sat, 25 Jul 2026 21:07:02 +0000</pubDate>
      <link>https://dev.to/salamancacm/i-kept-seeing-weird-stuff-on-my-vps-so-i-built-a-tool-to-stop-guessing-2808</link>
      <guid>https://dev.to/salamancacm/i-kept-seeing-weird-stuff-on-my-vps-so-i-built-a-tool-to-stop-guessing-2808</guid>
      <description>&lt;p&gt;A few weeks ago I noticed some things I couldn't explain on one of my VPS instances — nothing catastrophic, just enough "that's not right" to make me nervous. I went looking for a lightweight tool to audit and harden a fresh Linux server and mostly found two things: hand-rolled bash scripts of wildly varying quality, or heavyweight compliance scanners built for enterprises running hundreds of servers, not someone with a couple of &lt;code&gt;$5/mo&lt;/code&gt; boxes.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/salamancacm/vpsguard" rel="noopener noreferrer"&gt;&lt;strong&gt;vpsguard&lt;/strong&gt;&lt;/a&gt; — a single Go binary that audits, hardens, and monitors a Linux VPS, with no dependencies beyond what's already on the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rtee18xdb90ilfdpqhs.gif" 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%2F2rtee18xdb90ilfdpqhs.gif" alt="vpsguard audit, harden, and monitor catching a simulated SSH key intrusion" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a real recording — &lt;code&gt;audit&lt;/code&gt; finding real issues on a stock Ubuntu box, &lt;code&gt;harden&lt;/code&gt; fixing them, and &lt;code&gt;monitor&lt;/code&gt; catching a simulated attacker adding their own SSH key. No staged screenshots.&lt;/p&gt;

&lt;p&gt;Twelve checks in total: SSH config, firewall (ufw &lt;em&gt;and&lt;/em&gt; firewalld — more on that below), fail2ban, suspicious user accounts, SSH key hygiene, cron, pending updates, exposed database ports, Docker socket permissions, kernel/patch status, and (as a beta check) AWS EC2's IMDSv1 exposure — the same SSRF vector behind the Capital One breach.&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;harden&lt;/code&gt; remediation is idempotent — run it ten times, get the same end state, no duplicated config lines — and every config file it touches gets backed up first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that actually matters: monitor
&lt;/h2&gt;

&lt;p&gt;Audit is nice, but the thing that motivated this whole project was catching &lt;em&gt;change&lt;/em&gt; — someone adding an SSH key you didn't add, a new UID-0 account, a new process running as root. &lt;code&gt;vpsguard monitor&lt;/code&gt; snapshots server state and diffs it against the last run — that's the second half of the GIF above, where it catches the CRIT the instant the attacker's key gets added.&lt;/p&gt;

&lt;p&gt;Wire it to cron (&lt;code&gt;vpsguard install-cron&lt;/code&gt;) and point it at a Slack/Discord webhook or email, and you get pinged instead of finding out three weeks later when you happen to check a log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it from CI/CD
&lt;/h2&gt;

&lt;p&gt;If you'd rather bake this into a pipeline than remember to run it yourself, there's a &lt;a href="https://github.com/marketplace/actions/vps-fleet-audit-vpsguard" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt; that audits a whole fleet on a schedule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VPS security audit&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt; &lt;span class="c1"&gt;# daily at 06:00 UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;audit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;salamancacm/vpsguard-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-1.example.com,db-1.example.com&lt;/span&gt;
          &lt;span class="na"&gt;ssh-user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
          &lt;span class="na"&gt;ssh-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VPS_SSH_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;ssh-known-hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VPS_KNOWN_HOSTS }}&lt;/span&gt;
          &lt;span class="na"&gt;fail-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CRIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It installs vpsguard on the runner, connects to each host with your own SSH key (never vpsguard's — it doesn't handle credentials), runs the audit, and writes a summary table straight into the workflow's job summary. Set &lt;code&gt;fail-on&lt;/code&gt; to &lt;code&gt;CRIT&lt;/code&gt;, &lt;code&gt;WARN&lt;/code&gt;, or &lt;code&gt;NONE&lt;/code&gt; depending on whether you want a bad finding to actually fail the build or just get reported; it also exposes &lt;code&gt;crit-count&lt;/code&gt;, &lt;code&gt;warn-count&lt;/code&gt;, and &lt;code&gt;unreachable-count&lt;/code&gt; as outputs if you want to branch on them yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things I'm actually proud of
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's honest about what it hasn't verified.&lt;/strong&gt; The AWS IMDSv1 check is tagged &lt;code&gt;[BETA]&lt;/code&gt; in its own output, because I built and unit-tested it but never ran it against a real EC2 instance (that would mean spending real money on infra I didn't need). Rather than pretend otherwise, findings from unverified checks are marked, everywhere — table output and &lt;code&gt;--json&lt;/code&gt; both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real bugs got caught by testing against real systems, not mocks.&lt;/strong&gt; Validating the RHEL/&lt;code&gt;dnf&lt;/code&gt; code path against an actual Rocky Linux container surfaced two genuine bugs: &lt;code&gt;harden&lt;/code&gt; was trying to &lt;code&gt;dnf install ufw&lt;/code&gt; (not in RHEL's repos at all) and the audit checks had no concept of &lt;code&gt;firewalld&lt;/code&gt; — RHEL's actual default firewall — so a properly-secured RHEL box would've been reported as having &lt;em&gt;no firewall at all&lt;/em&gt;. Fixed, and now covered by real Rocky Linux testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;vpsguard fleet&lt;/code&gt;&lt;/strong&gt; audits multiple hosts over SSH at once, using your own SSH config/agent — the same mechanism the GitHub Action above wraps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/salamancacm/vpsguard/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Checksum-verified against the release, refuses to install on a mismatch — read the script first if piping curl to sh isn't your thing, which is fair.) Also available via &lt;code&gt;go install&lt;/code&gt;, and Homebrew-on-Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Kernel/patch checking on RHEL is solid; broader cloud-provider coverage (Security Group/VPC-level blindness is a real gap right now — vpsguard only sees the OS firewall, not AWS/GCP's network layer) is on the list. If you run a VPS and have five minutes, &lt;code&gt;vpsguard audit&lt;/code&gt; is read-only and won't touch anything — I'd genuinely like to know what it gets wrong on your setup.&lt;/p&gt;

&lt;p&gt;Repo's here: &lt;strong&gt;&lt;a href="https://github.com/salamancacm/vpsguard" rel="noopener noreferrer"&gt;https://github.com/salamancacm/vpsguard&lt;/a&gt;&lt;/strong&gt; — issues, PRs, and "this check is wrong" reports all welcome.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a visual API generator — no code, no prompts, just clean backend projects</title>
      <dc:creator>Carlos Salamanca</dc:creator>
      <pubDate>Tue, 25 Nov 2025 00:05:42 +0000</pubDate>
      <link>https://dev.to/salamancacm/i-built-a-visual-api-generator-no-code-no-prompts-just-clean-backend-projects-5cka</link>
      <guid>https://dev.to/salamancacm/i-built-a-visual-api-generator-no-code-no-prompts-just-clean-backend-projects-5cka</guid>
      <description>&lt;p&gt;✨ &lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the past few weeks, I’ve been building a tool that I personally needed for a long time:&lt;br&gt;
a way to generate complete backend projects without writing the same boilerplate over and over.&lt;/p&gt;

&lt;p&gt;The result is GenAPI — a visual API generator that lets you design your data models in a UI and then export a fully working backend project.&lt;/p&gt;

&lt;p&gt;🔗 Try it here: &lt;a href="https://thegenapi.io" rel="noopener noreferrer"&gt;https://thegenapi.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(No login required — 100% free at the moment)&lt;/p&gt;




&lt;p&gt;🛠 &lt;strong&gt;Why I built this&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As developers, we constantly repeat the same setup steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating models/entities&lt;/li&gt;
&lt;li&gt;defining controllers/services&lt;/li&gt;
&lt;li&gt;configuring routes&lt;/li&gt;
&lt;li&gt;setting up project structure&lt;/li&gt;
&lt;li&gt;writing CRUD logic&lt;/li&gt;
&lt;li&gt;preparing basic validations&lt;/li&gt;
&lt;li&gt;wiring everything into a backend framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After doing this hundreds of times across Node, Java, Python and PHP projects, I wanted a faster way.&lt;/p&gt;

&lt;p&gt;Not AI-generated code.&lt;br&gt;
Not templates.&lt;br&gt;
A real visual builder that outputs a clean, ready-to-run backend.&lt;/p&gt;




&lt;p&gt;🧩 &lt;strong&gt;How GenAPI works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The workflow is very simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the visual builder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You start with an empty canvas where you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities&lt;/li&gt;
&lt;li&gt;Fields&lt;/li&gt;
&lt;li&gt;Types&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;Optional constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Choose your backend framework&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once your models are ready, you pick the stack you want to export to.&lt;/p&gt;

&lt;p&gt;Right now GenAPI supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java (Spring Boot)&lt;/li&gt;
&lt;li&gt;Java (Quarkus)&lt;/li&gt;
&lt;li&gt;Node.js (Express)&lt;/li&gt;
&lt;li&gt;Python (FastAPI)&lt;/li&gt;
&lt;li&gt;PHP (Laravel)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Download the generated ZIP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GenAPI creates a complete backend project with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models / Entities&lt;/li&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Routes&lt;/li&gt;
&lt;li&gt;Basic CRUD logic&lt;/li&gt;
&lt;li&gt;Validations&lt;/li&gt;
&lt;li&gt;Clean folder structure&lt;/li&gt;
&lt;li&gt;Dependencies installed&lt;/li&gt;
&lt;li&gt;A README with instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 You run it locally and it just works.&lt;/p&gt;

&lt;p&gt;No prompts.&lt;br&gt;
No AI guesswork.&lt;br&gt;
Just deterministic code based on your entities.&lt;/p&gt;




&lt;p&gt;🎁 &lt;strong&gt;New feature: Starter Templates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To help new users get started quickly, I’m adding starter templates inside the builder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blog API&lt;/li&gt;
&lt;li&gt;E-commerce&lt;/li&gt;
&lt;li&gt;Booking System&lt;/li&gt;
&lt;li&gt;CRM Lite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These load pre-made entities so you can test the tool instantly.&lt;/p&gt;




&lt;p&gt;🚀 &lt;strong&gt;Who is GenAPI for?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This tool is ideal if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build prototypes frequently&lt;/li&gt;
&lt;li&gt;generate small/medium backends&lt;/li&gt;
&lt;li&gt;teach backend development&lt;/li&gt;
&lt;li&gt;want to speed up CRUD-heavy work&lt;/li&gt;
&lt;li&gt;start many client projects&lt;/li&gt;
&lt;li&gt;hate repeating boilerplate code&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🧪 &lt;strong&gt;What I’m currently working on&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More export options&lt;/li&gt;
&lt;li&gt;Better UI for relationships&lt;/li&gt;
&lt;li&gt;SAP CAP export (CDS-based, OData out of the box)&lt;/li&gt;
&lt;li&gt;Auto-documented APIs&lt;/li&gt;
&lt;li&gt;Advanced constraints&lt;/li&gt;
&lt;li&gt;Microservice export mode&lt;/li&gt;
&lt;li&gt;A VSCode extension to sync entities&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🙏 &lt;strong&gt;I’d love your feedback&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since GenAPI is still early, feedback from the dev community is extremely helpful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the builder intuitive?&lt;/li&gt;
&lt;li&gt;Does the generated code look clean?&lt;/li&gt;
&lt;li&gt;What frameworks should I add next?&lt;/li&gt;
&lt;li&gt;Would this be useful in your workflow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comments are 100% welcome.&lt;/p&gt;

&lt;p&gt;🔗 Try it here: &lt;a href="https://thegenapi.io" rel="noopener noreferrer"&gt;https://thegenapi.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
