-
Notifications
You must be signed in to change notification settings - Fork 0
Rollback model
The feature that sets this installer apart, explained without jargon: what happens when something goes wrong, and why the things you already had on the system stay safe.
(For the engine's technical detail: 0. Engine and 3. Rollback e2e + hardening.)
Either the installation succeeds completely, or the system goes back to exactly what it was.
No dirty intermediate states. If step 12 fails, steps 1–11 are undone, one at a time, in reverse order.
The rollback comes in three forms, with the same rules:
| When | What happens |
|---|---|
| A step fails | the installer walks itself back, immediately — the failing step included: a run that stops halfway has usually already created something, and leaving it out would leave that on disk |
You press Ctrl-C (or a SIGTERM arrives) |
the same: the installation undoes itself and the system returns to what it was. You have nothing to run |
The process is killed (kill -9, power cut) |
there is no time to clean up — but the state is on disk: sudo invok rollback undoes what had been done, even days later |
The same command also uninstalls a working instance: that is precisely why the manifest stays on disk after a successful installation. With more than one instance installed it lists them and stops rather than guess which one you meant — see below.
Ctrl-C, in detail. It takes effect between one step and the next: the one in progress is carried to completion. That is not a limitation being hidden — stopping an
apthalfway would leave the package manager inconsistent, and truncating a database initialisation would leave something worse than what you were trying to avoid. A second Ctrl-C exits at once: there the system stays half-done by your choice, andsudo invok rollbackcleans it up.
Before changing anything, every step notes down whether what it is about to create already existed:
- if it did not exist → the step created it → on rollback it removes it;
- if it did exist → it is not ours → it is not touched, neither during the installation nor during the rollback.
That single distinction — “did I create this?” — is what protects your things.
Already have a database called
odoo? It is not touched.
If a database with the same name already exists, the installer never deletes it during a rollback: it might hold real data. Only databases it created itself are removed.
The same goes for attachments: the filestore (the files uploaded into Odoo) of a pre-existing database is not removed. The directory is created by the installer, but the data inside is yours — and deleting requires both conditions, our directory and our database.
Database already there but empty? The installer stops instead of writing into it.
Initialising the Odoo schema inside a pre-existing database cannot be undone cleanly, so the installer refuses to do it: it stops with a clear message and asks you to use a different name, or an empty database it created itself. This is the one “protection that blocks”, and it is intentional.
The message also brings up the most frequent case: that database may be the leftover of an earlier
interrupted installation of yours, not a production DB. If the leftover came from an installation
this tool registered, sudo invok rollback removes it — that is what the manifest is for. Otherwise
drop it by hand (sudo -u postgres dropdb <name>) or pick a different name.
Your
~/.bashrcwith your aliases? It comes back byte for byte.
The installer appends a single line to your .bashrc (for the odoo command), after taking a backup.
On rollback it restores the original: your aliases and functions are left intact, without scars.
-
PostgreSQL already installed on the machine → it stays installed (the installer only
stops/disables it if it had started it; with
--aggressive-rollbackit removes it only if the cluster hosts no other databases). -
/opt/odooalready present → it is not removed. - System packages you already had → they are not uninstalled (only the ones the installer added).
All of this rests on one file, /var/lib/invok/state.json, which records for each step whether the
artifact was already there or we created it. It is the only thing that makes an instance
uninstallable months later: without it, a rollback would have to guess the names — and guessing here
means risking dropping a database we did not create.
Two rules follow from that:
- the manifest says what is still there, not what was done. When a step is undone, its record disappears: if it stayed, a re-run would skip it believing it done, and the installation would continue on artifacts that no longer exist. If the undo fails, however, the record stays — it is the only trace of the leftover to retry;
-
it is never silently overwritten. Re-running the installer on an already-installed instance stops
on purpose: going ahead would rewrite the manifest with everything marked “pre-existing”, and from
there the instance could no longer be removed automatically. The message names the three ways on —
--instance <name> --port <free port>to add a second installation beside this one,rollbackto remove it,--forceto install over it (which archives the previous manifest instead of deleting it).
It lives outside /opt/odoo, like the log and the lock: that directory is the perimeter the
rollback must be able to remove whole, and a file inside would keep it occupied at the very last step.
One manifest per instance, so each is undone on its own. But some artifacts are shared by
construction — /opt/odoo, the system packages, the PostgreSQL cluster, wkhtmltopdf, the nginx
installation and its firewall rule — and they belong to whichever instance created them. Removing
that instance while another is running would take the ground out from under it.
So the rollback asks one more question before each undo: is another manifest still using this? The count is derived from the manifests, never kept in a second register that could drift.
-
shared, and somebody else is installed → the undo does not run, and the report says
Shared with the instances still installed (…): left in place; -
partly shared — the step that owns both
/opt/odooand this instance's own home — → it does its own half and leaves the rest; - its own → removed, exactly as always.
The instance's manifest is then kept, holding only the shared records: a tombstone, the record
of who owns what the others are standing on. invok list shows it as shared only, and the last
removal can still take those artifacts away.
Since 3.2.0 the same rule governs the rollback that runs when an installation fails halfway, and not only the
rollbackcommand. It matters in one narrow case, and only there: an instance that created the shared artifacts is interrupted, a second instance is installed beside it, and the first is then resumed and fails. Everywhere else the question does not arise — an instance added to a machine that already has one finds those artifacts pre-existing, so its undos are no-ops anyway. There the ownership record is truthful, which is exactly why it alone protected nothing: the failing installation would have removed/opt/odoo, the packages and the cluster from under a running instance.Two rollbacks with different opinions about what is safe to remove would be a difference nobody can see until it costs somebody an instance.
sudo invok rollback --instance cliente-x # that one, and only it
sudo invok rollback --all # every instance, in the right order--all runs two passes — each instance's own artifacts first, then what they had in common — and
that ordering is the reason it exists as a flag rather than a loop you write yourself: otherwise the
last userdel would depend on the order a directory happens to be read in.
One detail worth knowing, because it touches a directory you may have chosen the permissions of: a
named instance whose user cannot walk through /opt/odoo — the case when the historical instance
owns it as 0750 — has that directory widened by exactly one bit (o+x: walk through, still not
list). It is recorded like any other artifact, and put back when no named instance needs it any more.
sudo invok --config customer.env --dry-runIt shows the complete plan — what it would create and what is already there — without changing anything. It is how you look at what it will do before letting it do it.
It runs without sudo too, but then the plan is incomplete: some steps have to interrogate the
system (PostgreSQL state, installed packages) and without privileges they get no answer. The installer
says so before printing it.
This is not just an intention: it is a verified property, checked by end-to-end tests that inject a failure and assert that the state comes back identical to the initial one, with pre-existing resources intact. Detail: 3. Rollback e2e + hardening.
Start here
Key concepts
References
For developers
Technical detail — how it works inside
Steps:
- 1.1 PrepareOptRoot
- 1.2 CreateOdooUser
- 1.3 SetupLogDir
- 1.3b SetupCacheDir
- 1.4 AptPackages (delta)
- 1.5 InstallWkhtmltopdf
- 1.6 SetupPostgres
- 1.7 CreateDbRole
- 1.8 CreateDatabase
- 1.9 CloneOdooRepo
- 1.10 CreateVirtualenv
- 1.11 InstallPythonRequirements
- 1.12 GenerateConfig
- 1.12b SetupDataDir
- 1.13 InitializeOdooDatabase
- 1.14 SetupSystemd
- 1.15 Nginx (6 sub-steps)
- 1.16 WriteControlScript + PatchBashrc
Cross-cutting: