Self-hosted Odoo or ERPNext on a VPS your business controls.
First month $1, then the normal monthly price. One per customer.
Odoo Community and ERPNext are open source, and a small business can host either on one VPS for the price of the server alone. You get full root, NVMe RAID10 storage and ECC memory in Amsterdam, where the data stays under EU rules, or in New York for a North American team. Docker compose, one Postgres or MariaDB, a reverse proxy with TLS, and a backup job you have tested.
Transparent pricing
Plans and prices
| Plan | vCPU | Memory | NVMe | Traffic | Monthly | 1 year | |
|---|---|---|---|---|---|---|---|
| Standard | |||||||
| S-2Standard | 1vCPU | 2 GBMemory | 30 GBNVMe RAID10 | UnlimitedTraffic | $7.99/moFirst month $1 | $7.19/mo on 1 year | Start for $1 |
| S-4Standard | 2vCPU | 4 GBMemory | 60 GBNVMe RAID10 | UnlimitedTraffic | $13.99/moFirst month $1 | $12.59/mo on 1 year | Start for $1 |
| S-8Standard | 3vCPU | 8 GBMemory | 120 GBNVMe RAID10 | UnlimitedTraffic | $24.99/moFirst month $1 | $22.49/mo on 1 year | Start for $1 |
| S-16Standard | 4vCPU | 16 GBMemory | 240 GBNVMe RAID10 | UnlimitedTraffic | $44.99/moFirst month $1 | $40.49/mo on 1 year | Start for $1 |
| S-32Standard | 8vCPU | 32 GBMemory | 480 GBNVMe RAID10 | UnlimitedTraffic | $84.99/moFirst month $1 | $76.49/mo on 1 year | Start for $1 |
| S-64Standard | 16vCPU | 64 GBMemory | 720 GBNVMe RAID10 | UnlimitedTraffic | $159.99/moFirst month $1 | $143.99/mo on 1 year | Start for $1 |
| Dedicated CPU | |||||||
| D-4Dedicated | 1vCPU | 4 GBMemory | 45 GBNVMe RAID10 | UnlimitedTraffic | $37.00/moFirst month $1 | $31.45/mo on 1 year | Start for $1 |
| D-8Dedicated | 4vCPU | 8 GBMemory | 90 GBNVMe RAID10 | UnlimitedTraffic | $69.00/moFirst month $1 | $58.65/mo on 1 year | Start for $1 |
| D-16Dedicated | 4vCPU | 16 GBMemory | 160 GBNVMe RAID10 | UnlimitedTraffic | $118.00/moFirst month $1 | $100.30/mo on 1 year | Start for $1 |
| D-32Dedicated | 6vCPU | 32 GBMemory | 220 GBNVMe RAID10 | UnlimitedTraffic | $215.00/mo | $182.75/mo on 1 year | Deploy D-32 |
| D-64Dedicated | 10vCPU | 64 GBMemory | 400 GBNVMe RAID10 | UnlimitedTraffic | $377.00/mo | $320.45/mo on 1 year | Deploy D-64 |
| High Memory | |||||||
| H-64High Memory | 8vCPU | 64 GBMemory | 480 GBNVMe RAID10 | UnlimitedTraffic | $249.00/mo | $211.65/mo on 1 year | Deploy H-64 |
| H-128High Memory | 16vCPU | 128 GBMemory | 960 GBNVMe RAID10 | UnlimitedTraffic | $459.00/mo | $390.15/mo on 1 year | Deploy H-128 |
| H-192High Memory | 24vCPU | 192 GBMemory | 1.4 TBNVMe RAID10 | UnlimitedTraffic | $669.00/mo | $568.65/mo on 1 year | Deploy H-192 |
Why a small business self-hosts its ERP.
The software is open source. The server is the only recurring cost, and it is the same whether five people log in or fifteen.
Your invoices, customers and stock stay in one place you control
An ERP holds the whole company: contacts, quotes, invoices, inventory, payroll data. On a VPS in Amsterdam that data sits on ECC memory and NVMe RAID10 in the EU, under your own root account. Read more on the EU VPS page.
Flat cost, not per seat
Odoo Community and ERPNext have no per-user fee. An S-4 (2 vCPU, 4 GB, 60 GB NVMe) at €11.99 a month ($13.99) runs either for a handful of users, and adding a user costs nothing. Traffic is unlimited and there is no setup fee.
Postgres likes NVMe
ERP screens are hundreds of small queries. Our published pgbench median is 7,364 TPS and 4K random reads reach 122,959 IOPS, so list views and reports stay quick without tuning heroics. See the benchmarks.
Full root means full responsibility
This is unmanaged hosting. We keep the host and network up; you patch the OS, update the containers, keep backups and test a restore. If that is not something your team wants to own, budget for a freelancer or a partner who will.
Which plan for Odoo or ERPNext.
Both run as Python workers in front of a database. RAM per worker decides the plan, then disk for attachments and backups.
| Setup | Plan | Why |
|---|---|---|
| Odoo Community, a handful of users, core apps | S-4 | 2 vCPU, 4 GB: Postgres plus two or three Odoo workers. |
| Odoo with many modules, or 10-20 active users | S-8 | 3 vCPU, 8 GB lets you run more workers and a bigger shared_buffers. |
| ERPNext with its workers, Redis and scheduler | S-8 | The frappe stack runs more processes than Odoo; 8 GB keeps it comfortable. |
| Reports that time out, large imports, multi-company | D-8 or S-16 | Pinned cores for steady long queries, or 16 GB for a bigger Postgres. |
S-4 at €11.99 a month ($13.99) is where we start Odoo Community for a small team. S-8 (3 vCPU, 8 GB, 120 GB) at €21.99 a month ($24.99) is the plan for ERPNext, or for Odoo once you enable many modules and run enough workers that users stop waiting on each other. D-8 (4 vCPU, 8 GB, 90 GB) at €64.00 a month ($69.00) pins each vCPU 1:1 to a physical EPYC Genoa core, which matters when month-end reports and stock valuations run for minutes and you want the same duration every time.
Disk fills faster than people expect. Attachments, PDF invoices, product images and a nightly dump all land on the same volume, and the 60 GB on S-4 is the first thing to run out. Keep backups off-server and move to S-8 or add +100 GB NVMe for €11.00 a month when df -h passes 70%. RAM and vCPU resize in place with one short reboot.
Setting up Odoo with docker compose.
Step 1: Order the VPS and install Docker
Pick Ubuntu 24.04 or Debian 13 during ordering; the server is online 30-60 seconds after payment. Add your SSH key through cloud-init, then install Docker with the script the Docker project publishes.
apt update && apt upgrade -y && apt install -y ufw restic
ufw allow OpenSSH && ufw allow 80,443/tcp && ufw enable
curl -fsSL https://get.docker.com | sh
mkdir -p /srv/odoo/{config,addons,backups} && cd /srv/odoo
Step 2: The compose file: Odoo, Postgres and Caddy
The official image on Docker Hub reads its database settings from environment variables. Pin the major version you intend to run and change the password.
# /srv/odoo/compose.yaml
services:
db:
image: postgres:16
environment: { POSTGRES_DB: postgres, POSTGRES_USER: odoo, POSTGRES_PASSWORD: change-me }
volumes: [db:/var/lib/postgresql/data]
odoo:
image: odoo:18
depends_on: [db]
environment: { HOST: db, USER: odoo, PASSWORD: change-me }
volumes: [odoo:/var/lib/odoo, ./config:/etc/odoo, ./addons:/mnt/extra-addons]
caddy:
image: caddy:2
ports: ["80:80", "443:443"]
volumes: [./Caddyfile:/etc/caddy/Caddyfile, caddy:/data]
volumes: { db: {}, odoo: {}, caddy: {} }
Step 3: Workers, proxy mode and the Caddyfile
Odoo runs single-threaded until you set workers, and with workers on it moves websocket traffic to port 8072. Both go in config/odoo.conf; the Caddyfile routes accordingly and fetches a Let's Encrypt certificate on first start.
# /srv/odoo/config/odoo.conf [options] proxy_mode = True workers = 3 max_cron_threads = 1 db_maxconn = 32 admin_passwd = change-me-too
# /srv/odoo/Caddyfile
erp.example.com {
reverse_proxy /websocket odoo:8072
reverse_proxy odoo:8069
}
docker compose up -d docker compose logs -f odoo
Point the A and AAAA records for erp.example.com at the VPS first. Then open the site and create the database. After that, add list_db = False to odoo.conf and restart, so the database manager is no longer public.
Step 4: ERPNext instead: the frappe_docker route
ERPNext ships its own compose setup in the frappe_docker repository. The single-server file brings up MariaDB, Redis, the web workers, the scheduler and a site in one go.
git clone https://github.com/frappe/frappe_docker && cd frappe_docker docker compose -f pwd.yml up -d docker compose -f pwd.yml logs -f create-site
When the create-site container finishes, the site answers on port 8080. Put Caddy in front exactly as above, pointing at that port, and change the default Administrator password before you add users.
Step 5: Backups you can restore
An ERP backup is two things: the database dump and the filestore with attachments. Dump nightly, push both off the server with restic, and restore once on a scratch VPS to prove it works.
# /etc/cron.daily/odoo-backup #!/bin/sh cd /srv/odoo docker compose exec -T db pg_dump -U odoo -Fc odoo > backups/odoo-$(date +%F).dump docker run --rm -v odoo_odoo:/src:ro -v /srv/odoo/backups:/dst alpine \ tar czf /dst/filestore-$(date +%F).tgz -C /src . restic -r sftp:backup@BACKUP_HOST:/odoo backup /srv/odoo/backups find backups -mtime +7 -delete
Step 6: Upgrades, minor and major
Minor updates are a pull and a restart: docker compose pull && docker compose up -d. Major Odoo versions are a different job. Community has no push-button upgrade path; the usual route is the OpenUpgrade project, and it deserves a copy of the database on a second VPS before you touch production. The Odoo site lists supported versions.
Pitfalls we see, and how to avoid them.
Postgres left on defaults
The container image ships with a tiny shared_buffers. On S-8, set it to a quarter of RAM, raise work_mem for reports and effective_cache_size to what is left. Pass them as command: postgres -c shared_buffers=2GB in compose.
Too many workers for the memory
Every Odoo worker and every frappe gunicorn worker takes its own share of RAM. When memory runs out the OOM killer often picks Postgres, and everyone gets a white screen. Count workers against RAM, watch free -m, and size up before you add workers.
The database manager left open
Odoo exposes /web/database/manager by default. Set list_db = False and a strong admin_passwd once the database exists, and keep Postgres bound to the compose network, never to a public port.
Backups on the same disk
A dump next to the database it came from is not a backup. Push it off-server with restic to any SFTP host, or take our backup add-on at 20-60% of the plan price. Restore it once on a €1 first-month VPS to be sure.
Pick the region closest to your users.
ERP screens are chatty, so latency shows. From Amsterdam we measure 9.0 ms to London, 8.5 ms to Frankfurt and 9.3 ms to Paris. From New York, Boston is 5-8 ms and Toronto 10-15 ms. Same plans and prices in both regions.
Questions about running Odoo or ERPNext on a VPS.
How much RAM does Odoo Community need?
For a handful of users on the core apps, 4 GB on S-4 is enough for Postgres and two or three workers. With many modules, more users or heavy reporting, go to 8 GB on S-8 so you can add workers and give Postgres a larger buffer. Resize in place when you outgrow it.
Does ERPNext need more than Odoo?
Usually yes. The frappe stack runs MariaDB, Redis, several gunicorn workers, a scheduler and a websocket process. We recommend S-8 with 8 GB as the starting point rather than S-4.
Is my ERP data stored in the EU?
If you choose Amsterdam, yes. The server, its NVMe storage and the backups you keep on it are in the Netherlands. BuyVPS is a Dutch company. Pick New York if your team and customers are in North America; the price is the same.
Can you manage or upgrade Odoo for me?
No. This is unmanaged hosting: we look after the hardware, network and hypervisor, and you look after the operating system and the application. Backups and monitoring are available as add-ons.
Odoo Community or Enterprise on this VPS?
Either runs on a VPS. Community is free and is what the compose file above installs. Enterprise needs a subscription from Odoo and its own packages, but the server sizing and the backup routine are the same.
What happens if the VPS is too small after a month?
Resize in place: add RAM or vCPU from the panel or the API, data and IP stay, usually one short reboot. Your first order is also covered by the 30-day performance guarantee if the platform itself does not meet expectations.
Deploy a measured VPS
From $6.79/mo on a 2-year term. KVM on AMD EPYC, NVMe RAID10, ECC memory. No setup fee, cancel monthly.
30-day performance guarantee. Not satisfied? Full refund, no admin fee. How it works