Git-backed addons
Custom modules come from Git repositories rather than being copied onto the server. An instance lists the repositories it uses, and Antelao clones them into the instance's addons tree.
Adding a repository
In the console, the instance's Modules tab, on its Configuration sub-tab. In the New instance wizard, switch on Custom modules / add-ons on the Advanced tab: the providers and repositories you enter there are added with Create, before the instance is installed, so the installation clones them. Each repository needs its URL, the branch or tag to track, and credentials if it is private.
Credentials are stored as secrets: they are write-only through the API, never returned by a read, and never written into a job payload or log.
Which platforms a provider may sit on
GitHub and GitLab. A provider on either has its modules cloned and pinned from there, the automatic update polls it, and a workstation can create a repository on it.
Bitbucket, Azure DevOps and a custom host are refused, with a message saying so rather than failing at the first fetch.
Providers and workspaces have an order you set
Every provider card except the builtin one carries a drag handle, and the order is saved like any other configuration change. The builtin provider always sits last.
Inside a provider, each workspace is a card with a drag handle of its own: drag it to put the provider's workspaces in the order you want, and they stay in that order through every save and update.
Cards arrive collapsed, so a page holding several providers opens as a list rather than as a wall of forms. The first provider opens, and inside each provider the first workspace opens; the Credentials section starts collapsed, with the number of credentials in its heading.
Revisions are pinned, not floating
When a module is added or updated, the job fetches immediately and records the exact commit it retrieved. The instance's configuration then names that commit rather than a branch tip.
This is the difference between "we run branch main" and "we run a1b2c3d". Only the second one
lets you say what is deployed, reproduce it later, or notice that a rebuild changed something.
On the Modules tab, each repository's Local column shows the commit it is pinned to and its Remote column the head of its branch as the server last read it, so what has moved upstream since is visible at a glance.
Updating
Updating a module is an explicit action that fetches, re-pins and rebuilds. It is a job like any other, so it queues, logs and can fail visibly rather than silently leaving a half-updated tree.
On a development instance a module's checkout is on its series branch (for example 20.0)
rather than on a detached commit, and an update moves that branch to the new commit and checks it
out, as git pull --ff-only would. The update is refused while the
code editor holds work that exists nowhere else: uncommitted changes, or
commits on the branch that are not on the remote. The refusal names the checkout; commit and push the
work, then update again.
To throw that work away instead, run the update on the server itself, as root, with
--discard-changes. Neither the console nor a command over a connection can pass it:
sudo ohm instance modules install --instance fanes --modules sale_custom --latest --discard-changes --local
Automatic git updates follow the remotes instead: the server polls them, moves the modules to their branch heads and restarts the instance on its own. An update that cannot fetch a module does not record the new commit for it. The Test and Staging presets switch automatic updates on, but never without being asked: see Presets.
pelmo$ ohm instance modules auto-update show --instance fanesGit lock files left behind by an interrupted update are cleared once they are more than 30 minutes old, so a module update is not blocked by them for long.
A module above the license's custom module limit is frozen: it stays loaded, but it is not pulled or updated, by hand or by automatic updates, until a license allows it again. Automatic updates from git stop altogether when the license no longer carries them, and resume by themselves. The instance's Modules tab says which. See When the license changes.
Odoo's own code
The builtin provider holds two rows that are not add-ons: odoo and enterprise. They cannot be
enabled, disabled, copied or deleted, and no module run touches them.
odoo is Odoo Community, and it comes from the instance's image. Its Commit column shows the Odoo build the running image carries and its Head column the newest build available, as the daily update check last read them; before that check has run, it shows the build the configuration asks for. It takes no commit, so it has no Edit: change the Odoo build on the Docker image card of the instance's Configuration tab, which rebuilds the image.
After the image's Odoo build has changed, Upgrade base on the odoo row upgrades the base
module - and with it every installed module - in every database of the instance, then restarts the
instance. A confirmation names the databases first; the upgrade can take minutes per database.
enterprise is a checkout the instance fetches, pinned to a commit like an add-on. On an Enterprise instance its row offers:
- Read the remote - reads the head of the instance's branch and fills the Head column, moving nothing.
- Update to latest - fetches the head and records its commit. Nothing restarts, so the instance runs the code it loaded until it does.
- Update and upgrade - fetches the head, restarts the instance when that changed the code, and
upgrades
basein every database that runs Enterprise. - Edit - pins a commit, or clears it to take the head. Saving fetches it straight away, without a restart.
Update Odoo add-ons, in the toolbar of the Modules tab, puts the Enterprise add-ons where the
configuration says: on an Enterprise instance it fetches them at the recorded commit, or at the head
of the instance's branch with Fetch the newest commit switched on, and records the commit; on any
other instance it removes them. Nothing restarts. It is the same as ohm instance odoo install, and
what repairs an Enterprise checkout that is missing or damaged.
Enterprise and Community move in step. An Enterprise head much newer than the Odoo build in the image can need Community code the image does not have yet. The confirmation says how old the image's build is; if the instance fails after an update, build the image on a newer Odoo build or pin Enterprise back.
Modules
pelmo$ ohm instance modules select --instance fanespelmo$ ohm instance modules install --instance fanesSelecting decides which modules the instance carries. Installing is the Odoo-level action of installing them into a database.
In Odoo, disabling a module is not a lighter version of uninstalling it. Both can remove data that belongs to that module, and neither is reversible by re-enabling. Back the database up first.
Clones are shallow
A repository is cloned with only the history it needs, so a large addons repository does not cost a full clone on every rebuild.
Odoo version and addons paths
Odoo 16.0 and earlier reject an empty addons path, while 17.0 and later tolerate it. A fresh instance on 15.0 or 16.0 therefore omits the addons path entirely until a module exists, rather than passing an empty one and failing to initialise a database.
You do not need to do anything about this. The configuration looks different between versions, and that is not a fault.