How to Self-Host Inventory on a VPS (and Skip the SaaS Tax)

A capable VPS runs about $12 to $24 a month, less than a single seat of most cloud inventory tools, and you keep every row of your stock data on hardware you control. This guide walks the full path to self-host inventory on a VPS: picking the right server size, locking it down, deploying the app, and keeping it alive. No hand-waving, just the steps and the numbers.
Why a VPS beats shared hosting and SaaS
Shared cPanel hosting is fine to start, but you hit walls fast: capped PHP memory, no root access, no long-running queue workers, and shared CPU that throttles under a busy sync. SaaS solves the ops problem but charges per seat and parks your data on someone else's account, which gets expensive and awkward the moment you add warehouse staff or want a raw database export.
A VPS sits in the middle and, for most small-to-mid operations, wins outright. You get root, a predictable monthly bill that does not scale with headcount, and the freedom to run whatever stack you like. The tradeoff is that you own the maintenance. That is a real cost, but a smaller one than most people assume once the initial setup is done.
Sizing the VPS: a formula that actually works
Most people either over-buy an 8 GB box "to be safe" or cram everything onto a 1 GB instance that swaps itself to death during a bulk import. Here is a heuristic that holds up for a web app, a database, and a queue worker on one machine:
RAM (GB) = 1 (OS + headroom)
+ 0.5 (web server + PHP/app runtime)
+ 0.4 per 10 concurrent users
+ 1.0 per 100,000 SKUs (DB working set)
vCPU: start with 2. One core handles web traffic, the other absorbs background jobs (label generation, stock recalcs, webhook fan-out) without stalling the UI.
Disk: base OS and app need about 5 GB. Add roughly 1 GB per 250,000 inventory movements you plan to retain, then double it for database indexes, logs, and backups staged locally before they ship off-server.
Worked example
A distributor with 5 concurrent users, 20,000 SKUs, and around 200 orders a day:
- RAM: 1 + 0.5 + (0.4 × 0.5) + (1.0 × 0.2) = about 1.9 GB
- Round up to a 2 vCPU / 4 GB plan for headroom during imports and reindexing
- Disk: 40 GB SSD is plenty for a couple of years of movement history plus staged backups
That is a $12 to $20 box at most providers. You would grow into a 4 vCPU / 8 GB plan somewhere north of 100,000 SKUs or 15 concurrent users, and swapping up is usually a reboot, not a migration.
Cost comparison
| Option | Typical monthly | What you actually get |
|---|---|---|
| VPS (2 vCPU / 4 GB) | $12 to $24 | Root access, unlimited users, full data control, you run ops |
| Shared cPanel | $5 to $15 | Easy start, capped PHP memory, no root, no persistent workers |
| SaaS inventory | $30 to $99 per user | Managed and hands-off, per-seat pricing, data lives on their account |
The gap widens with every person you add. Five warehouse users on a $40 per seat plan is $200 a month. The same team on one VPS is still $20, and adding a sixth user costs nothing.
How to self-host inventory on a VPS in 8 steps
This is the short version of a repeatable deploy. It assumes Ubuntu 22.04 or 24.04, which covers most providers.
- Spin up the server. Pick your provider, choose a nearby region for latency, and create a plain Ubuntu instance from your sizing math above.
- Create a non-root user. Add a sudo user, upload your SSH key, then disable root login and password auth in
sshd_config. Key-only access removes the single biggest attack surface on a public VPS. - Set the firewall.
ufw allow OpenSSH,ufw allow 80,ufw allow 443, thenufw enable. Nothing else should be reachable from the internet. - Install the stack. Either Nginx + PHP 8.3+ + your database of choice, or Docker and Docker Compose if you prefer containers. Containers make upgrades and rollbacks cleaner, which matters more than raw speed here.
- Point DNS and get TLS. Add an A record for your subdomain, then issue a free Let's Encrypt certificate with Certbot or your reverse proxy's built-in ACME. Renew on a cron job so it never lapses.
- Deploy the app and migrate. Pull the code (or the image), set your environment file, and run the database migrations. Confirm the app answers on HTTPS before moving on.
- Run a queue worker and process manager. Inventory apps do real background work: recalculating stock, firing webhooks, syncing locations. Use systemd or a supervisor so that worker restarts on crash and on reboot.
- Automate backups. A nightly database dump plus a files snapshot, pushed off the server. Details below, because this is the step people skip and regret.
Backups, updates, and staying alive
Follow the 3-2-1 rule: three copies, two media, one off-site. On a VPS that translates to a nightly mysqldump (or pg_dump), an archive of your uploads directory, and a push to object storage in a different region. A tool like restic handles deduplication and encryption in one command, and you can wire it to cron in ten minutes.
Test a restore before you need one. A backup you have never restored is a hope, not a backup. Once a quarter, pull the latest snapshot onto a throwaway instance and confirm the app boots against it.
For updates, put OS security patches on unattended-upgrades and handle app upgrades deliberately: snapshot the VPS first, deploy to a staging copy if the change is large, then promote. With containers this is close to painless because rolling back is just pointing at the previous image tag.
Where Inventoros fits
If you would rather not hand-roll the application layer, Inventoros is built for exactly this setup. It is free, open source (MIT), and self-hosted, with multi-location stock, plugins, webhooks, and a full REST and GraphQL API out of the box, so the box you just provisioned has something real to run. It installs on a VPS, cPanel, or Docker, and the documentation covers the deploy path end to end without a sales call in the middle.
FAQ
How much RAM do I need to self-host an inventory system? For a typical small operation (a handful of users and tens of thousands of SKUs), 4 GB is comfortable and 2 GB works if you keep imports modest. Use the formula above: start from 1 GB for the OS, add for your user count and SKU volume, then round up one tier for headroom during bulk operations and reindexing.
Is it safe to self-host inventory data on a VPS? Yes, if you do the basics: SSH keys only with password login disabled, a firewall that exposes just 22, 80, and 443, TLS on every request, and automated off-site backups. A locked-down VPS is arguably safer than a SaaS account, because the only people with access are the ones you gave keys to, and there is no shared control plane to breach.
Can I move from cPanel to a VPS later? Almost always. Export your database and files from the shared host, provision the VPS, import, then repoint DNS. Because the application and data are portable, the migration is mostly downtime planning rather than a rebuild. Doing a trial import onto the new server before you cut over removes the surprises.
VPS or Docker, which should I pick for self-hosting inventory? They are not competitors. Docker runs on the VPS. The real choice is Docker Compose versus installing the stack directly on the host. Containers make upgrades, rollbacks, and clean reinstalls easier, so most people should default to Compose unless they have a specific reason to run bare metal packages.