Skip to main content

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 systemDebian 10, 11 or 12, or Ubuntu 20.04, 22.04 or 24.04, 64-bit
PrivilegesRoot. odoocli refuses to run unelevated
DockerInstall it yourself, or let server install install it along with the other prerequisites
DNSA name that resolves to the server's public address. A wildcard such as *.odoo.example.com lets instances enrol themselves
FirewallInbound TCP 80 and 443 reachable from the internet, if you want publicly trusted certificates

Windows and macOS are not supported as hosts.

The management ports are not behind the managed nginx

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:

Local only
# apt-get update && apt-get install -y odoocli

Or from a package you downloaded:

Local only
# dpkg -i odoocli_1.0.0_amd64.deb

The payload lands in /opt/odoocli with a launcher at /usr/local/bin/odoocli. Check it:

Local only
# odoocli --version

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

Local only
# odoocli server config create --preset production

The production preset runs an interactive wizard. Have these answers ready:

SectionWhat it asks for
GeneralHostname (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
PathsInstance root (/var/lib/odoo/instances), backup and archive directories, and a temp directory for I/O-heavy work
Remote PostgreSQLAnswer no to use the bundled odoo-postgres container, which is the normal case
SMTPHost, port, credentials and the from address. Skipping it means no Postfix relay is installed; installation still succeeds with a warning
Fail2BanWhitelist, 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:

Local only
# odoocli server config create --preset development

3. Install the server

Local only
# odoocli server install

This 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:

Local only
# odoocli server info

server 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:

Local only
# odoocli instance config create
Local only
# odoocli instance install --instance acme
Local only
# 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:

Local only
# odoocli connection add --name prod-1 --url https://odoo.example.com:5210

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

Remote or localagainst 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.