Dev.to · 7 min read

"How I let AI agents work on my production server without breaking it"

"How I let AI agents work on my production server without breaking it"

description: "A solo operator's rulebook: agents propose, a human applies. Real incidents and the rules they produced, from a small town in Greece." tags: ai, devops, productivity, webdev cover_image: [Image description] [Human Gate] I'm not a classic programmer. I started as a photographer and art director, and today I run a network of 42 domains, a handful of SaaS platforms and a fleet of AI chat assistants from Diakopto, a small town in Greece. Most of that code was written by AI agents working inside my editor over SSH, on the same server that serves real users. The agents are faster than me at almost everything. That's exactly the problem. A fast agent with shell access can take down in thirty seconds what took a month to build. So I don't try to make the agents smarter. I make the path to production narrower. This post is the rulebook, and most of the rules exist because something went wrong once. Rule 1: Agents propose, I apply Every change to production starts as a file, not a command. The agent audits first (read-only: configs, logs, row counts, what's actually deployed) and then writes a PROPOSED.md with four parts: The change: which files, which tables, which services Blast radius: what else could break, and for whom Rollback: the exact steps back, written before the change Checks: how we'll know it worked I read it, ask questions, and only then say GO. Silence is not a GO. "Looks fine" in the middle of a different conversation is not a GO. The incident behind the rule: once, my editor froze while I was still reading a proposal. The agent didn't wait. It applied the change, which happened to pass every check. Nothing broke, and that's what scared me: next time the change might not be one that passes. Since then, the agent's instructions end every proposal with write it, report, stop. Rule 2: Some commands are never the agent's Agents write files to disk. Unless I give an explicit GO for that specific step, they don't: run npm run build restart processes (pm2 restart) change nginx run database migrations git push publish anything The build one surprises people. On my server, several frontends are served straight from their dist/ folder. That means building is deploying. An agent that "just runs a quick build to check for errors" has shipped whatever was on disk to every visitor. Two of my repos also had GitHub Actions that deployed on every push to main. I switched both off. If a push can deploy, then anything that can push can deploy. Rule 3: Never prisma migrate dev on the server migrate dev is a development tool. When it detects drift between your migration history and the real database, its answer can be to reset the database. On a laptop that's a shrug. On production it's a very bad afternoon. My database also has partial unique indexes that I created with raw SQL, because Prisma's schema doesn't express them the way I needed. Prisma doesn't know they exist, so any tool that "syncs" the schema is a tool that can quietly drop them. For the same reason, prisma db push is banned too: it bypasses migration history completely. Schema changes on the server follow one fixed sequence: pg_dump -Fc mydb > /var/backups/mydb-before-change.dump psql mydb -f 2026-09-10-add-column.sql npx prisma generate Snapshot at the provider, dump, handwritten SQL, update schema.prisma to match, regenerate the client, and then a restart that I approve. It's boring. Boring is the point. Rule 4: Every command has an address I work with three places that can run commands: the terminal on my Mac, a terminal on the server, and the agent itself. Every command I receive is labeled with where it runs, and I get one command at a time. This sounds bureaucratic until you paste scp ~/Downloads/logo.png ... into the server terminal, or a sudo command into your Mac. I've done both. My rule of thumb now: if it starts with cd ~/Downloads or scp, it belongs on the Mac. If it starts with cd /var/www or sudo, it belongs on the server. Rule 5: A test that has never failed has proven nothing One of my platforms caches data per client. I asked for a test that proves client A can never see client B's data. The test passed. Then we broke the code on purpose: made the cache global, so every client shared it. If the test still passed, it was decoration. It failed, loudly, which is the only reason I trust it now. When an agent writes a security test, make it show you the test failing against broken code before you believe it passes against working code. Rule 6: Silent fallbacks are lies My AI chat gateway was configured with a primary model provider and a fallback. Everything "worked". An audit showed that the primary had never worked on that gateway: first a dead key, then retired model names. For weeks every conversation had silently gone through the fallback, and nothing anywhere said so. Now every fallback is counted and visible. When the gateway serves a prompt from its fallback path, a counter goes up and the logs say why. A fallback you can't see is a fault that hasn't been reported yet. Rule 7: Real numbers only A mockup for my company's homepage once had a lovely "live console": a site count slowly drifting upward, a made-up hostname, ping values from Math.random(). It looked great. It was also lying to every visitor. The rule now covers every screen I own: if a number isn't measured, the UI shows "—". No placeholder that looks real, no "estimated" metric that nobody estimated. Rule 8: Ground truth beats screenshots I was once sure a redesign was already live, because I had a screenshot of it. The agent disagreed, and instead of arguing it proved it with four checks: which docroot nginx actually serves, the hash of the file on disk versus what the edge returned, the MIME types, and which stylesheet loaded last. The design had never been live. My screenshot was the prototype, open in another tab. Memory, mine or the agent's, is not evidence. The server is. The small rules Backups live outside the web root. I once found a backup file sitting in a public folder on one of my own sites, downloadable by anyone who guessed the name. Secrets never go into chat. The agent never gets admin passwords. If a check needs a real login in a browser, I do that part myself. Two editor windows, maximum. Power cuts happen here, and every cut leaves dead SSH sessions behind that eat connections. Two files per project. JOURNAL.md is append-only and written by the agent. PENDINGS.md is the to-do list, and only I edit it. Every session closes with three lines: what closed, what's blocked, what's next. What it costs, what it buys It's slower. A change I could "just do" in two minutes takes fifteen: audit, proposal, questions, GO, apply, verify. What it buys is that I can sleep. A recent audit showed four long-running services on the server that had gone more than two weeks without a single restart. That's not because the agents never make mistakes. They make plenty. It's because their mistakes land in a proposal, where they cost me a question instead of an outage. How do you work with AI agents near production? Do you let them run builds or migrations, or do you keep a gate like this? I'd genuinely like to know where other people draw the line. Alexandros · Web Host Pro · Diakopto, Greece

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More AI & Machine Learning News