Odoo 14 → 18 Migration Scripts
This folder contains automation to migrate an Odoo database sequentially through major versions using OpenUpgrade and per‑version local instances.
Primary script:
- migrate_14-18.sh — migrates an Odoo 14 database through 15 → 16 → 17 → 18.
The script follows the PMIverse multi‑version layout and safety conventions described in the global guidelines.
Prerequisites
-
OS: Arch Linux (workstation)
-
PostgreSQL available locally; your user can run
psql,createdb,dropdb,pg_dump,pg_restore. -
Instance folders present (one per Odoo version):
/srv/pmiverse/_pmisuite14//srv/pmiverse/_pmisuite15//srv/pmiverse/_pmisuite16//srv/pmiverse/_pmisuite17/-
/srv/pmiverse/_pmisuite18/ -
Each instance must include:
- Python venv at
<instance>/venv(script sources<instance>/venv/bin/activate) - OCB repo with
odoo-binat<instance>/repos/OCB/odoo-bin - OpenUpgrade repos per version (for 15+) at
<instance>/repos/OCB-openupgrade/<ver>-openupgrade/openupgrade_scripts/scripts -
Odoo config file at
<instance>/config/pmisuite<ver>.confwith correctaddons_path(including OpenUpgrade addons if needed) -
A local PostgreSQL database containing your Odoo 14 data (e.g.,
mydb14).
What the migration script does
migrate_14-18.sh performs a safe, sequential migration. High‑level steps:
- Validates required CLI tools and files:
psql,createdb,dropdb,pg_dump,pg_restore, per‑versionodoo-bin, venvs, configs. - Verifies the source 14.0 DB exists.
- Normalizes the source DB name by replacing dashes with underscores for derived names.
- Performs the migration pipeline:
- Step 0: Create 14 baseline clone
<src>_14. Uninstall obsolete modules (likepmis_stock_analytics) using Odoo 14 shell; backup baseline. - Step 1 (14 → 15): Clone to<src>_15, apply 15.0 pre-migration fixes (e.g., account modules, warehouse mismatches), run OpenUpgrade with 15 env; backup. - Step 2 (15 → 16): Clone to<src>_16, run OpenUpgrade with 16 env; backup. - Step 3 (16 → 17): Clone to<src>_17, apply 17.0 pre-migration fixes (e.g., HR user partner detachment), run OpenUpgrade with 17 env; backup. - Step 4 (17 → 18): Clone to<src>_18, run OpenUpgrade with 18 env; backup. - Writes migration logs to
/srv/pmiverse/logs/openupgrade_<ver>.logand backups (pg_dump -Fc) to/srv/pmiverse/backupsafter each step (unless--skip-backupsis used).
Usage
cd /srv/pmiverse/_pmiconfig/scripts/migrate
./migrate_14-18.sh -d <source_db>
# Optional: overwrite intermediate DBs if they already exist
./migrate_14-18.sh -d <source_db> --force
# Optional: skip backups between versions for speed
./migrate_14-18.sh -d <source_db> --skip-backups
# Help
./migrate_14-18.sh --help
Arguments:
-d, --database <source_db>: required. Name of your existing Odoo 14 DB in Postgres.-f, --force: optional. If present, existing target/intermediate DBs (e.g.,<src>_15) are dropped and recreated as needed.--skip-backups: optional. Skip database backups (.dumpfiles) after each migration step. Recommended for very large databases.--up15-path,--up16-path,--up17-path,--up18-path: override each version's OpenUpgrade scripts directory.-h, --help: print option help without creating directories or accessing databases.
Derived database names:
- The script will create and operate on: <src>_14, <src>_15, <src>_16, <src>_17, <src>_18.
- Dashes in <src> are normalized to underscores when deriving these names.
After migration
When the script completes, your final migrated database is <src>_18. To start Odoo 18 locally against it:
# Activate the 18.0 venv
source /srv/pmiverse/_pmisuite18/venv/bin/activate
# Run Odoo 18 with the pinned config
/srv/pmiverse/_pmisuite18/repos/OCB/odoo-bin \
-c /srv/pmiverse/_pmisuite18/config/pmisuite18.conf \
-d <src>_18 \
--logfile=/srv/pmiverse/logs/odoo18_<src>_18.log
Before first app start on a production‑derived dump, neutralize external effects (mail, URLs, crons, integrations). Example (Odoo shell):
params = env["ir.config_parameter"].sudo()
params.set_param("web.base.url", "http://localhost:18069")
params.set_param("mail.smtp_host", "localhost")
params.set_param("mail.smtp_port", 1025) # mailhog
See the “Safe Handling of Production Dumps (Dev)” section in the global guidelines for a fuller checklist.
Production migration runbook (14 → 18)
This section explains how to migrate a real production database to Odoo 18 using a controlled host to perform the upgrade, then deploy it back to the production server. It complements the local instructions above and follows PMIverse guidelines.
Production-sensitive and destructive: The commands in this section are examples, not verified service names or a complete change plan for every host. Confirm all database names, service units, paths, backups, neutralization controls, and rollback steps for the target environment, then obtain explicit operational approval before execution.
Important principles:
- Always back up both DB and filestore together at each stage.
- Keep config parity with production (ports, proxy_mode = True, wide addons_path).
- Neutralize integrations on restored copies until go‑live.
- Execute in an approved change window with a clear rollback plan.
1) Prepare
- On the migration host (workstation or staging VM), ensure the per‑version instances exist:
/srv/pmiverse/_pmisuite{14,15,16,17,18}with venvs,odoo-bin, OpenUpgrade paths, and pinned configspmisuite{15,16,17,18}.conf. - Ensure Postgres CLI tools are available:
psql,pg_dump,pg_restore,createdb,dropdb. - Choose a working base name
<src>for derived DBs. The script will create<src>_14,<src>_15,<src>_16,<src>_17,<src>_18.
2) Back up production (on the production server)
- Stop Odoo to quiesce writes (unit names may differ):
sudo systemctl stop odoo
# or: sudo systemctl stop odoo14
- Database backup (custom format):
pg_dump -Fc -d <prod_db> > /srv/pmiverse/backups/<prod_db>_pre_migration_$(date +%Y%m%d_%H%M%S).dump
- Filestore backup (the path depends on your production
data_dir):
rsync -aHAX --info=stats2 /path/to/filestore/<prod_db>/ \
/srv/pmiverse/backups/filestore_<prod_db>_pre_migration/
- Optionally start Odoo back if business requires while you transfer copies:
sudo systemctl start odoo
3) Transfer backups to the migration host
rsync -aHAX user@prod:/srv/pmiverse/backups/<prod_db>_pre_migration_*.dump \
/srv/pmiverse/backups/
rsync -aHAX user@prod:/srv/pmiverse/backups/filestore_<prod_db>_pre_migration/ \
/srv/pmiverse/backups/filestore_<prod_db>_pre_migration/
4) Restore the production dump on the migration host and neutralize
- Restore DB into a local database name you will pass to
-d(e.g.,<src>):
createdb <src>
pg_restore -d <src> /srv/pmiverse/backups/<prod_db>_pre_migration_*.dump
-
If add‑ons require filestore present during upgrade, restore it under the migration host’s
data_dirpath (per config) so thatfilestore/<db>aligns with the DB name you restore. -
Before starting servers for checks, neutralize external effects (Odoo shell):
# Odoo shell connected to <src> (or <src>_14 later)
params = env["ir.config_parameter"].sudo()
params.set_param("web.base.url", "http://localhost:18069")
params.set_param("mail.smtp_host", "localhost")
params.set_param("mail.smtp_port", 1025) # mailhog
# Review connectors, acquirers, and crons; disable non‑essential ones
5) Run the migration on the migration host
cd /srv/pmiverse/_pmiconfig/scripts/migrate
./migrate_14-18.sh -d <src>
# Add --force if intermediate targets already exist and can be overwritten
- The script creates
<src>_14(baseline) and upgrades stepwise to<src>_18, producing logs and backups per hop under/srv/pmiverse/logsand/srv/pmiverse/backups.
6) Validate on Odoo 18 locally (UAT smoke test)
- Start Odoo 18 locally against
<src>_18:
source /srv/pmiverse/_pmisuite18/venv/bin/activate
/srv/pmiverse/_pmisuite18/repos/OCB/odoo-bin \
-c /srv/pmiverse/_pmisuite18/config/pmisuite18.conf \
-d <src>_18 --logfile=/srv/pmiverse/logs/odoo18_<src>_18.log
- Validate critical flows, custom modules, and reports. Fix issues, then re‑run with
--forceif necessary.
7) Prepare the production Odoo 18 stack
- Ensure the Odoo 18 stack exists on production: repos, venv,
pmisuite18.conf, systemd unit, nginx/proxy config, ports,proxy_mode = True, and wideaddons_pathmatching the migration host. Keep paths under/srv/pmiversefor parity. - Schedule a change window and stop the old Odoo service before restoring the migrated DB:
sudo systemctl stop odoo
# or: sudo systemctl stop odoo14
8) Transfer the migrated DB and filestore back to production
- On the migration host, back up the final migrated DB:
pg_dump -Fc -d <src>_18 > /srv/pmiverse/backups/<src>_18_migrated_$(date +%Y%m%d_%H%M%S).dump
- Transfer the DB dump and the (migrated) filestore:
rsync -aHAX /srv/pmiverse/backups/<src>_18_migrated_*.dump \
user@prod:/srv/pmiverse/backups/
rsync -aHAX /srv/pmiverse/_pmisuite18/data/filestore/<src>_18/ \
user@prod:/srv/pmiverse/_pmisuite18/data/filestore/<target_db>/
Note: If filestore didn’t change during migration, ensure the prod 18 instance points to the
correct filestore location matching <target_db>.
9) Restore on production and reconfigure for go‑live
- On production, create and restore the target database name (can keep original or use a new one):
createdb <target_db>
pg_restore -d <target_db> /srv/pmiverse/backups/<src>_18_migrated_*.dump
-
Update system parameters for production values (hostnames, mail relays), re‑enable crons and integrations, verify
web.base.url. Review dbfilter/nginx/proxy to route traffic correctly. -
Start Odoo 18 in production and monitor:
sudo systemctl start odoo18
sudo journalctl -u odoo18 -f
10) Post‑go‑live checks and rollback plan
- Verify: user logins, critical flows, scheduled actions, mail in/out, integrations.
- Monitor performance, worker health, and logs. Keep backups ready.
- Rollback plan: stop Odoo 18, restore the last good Odoo 14 DB+filestore backups, start old service.
Checklist summary
- [ ] Back up prod DB + filestore; transfer to migration host
- [ ] Restore locally; neutralize; run migrate_14-18.sh
- [ ] Validate on 18; fix issues
- [ ] Prepare prod 18 stack; stop old service for cutover
- [ ] Transfer migrated DB + filestore; restore on prod
- [ ] Reconfigure; enable crons/integrations; start Odoo 18
- [ ] Post‑go‑live monitoring; rollback plan ready
Logs and backups
- Logs:
/srv/pmiverse/logs/uninstall_pmis_stock_analytics.log(Step 0)/srv/pmiverse/logs/openupgrade_15.log/srv/pmiverse/logs/openupgrade_16.log/srv/pmiverse/logs/openupgrade_17.log-
/srv/pmiverse/logs/openupgrade_18.log -
Backups:
/srv/pmiverse/backups/<db>_<tag>_<timestamp>.dump(format: custom-Fc).
These locations are created if missing. Keep DB and filestore backups together for safety
(filestore per instance under its data_dir).
Safety notes
- The script never modifies your source DB. It clones and works on derived DBs.
- Without
--force, the script aborts if a target DB already exists. - With
--force, existing intermediate DBs are dropped before recreation — use carefully. - Do not edit the shared per‑instance config files for one‑off local tweaks; prefer CLI overrides in IDE run configs as needed.
Troubleshooting
- “Source database '' does not exist”
-
Confirm with
psql -lqt | cut -d '|' -f 1 | grep -w <name>. -
“Missing file: …/odoo-bin” or “Missing upgrade path dir: …/openupgrade_scripts/scripts”
-
Ensure the per‑version repos exist and paths match the layout above.
-
Permission errors for
createdb/dropdb/pg_restore -
Ensure your OS user has rights on the local Postgres cluster or connect as a role with sufficient privileges.
-
Encoding or collation mismatches
-
Create the target DBs with the same encoding/locale as your source cluster. The script uses
createdbdefaults; adjust cluster defaults if required. -
OpenUpgrade failures at a specific hop
- Inspect the corresponding
openupgrade_<ver>.logand apply OCA/OpenUpgrade recommended fixes (addon availability, pre‑migration data cleanup, etc.). Re‑run with--forceonce corrected.
Clean up
If you need to reclaim space after a successful migration, you may drop intermediate DBs, e.g.:
dropdb <src>_14
dropdb <src>_15
dropdb <src>_16
dropdb <src>_17
Only do this after verifying <src>_18 is healthy and backed up.
Related documentation
- Global guidelines:
/srv/pmiverse/_pmiguidelines(PMIverse multi‑version development standards) - OpenUpgrade project: https://github.com/OCA/OpenUpgrade
License and attribution
- Copyright (c) 2025. LUXIM d.o.o., Slovenia — Matjaž Mozetič.
- Internal automation script and docs for PMIverse environment.