Skip to content

Rollback model

Omisen edited this page Aug 16, 2026 · 3 revisions

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.)


The promise

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 apt halfway 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, and sudo invok rollback cleans it up.

How it works, briefly

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.

The three guarantees about pre-existing resources

1. It does not destroy data that was already there

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.

2. It does not write inside data that was already there

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.

3. It does not alter your files without being able to restore them

Your ~/.bashrc with 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.

Other examples of “left as it was”

  • PostgreSQL already installed on the machine → it stays installed (the installer only stops/disables it if it had started it; with --aggressive-rollback it removes it only if the cluster hosts no other databases).
  • /opt/odoo already present → it is not removed.
  • System packages you already had → they are not uninstalled (only the ones the installer added).

The manifest: what is still on the system

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, rollback to remove it, --force to 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.

More than one instance: what belongs to whom

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/odoo and 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 rollback command. 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.

Seeing it first: --dry-run

sudo invok --config customer.env --dry-run

It 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.

Clone this wiki locally