Someone installed a bitcoin miner on my hardened VPS. That incident forced me to admit I did not want to own a server anymore — I wanted to own configuration.

I had a VPS on OVH, and I had secured it as well as a frontend developer can
secure a Linux box: SSH on a non-standard port, key-based authentication with a
long passphrase, fail2ban, UFW with only the necessary ports open, and
automatic security updates. Not just the baseline from "harden your VPS" guides
— I went a step beyond it.
It was not enough.
Someone got in anyway and installed a cryptocurrency miner. I did not find out from monitoring — monitoring a side-project VPS is exactly the kind of thing that quietly falls off your todo list. I found out because OVH emailed me that something was wrong with my VPS: it was trying to break into other VPS instances and generating a lot of suspicious traffic.
That was the uncomfortable part. After the OVH email, I started scanning the server, checking running processes, suspicious files, and outbound connections. That is when I found the miner. I did not know how long it had been there, what else had changed, or whether cleaning the machine would mean I could ever trust it again.
That was the moment I decided to migrate to AWS Amplify. Not for cost. For the simple reason that a server I had hardened to the best of my ability had still been compromised — and the thing I had stopped paying attention to was no longer something I could afford to own.
It is not. A misconfigured AWS account can leak just as badly as a misconfigured VPS — sometimes worse, because the bills scale with the abuse.
The lesson is different: a VPS is a server you are responsible for. Amplify is a platform that is responsible for the server.
On the VPS, I owned the OS patches, the web server config, the SSL renewal, the firewall rules, the SSH keys, the cron jobs I forgot I had created, and the cryptocurrency miner that someone else installed for me.
On Amplify, I own the build config.
That is the actual trade. It is not a security trade. It is a what am I willing to be responsible for trade. For a frontend developer working alone on a personal project, the second list is the right answer. I had spent years pretending I was a part-time sysadmin. I am not.
The obvious move would have been Vercel. Or Netlify. Or Cloudflare Pages. Any platform where you connect a repository, click two buttons, and your site is live. They would all have worked. Vercel especially — it is excellent for Next.js, the DX is unbeatable, and for a lot of frontend developers it is the correct answer.
I did not pick any of them. I have never been someone who reaches for the simplest option. I wanted to configure it myself.
Not to prove anything. I wanted to do a little DevOps — to understand what a
build pipeline actually looks like when you have to declare it yourself. What
goes in amplify.yml. What the cache directories do. How IAM and SSL and CDN
fit together. The "click two buttons and done" platforms hide all of that, which
is their strength. It is also why I did not pick them.
AWS specifically was a personal choice more than a technical one. At work there was always a backend engineer who owned the infrastructure side. I had wanted to do more on AWS for a long time but never had the excuse. After my Cloud Practitioner certification I had the vocabulary but no real project. A personal blog is the perfect low-stakes way to learn AWS — if the migration had gone badly, my blog would have been down for a weekend. That is the entire blast radius.
AWS Amplify hosts the whole site with build on push, automatic SSL, and preview deployments for pull requests or connected branches. Cloudflare sits in front for DNS, proxying, caching, and edge rules. The domain stayed where it was.
No EC2. No VPS. No load balancer. No shell I am responsible for keeping patched.
Migration took 2 to 3 hours — most of it DNS propagation waiting. Deleting the compromised VPS took 30 seconds.
This is what convinced me Amplify is meant for frontend developers. The entire
deployment is one amplify.yml:
version: 1
frontend:
phases:
preBuild:
commands:
- node -v
- corepack enable
- corepack prepare pnpm@9 --activate
- pnpm config set store-dir .pnpm-store
- pnpm config set node-linker hoisted
- pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
build:
commands:
- pnpm build
environment:
variables:
NEXT_PUBLIC_SITE_URL: https://my-site
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- .pnpm-store/**/*
- .next/cache/**/*A few things worth noticing:
.pnpm-store and .next/cache both cached — subsequent builds reuse
installed packages and Next.js incremental compilation. First deploy is slow,
every one after is fast.--ignore-scripts on install — lifecycle scripts in dependencies are a
security and reliability risk on CI. Any postinstall step I need goes
explicitly in the build phase.That is the entire deployment pipeline. No server. No miner.
Deploys. Push to main, Amplify builds, the site updates. If it fails, I get an email with the line that broke.
Preview environments. Branches and pull requests can get their own URLs. On OVH this would have meant a second VPS or a subdomain hack.
SSL and CDN. Cloudflare handles the edge. Amplify handles the hosting layer. I stopped thinking about both.
The attack surface. By moving to Amplify, I deleted the box that was the actual security problem. I did not "harden" it. I deleted it. That is the cheapest possible security improvement.
The first amplify.yml took me longer than it should have — the docs assume you
already know where Next.js puts its build artifacts. Expect 30 minutes of trial
and error for the first green build.
DNS at the cutover is the only genuinely stressful part. You point things and wait, point and wait. The first 20 minutes feel like the migration failed. It has not.
It dropped significantly. I am not going to quote a single number because AWS bills you in dollars, the złoty cost depends on the exchange rate, and it scales with deploys and traffic. The point is not the savings — the point is that the cost now scales with what the site actually does, instead of being a flat fee I was paying whether anyone visited or not.
This is the part most "migrate to AWS" posts skip.
I will save you the scroll:
amplify.yml is all you
are getting. The deep dive deserves its own post.This post is for the frontend developer with a forgotten VPS, a Cloud Practitioner cert, and the feeling that there might be a better way. That was me until this migration forced the decision.
If you own a VPS you have not logged into for months, you do not own a server. You own a liability.
Hardening helps. It is not enough. I had fail2ban, key-based auth with a long
passphrase, a non-standard SSH port, UFW with only the necessary ports open,
automatic updates — and someone still got in. I only found out because my
provider noticed the traffic and warned me. A server you do not actively
maintain will eventually become a problem, no matter what you configured on day
one. Time is on the attacker's side.
If your VPS exists because you needed a server at some point and that point has passed, the right move is to delete it. Not migrate it. Not back it up. Delete it. Whatever you migrate to should be a platform, not another server.
You probably do not need a higher certification than Cloud Practitioner to do this. The cert teaches you the vocabulary. Amplify hides almost everything else behind a UI that looks familiar if you have used modern frontend hosting. The mental block is bigger than the technical block.
The migration was an afternoon of work and a configuration file. The lesson took a few months and one bitcoin miner.
The real shift is not from OVH to AWS. It is from owning servers to owning configuration. From running infrastructure to declaring it. From being responsible for a Linux box to being responsible for a YAML file.
That is the trade. And once you see it, you do not go back.
If you want to compare the actual setup, my blog is the live example — Next.js 15, deployed via Amplify, served behind Cloudflare. No bitcoin miners involved.
Was this helpful?