Odoo Online and Odoo.sh are the easiest ways to run Odoo, but many companies prefer to self-host: full control over the server, custom modules without restrictions, and predictable hosting cost. This guide shows how we at Bundo Tech set up a clean, production-ready Odoo 19 server on Ubuntu 24.04. It takes about 45 minutes.
What you need: a VPS with Ubuntu 24.04, at least 2 vCPU and 4 GB RAM (8 GB for more than 20 users), a domain pointing to the server's IP, and root or sudo access.
1. Update the server and create the odoo user
sudo apt update && sudo apt upgrade -y
sudo adduser --system --group --home /opt/odoo --shell /bin/bash odoo
Running Odoo as its own system user (never root) limits the damage if anything goes wrong.
2. Install PostgreSQL
sudo apt install -y postgresql
sudo -u postgres createuser --createdb odoo
The database role has the same name as the Linux user, so Odoo connects through the local socket with no password needed.
3. Install system dependencies
sudo apt install -y git python3-venv python3-dev build-essential \
libpq-dev libxml2-dev libxslt1-dev libldap2-dev libsasl2-dev \
libjpeg-dev zlib1g-dev libffi-dev nodejs npm
sudo npm install -g rtlcss
For PDF reports (invoices, quotations) Odoo needs wkhtmltopdf 0.12.6 with patched Qt. The version in Ubuntu's own repository is not the patched build and produces reports without headers and footers, so download the patched .deb from the wkhtmltopdf GitHub releases page and install it with sudo apt install ./wkhtmltox_*.deb.
4. Download Odoo 19 and create a virtual environment
sudo su - odoo
git clone https://github.com/odoo/odoo.git --depth 1 --branch 19.0 /opt/odoo/odoo
python3 -m venv /opt/odoo/venv
/opt/odoo/venv/bin/pip install wheel
/opt/odoo/venv/bin/pip install -r /opt/odoo/odoo/requirements.txt
mkdir /opt/odoo/custom-addons
exit
Keep your own modules in /opt/odoo/custom-addons, never inside the Odoo source folder. Updating Odoo then never touches your code.
5. Write the configuration file
Create /etc/odoo.conf:
[options]
admin_passwd = CHANGE_THIS_TO_A_LONG_RANDOM_STRING
db_user = odoo
addons_path = /opt/odoo/odoo/addons,/opt/odoo/custom-addons
data_dir = /opt/odoo/.local/share/Odoo
logfile = /var/log/odoo/odoo.log
proxy_mode = True
http_interface = 127.0.0.1
list_db = False
; performance
workers = 5
max_cron_threads = 1
limit_memory_soft = 2147483648
limit_memory_hard = 2684354560
limit_time_cpu = 600
limit_time_real = 1200
sudo mkdir /var/log/odoo && sudo chown odoo: /var/log/odoo
sudo chown odoo: /etc/odoo.conf && sudo chmod 640 /etc/odoo.conf
How many workers? A common rule is (CPU cores x 2) + 1, then check that RAM allows it: each worker uses roughly 150 to 300 MB. list_db = False hides the database manager from the internet, and http_interface = 127.0.0.1 makes sure only nginx can reach Odoo.
6. Run Odoo as a systemd service
Create /etc/systemd/system/odoo.service:
[Unit]
Description=Odoo 19
After=network.target postgresql.service
[Service]
Type=simple
User=odoo
Group=odoo
ExecStart=/opt/odoo/venv/bin/python3 /opt/odoo/odoo/odoo-bin -c /etc/odoo.conf
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now odoo
sudo systemctl status odoo
7. Put nginx in front with free SSL
Create /etc/nginx/sites-available/odoo (replace erp.example.com):
upstream odoo { server 127.0.0.1:8069; }
upstream odoochat { server 127.0.0.1:8072; }
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name erp.example.com;
client_max_body_size 100m;
proxy_read_timeout 720s;
location /websocket {
proxy_pass http://odoochat;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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;
}
location / {
proxy_pass http://odoo;
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;
}
gzip on;
gzip_types text/css text/plain application/javascript application/json image/svg+xml;
}
sudo apt install -y nginx certbot python3-certbot-nginx
sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d erp.example.com
The /websocket block matters: with workers enabled, live chat, notifications and Discuss go through port 8072. Without it, users see a "connection lost" banner.
8. Set up daily backups
A server without tested backups is not production-ready. Back up both the database and the filestore (attachments live there, not in PostgreSQL):
#!/bin/bash
# /opt/odoo/backup.sh (run as the odoo user from cron)
DB=mydb
DEST=/opt/odoo/backups
STAMP=$(date +%F)
mkdir -p $DEST
pg_dump -Fc $DB > $DEST/$DB-$STAMP.dump
tar -czf $DEST/$DB-filestore-$STAMP.tar.gz -C /opt/odoo/.local/share/Odoo/filestore $DB
find $DEST -type f -mtime +14 -delete
Schedule it with crontab -e as the odoo user (for example 30 2 * * * /opt/odoo/backup.sh) and copy the files off the server (S3, Backblaze or another VPS). Restore one backup to a test database every month to prove it works.
9. Security checklist
- Enable the firewall and allow only SSH, HTTP and HTTPS:
sudo ufw allow OpenSSH && sudo ufw allow 'Nginx Full' && sudo ufw enable - Use a long random
admin_passwdand keeplist_db = False. - Disable SSH password login and use keys.
- Install fail2ban and keep Ubuntu security updates on.
- Pull Odoo source updates regularly with
git pullin/opt/odoo/odoo, then restart the service.
Common problems
- 502 Bad Gateway: Odoo is not running. Check
sudo journalctl -u odoo -n 50and/var/log/odoo/odoo.log. - PDF without header or footer: the unpatched wkhtmltopdf is installed. Install the patched 0.12.6 build.
- Workers killed / timeouts on big imports: raise
limit_time_realandlimit_memory_hard, or run the import from the command line. - Wrong URLs (http instead of https) in emails: make sure
proxy_mode = Trueand nginx sendsX-Forwarded-Proto.
Need it done for you?
Bundo Tech is an Official Odoo Partner. We set up, harden and maintain self-hosted Odoo servers, migrate existing databases and provide ongoing support. See our Odoo deployment and managed Odoo hosting services, or contact us for a free consultation.