Skip to main content

Configuration files

Where they live

/root/.local/share/odoocli/
├── conf/
│ ├── odoo.json the server configuration
│ └── appsettings.json which master-database provider to use
├── data/ container data trees, secrets, the SQLite master database
├── logs/ CLI logs and the audit trail
└── license/ *.lic files, install-id, checkin.receipt, checkin-state.json
odoo.json is read once, at API startup

Editing it while the API is running changes nothing until you restart odoo-api. Worse, nginx and Fail2Ban configuration regenerated in the meantime uses the values the API still holds, so the file on disk and the behaviour on the wire disagree with no error anywhere.

Change it with odoocli server config edit and re-run odoocli server install, or restart odoo-api afterwards.

odoo.json

Written by odoocli server config create and edited by odoocli server config edit. Hand-editing is possible and occasionally necessary, but the wizard is the supported path.

/root/.local/share/odoocli/conf/odoo.json
{
"id": "6f1c2b90-6a1e-4a5f-9c1a-7a0f2b3c4d5e",
"hostname": "odoo.example.com",
"description": "Primary production host, Frankfurt",
"autoEnrollmentFqdn": "*.odoo.example.com",

"trustedProxies": ["203.0.113.8", "198.51.100.0/24"],

"instanceConfigSource": "Database",

"directoryRoot": "/var/lib/odoo",
"directoryInstanceRoot": "/var/lib/odoo/instances",
"directoryBackup": "/var/backups/odoo",
"directoryArchive": "/var/lib/odoo/archive",
"directoryHostTemp": null,

"management": {
"apiPort": 5210,
"apiBindAddress": "0.0.0.0",
"webPort": 5220,
"webBindAddress": "0.0.0.0",
"webHttps": true
},

"docker": {
"registry": "registry.antelao.io",
"username": null,
"password": null
},

"maxConcurrentJobs": 1,
"keepImageVersions": 3,
"postgresMajorVersion": "17",
"licenseExpiryWarningDays": 30,

"apiKey": "<40-character key, generated by server install>",

"smtpProfile": {
"host": "smtp.example.com",
"port": 587,
"username": "odoo@example.com",
"password": "<secret>",
"from": "odoo@example.com"
},

"fail2BanOptions": {
"whitelist": ["203.0.113.8"],
"blacklist": [],
"banTimeMinutes": 60,
"findTimeMinutes": 10,
"maxRetry": 5,
"notify": ["ops@example.com"]
}
}

The members worth understanding

MemberNotes
hostnameMust resolve to this server. Used for the console's own certificate
autoEnrollmentFqdnA wildcard such as *.odoo.example.com. Instances under it need no DNS work of their own
trustedProxiesAddresses or CIDR ranges of a reverse proxy in front of nginx. Leave empty when nginx is the public edge. Getting this wrong makes Fail2Ban ban the wrong address, silently. See Fail2Ban
instanceConfigSourceDatabase (default) or Json. Where instance configuration is stored
directoryBackupPut this on separate storage if you can. The default keeps backups on the same disk as the data they protect
maxConcurrentJobsDefault 1, meaning serial. Raising it helps a server with many instances doing independent work; it does not speed up one instance. See Jobs
keepImageVersionsHow many built images per instance to keep before cleanup removes older ones
licenseExpiryWarningDaysDefault 30. 0 turns the warning off, including the daily e-mail
apiKeyThe management API key. server install generates it; server apikey rotate replaces it

Secrets in this file are real secrets. It lives under a root-only directory; keep it that way, and remember that a copy of it is a copy of your API key and SMTP password.

appsettings.json

Selects the master-database provider. The CLI and the API both read it.

/root/.local/share/odoocli/conf/appsettings.json
{
"Connection": {
"Default": "SQLite"
}
}

Default is SQLite, PostgreSQL or SqlServer.

Local only
# odoocli system database provider
Local only
# odoocli system database migrate --from SQLite --to PostgreSQL
Switching the provider does not move your data

Migrate first, then switch, then restart odoo-api so it picks up the new file. Switching without migrating points the product at an empty database.

SQL Server is always an external server, and its connection string must be complete. It must never target the engine's own master database: the application database merely happens to share that name on the PostgreSQL container.

.env, for the compose deployment

Only relevant if you run the API and Web UI from docker-compose.yml rather than through server install, which is the development and build-your-own-images path.

.env
# Copy from .env.example. Never commit this file.
# The same value is the API's key (Api:Keys:ui) and the UI's client key (OdooApi:ApiKey).
ODOO_API_KEY=change-me-to-a-long-random-string

Generate a strong value:

Local only
openssl rand -base64 48

Compose refuses to start if ODOO_API_KEY is unset. Both services use host networking and bind-mount the host's Docker socket and data trees at identical paths, because the domain layer writes host paths into the configurations it generates. Changing the mount paths breaks that.

Environment variables

VariableUsed byPurpose
ODOO_API_URLodoocliDefault management API endpoint for remote mode
ODOO_API_KEYodoocli, composeThe management API key
Api__Keys__uiodoo-apiThe API's accepted key, injected by the installer
OdooApi__ApiKeyodoo-webThe key the console presents

Global CLI options

Available on every command:

OptionMeaning
-v, --verbosity <level>Log verbosity for this invocation
-f, --forceRecreate or overwrite instead of reusing what exists
-y, --yesAnswer confirmations with yes, for unattended use
--show-secretsPrint credentials unmasked instead of ****
--server <name|url>Run against a stored connection or a management API URL
--token <key>The API key for remote mode
--localForce local execution even when an endpoint is configured
--error-action <action>How errors are handled