To self-host Odoo on a VPS, you need a Linux server, PostgreSQL, Odoo itself, a web server in front with SSL, and a backup that you have tested. Getting it to start takes an afternoon. The real work is what comes after: workers, updates, logs, backups and security, every month, for as long as Odoo runs.
Running Odoo on your own VPS is a fair choice. It’s cheap to start, you pick the country, and you have full control. Lots of teams start this way, often with a bit of help from AI to get through the install.
This guide shows each part you take on, in the order you’ll meet it. For each one, you’ll see what Odoo asks for that other apps don’t. Those are the parts nobody warns you about.
1. The server
Pick a VPS with enough memory first, then CPU. Odoo uses memory for each worker, and Postgres wants its own share. A small server can run a test Odoo. A team of 20 people working all day needs more.
Sizing comes down to how many people use Odoo at the same time, not how many accounts you have. Our guide on how many Odoo worker you need shows how to work it out.
Pick the country with care too. Your data lives where the server lives.
2. PostgreSQL
Odoo stores everything in PostgreSQL. You can run it on the same VPS, or use a managed database from your cloud company.
Odoo needs its own database user that can create databases. Don’t run Odoo as the postgres superuser.
sudo -u postgres createuser --createdb --no-superuser --no-createrole odoo
Here is the first Odoo trap. When you restore a database by hand later, it must be owned by the odoo user. If it’s owned by postgres, Odoo’s database manager won’t see it, and you lose time finding out why. On almost any other app, a plain pg_restore is fine. With Odoo, it isn’t.
3. Odoo itself
Install Odoo from the official packages or from source. Use the Python version your Odoo version asks for, in its own virtual environment. Keep your own modules in a separate folder from Odoo’s code, so updates don’t mix them up.
All settings go in one config file. A starting point for a small team:
[options]
db_host = localhost
db_user = odoo
db_password = CHANGE_ME
admin_passwd = A_LONG_RANDOM_PASSWORD
list_db = False
dbfilter = ^yourdb$
addons_path = /opt/odoo/odoo/addons,/opt/odoo/custom-addons
data_dir = /var/lib/odoo
proxy_mode = True
workers = 4
max_cron_threads = 1
gevent_port = 8072
logfile = /var/log/odoo/odoo.log
A few of these lines matter more than they look:
- list_db = False hides the database manager from the internet. Leave it on and anyone can try to reach it.
- admin_passwd protects that manager. Make it long. Never leave the default.
- workers above 0 turns on multi-process mode. With workers = 0, Odoo runs as one process. That’s fine for tests, but too slow for a team at work.
- data_dir is where your files live. Attachments, images and PDFs are not in the database. Remember this for backups.
Run Odoo as a system service, so it starts again after a reboot.
4. The web server, SSL and proxy mode
Odoo should not face the internet on its own. Put Nginx (or another proxy) in front, and let it handle SSL.
Since Odoo 16, live features use a websocket on a second port (8072 by default). If your proxy doesn’t send /websocket there, chat and live updates stop working with no clear error.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream odoo { server 127.0.0.1:8069; }
upstream odoochat { server 127.0.0.1:8072; }
server {
listen 443 ssl;
server_name erp.example.com;
# ssl_certificate and ssl_certificate_key lines go here
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 100m;
location /websocket {
proxy_pass http://odoochat;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;}
location / {
proxy_pass http://odoo;
}
}
Two settings go together here. proxy_mode = True in the Odoo config, and the X-Forwarded-Host and X-Forwarded-Proto headers in the proxy. With only one of the two, Odoo thinks it runs on http:// and on the wrong name. Links in emails, the sitemap and language links on your website all come out wrong. Our proxy mode guide goes through it line by line.
For SSL, a free Let’s Encrypt certificate works well. Set it to renew on its own, then check that it really did.
5. Backups that you know will restore
An Odoo backup has two parts: the database and the filestore. Most home-made backups only save the first.
# database
pg_dump -U odoo -Fc yourdb > /backups/yourdb-$(date +%F).dump
# files (attachments, images, PDFs)
tar -czf /backups/yourdb-files-$(date +%F).tar.gz -C /var/lib/odoo/filestore yourdb
Then three rules:
- Copy the backups off the server. A backup on the same disk dies with the disk.
- Keep more than one. A bad change found a week later needs a backup from before it.
- Restore one, on another server, on a set day each month. Until you’ve done it, you don’t know if your backups work.
To restore, make the database owned by odoo, as in step 2:
createdb -U odoo -O odoo yourdb_restored
pg_restore -U odoo -d yourdb_restored --no-owner --role=odoo /backups/yourdb-2026-10-01.dump
Then put the files back in filestore/yourdb_restored. A database with no filestore opens, but every image and attachment is missing. Our guide on how to know if an Odoo backup will restore covers the full test.
6. Updates
There are three kinds, and each one is yours.
- The server. Security updates for Linux, Nginx and Postgres. Most can run on their own. Some need a restart you have to plan.
- Odoo fixes. Odoo ships bug and security fixes for each version. You pull the new code and restart.
- Your modules. When you change a module, you run an update on the database:
odoo -c /etc/odoo/odoo.conf -d yourdb -u your_module --stop-after-init
An update changes the database. If it fails half way, you can’t go back by just using the old code. Take a backup right before, and try the update on a copy first. That copy is your staging. On a single VPS, you build it yourself.
7. Logs and disk space
Odoo writes a log line for every request. Without log rotation, the log grows until the disk is full, and then Odoo stops. Set up logrotate for /var/log/odoo/ on day one.
Watch the disk for the database, the filestore and your local backups too. All three only grow.
8. Watching it
Someone has to know when Odoo is down, slow, or out of memory, ideally before your team does. At least, set up an outside check on your login page that alerts you, and look at memory and disk each week.
What it adds up to
None of this is hard on its own. The hard part is that it never ends, and each Odoo trap shows up one at a time, often on a busy day. Learning them all takes months, and each one costs about what the last problem cost.
In our experience, a self-run Odoo takes 10 hours a month to keep in good shape. It takes more in a bad month.
If you’ve run Odoo in production before, a VPS is a good choice and this list won’t surprise you. If you haven’t, compare the real cost first: self-hosting vs managed.
Keep your VPS, hand over the Odoo work
There is a middle way. You keep your VPS, in your account and your country. We run Odoo on it: deploys from Git, staging, backups, updates and help from Odoo experts. You keep the server running and big enough. Our software connects out from your server, so you don’t open any port to us.
See how bring your own server works. Or read the six ways to host Odoo side by side.
Skysize is built by ex-Odoo engineers and is ISO 27001 certified.
Talk to an Odoo hosting expert
FAQ
Can I host Odoo on a VPS? Yes. You need a Linux server, PostgreSQL, Odoo, a web server with SSL in front, and tested backups. Getting it running is quick. Keeping it in good shape takes time every month.
How big should my VPS be for Odoo? It depends on how many people use Odoo at the same time. Memory matters most. See how many Odoo workers you need.
Why do live chat and live updates not work on my VPS? Most often the proxy doesn’t send /websocket to port 8072. Check that gevent_port in the Odoo config matches the port in your proxy.
Why are links in my Odoo emails on http:// or the wrong domain? Odoo doesn’t know it sits behind a proxy. Set proxy_mode = True and send the X-Forwarded-Host and X-Forwarded-Proto headers.
What does an Odoo backup need to include? The database and the filestore. The filestore holds your attachments, images and PDFs, and it is not in the database.
Is self-hosting Odoo cheaper? The server is cheaper. Your time is the cost. Count the hours each month before you decide.