Install the server
This takes a fresh Linux host to a working Antelao server with the management API and Web UI
running. Everything here is run on that host, as root.
Requirements
| Operating system | Debian 10, 11 or 12, or Ubuntu 20.04, 22.04 or 24.04, 64-bit |
| Privileges | Root. odoocli refuses to run unelevated |
| Docker | Install it yourself, or let server install install it along with the other prerequisites |
| DNS | A name that resolves to the server's public address. A wildcard such as *.odoo.example.com lets instances enrol themselves |
| Firewall | Inbound TCP 80 and 443 reachable from the internet, if you want publicly trusted certificates |
Windows and macOS are not supported as hosts.
The Web UI (5220), the API (5210), Portainer (9000 and 9443) and pgAdmin (8081) listen on the host directly. Only the instances themselves are proxied. Restrict these ports with a firewall or reach them over a VPN.
1. Install odoocli
From the Antelao APT repository:
# apt-get update && apt-get install -y odoocliOr from a package you downloaded:
# dpkg -i odoocli_1.0.0_amd64.debThe payload lands in /opt/odoocli with a launcher at /usr/local/bin/odoocli. Check it:
# odoocli --version2. Describe the server
Nothing can be installed until odoo.json describes a real server. The first run scaffolds a
placeholder, and server install deliberately refuses to install against it.
# odoocli server config create --preset productionThe production preset runs an interactive wizard. Have these answers ready:
| Section | What it asks for |
|---|---|
| General | Hostname (required, must resolve to this server), description, auto-enrolment wildcard such as *.odoo.example.com, trusted proxies, and whether instance configuration lives in JSON files or the master database |
| Paths | Instance root (/var/lib/odoo/instances), backup and archive directories, and a temp directory for I/O-heavy work |
| Remote PostgreSQL | Answer no to use the bundled odoo-postgres container, which is the normal case |
| SMTP | Host, port, credentials and the from address. Skipping it means no Postfix relay is installed; installation still succeeds with a warning |
| Fail2Ban | Whitelist, blacklist, ban duration, search window, retry count and notification recipients. The wizard offers to whitelist your current public address so you cannot lock yourself out |
For a throwaway development host, skip the wizard entirely. The development preset uses
localhost and asks nothing:
# odoocli server config create --preset development3. Install the server
# odoocli server installThis is idempotent, so it is also the repair command: re-run it after any configuration change. It
installs the OS prerequisites and Docker, creates the Docker networks, brings up Portainer,
PostgreSQL and pgAdmin, creates the master database, installs Postfix, nginx and Fail2Ban, and
finally starts the odoo-api and odoo-web containers with a freshly generated shared API key.
Add --force to recreate containers that already match their expected configuration.
Check the result:
# odoocli server infoserver info masks credentials. Add --show-secrets to reveal them, which is how you read the
management API key for remote use.
4. Create the first administrator
Open https://<your-server>:5220/.
The Web UI serves HTTPS with a self-signed certificate that server install issues for the
server's hostname, so your browser warns on the first visit. Accept the exception once. This is not
cosmetic: passkeys only work in a secure context, and plain HTTP is not one.
Reach the UI by name, not by address. A passkey's relying-party id must be a domain, and the certificate carries DNS names only.
While no accounts exist you are redirected to /setup, which creates the first account with the
Administrator role. That account is protected: it cannot later be deleted, disabled or demoted.
Choose a password of at least 12 characters, and set up TOTP now if you can. Once an account
exists, /setup redirects to the sign-in page.
5. Create your first instance
In the Web UI, Instances → New instance runs a five-step wizard: basics, tuning, Git addons, modules, then install. On the command line the same thing is a short sequence:
# odoocli instance config create# odoocli instance install --instance acme# odoocli instance database init --instance acme-i, --instance accepts an id, a name, an HTTP port or a description. Omit it and the CLI shows a
picker.
An unlicensed server hosts one instance with one database, which is enough to work through this manual. Creating a second one asks for a licence:
Where the state lives
Everything Antelao knows is in the master database plus the application root at
/root/.local/share/odoocli/:
/root/.local/share/odoocli/
├── conf/ odoo.json (server configuration), appsettings.json (master database provider)
├── data/ container data trees, secrets, the SQLite master database
├── logs/ odoo-cli-*.log, odoo-audit-*.log, action logs
└── license/ *.lic licence files
Back up that directory and the master database together. Neither is much use without the other.
Administering it from your own machine
odoocli is remote-first: once an endpoint is configured, commands run against the API rather than
locally, and --local forces local execution. Install the CLI anywhere and store a connection once:
# odoocli connection add --name prod-1 --url https://odoo.example.com:5210The API key is prompted for and masked when you leave --api-key out, which keeps it out of your
shell history. Read it from the server with odoocli server info --show-secrets.
prod-1# odoocli instance list --server prod-1--server accepts either a stored connection name or a base URL. Without it, the default stored
connection is used, or the ODOO_API_URL and ODOO_API_KEY environment variables.
Every state-changing remote command enqueues a background job and streams its log until it finishes. A handful of commands have no remote form, because they build or repair the very thing a remote call would travel over. Those are marked Local only throughout the command reference.