How We Migrated 11 Production Odoo Servers to Ubuntu 22.04 Without a Single Minute of Downtime
When a client came to us with 11 live Odoo servers all running Ubuntu 20.04 and a hard deadline to get them onto 22.04, we knew this wasn't going to be a weekend job. This is the story of how we planned, executed, and verified that migration — without taking a single server offline during business hours.
Why Ubuntu 22.04?
Ubuntu 20.04 LTS (Focal Fossa) reaches end-of-life in April 2025. For production Odoo infrastructure, staying on an unsupported OS means no security patches, no upstream support, and a growing list of package version conflicts. PostgreSQL 12 (shipped with 20.04) also has an end-of-life date, and Odoo 13/14 increasingly wants newer Python packages that don't play well with the older dependency tree.
The client ran a steel industry ERP across 11 servers — each instance serving a different subsidiary, some with 50+ concurrent users during peak hours. A botched migration meant real business downtime, real financial losses.
The Pre-Migration Audit
Before touching a single server, we ran a full inventory. For each of the 11 hosts we documented:
- Current OS, kernel, and package versions
- Odoo version and any custom modules installed
- PostgreSQL version, database size, and live connection counts
- Nginx configuration, SSL certificates, and expiry dates
- Systemd service files and all active cron jobs
- Backup schedules and date of last verified restore
This audit took three days. It was the most important three days of the entire project. Every problem we found during dry runs traced back to something the audit uncovered first.
The Migration Strategy: In-Place vs Fresh Install
We chose a parallel fresh install approach over in-place OS upgrades. In-place upgrades on production servers are theoretically supported but practically fragile. A single package conflict at midnight on a live server is a career-defining experience — and not in a good way.
Our approach: provision a fresh Ubuntu 22.04 server, migrate the database, validate fully, then flip DNS. The old server stays live until validation is complete. This means there is never a point of no return until you are confident. Zero rollback drama.
The Migration Playbook (Server by Server)
For each server we followed this exact sequence without deviation:
- Provision fresh Ubuntu 22.04 VPS on the same hosting provider and region
- Install PostgreSQL 14, Python 3.10, Nginx, wkhtmltopdf, and all Odoo dependencies
- Run
pg_dumpfrom the old server during a low-traffic window - Restore via
pg_restoreon the new server and verify row counts - Copy the Odoo filestore (attachments directory) via rsync with
--checksum - Configure the Odoo conf file, systemd service, and Nginx vhost to mirror the old server
- Run a 48-hour parallel test with production data and a subset of real users
- Update DNS with a 60-second TTL, wait for propagation, monitor for 2 hours
- Decommission the old server after a 7-day holdback period
The Problems We Hit (And How We Fixed Them)
Problem 1: PostgreSQL 12 dumps not fully compatible with version 14. Two of the databases used custom extensions that required manual handling. We caught this during a dry run 10 days before the production migration window and resolved it ahead of time. The dry run saved the project.
Problem 2: Python 3.10 vs 3.8 package changes. Three custom Odoo modules used deprecated Python 3.8 syntax. We patched them before migrating the affected instances — a quick fix, but only because we knew to look for it.
Problem 3: Nginx SSL certificates with hardcoded paths. Some certificates referenced absolute paths from the old server directory structure. These needed updating in the Nginx vhost configs. The audit should have caught this earlier — we added it to our standard checklist going forward.
Problem 4: A 47GB filestore on one instance. Rsync over the production network took 11 hours for this specific server. We scheduled this transfer over a weekend rather than squeezing it into a Tuesday night window.
The Result
All 11 servers migrated in 6 weeks. Zero unplanned downtime. Every migration happened during off-hours or low-usage windows as planned. The client's team noticed faster page loads (PostgreSQL 14 performs measurably better for Odoo workloads) and reported no broken functionality post-migration.
The lesson: zero-downtime migrations are not magic. They are thorough planning, documented dry runs, and the discipline to never skip steps even when the timeline feels tight. The 3-day audit at the start saved us from at least 3 production incidents. That trade-off should be obvious.
If you are running Odoo on Ubuntu 20.04 and have not yet planned your migration path, the time to start is before the deadline, not after.