Skip to Content

Create an Odoo database

create_database.py creates a new Odoo 18 Community database, configures the built-in administrator, and installs selected modules without demo data. It always includes base and web. Dependencies and auto-installed modules follow Odoo's normal installation rules. Final business setup remains in the Odoo UI.

Prerequisites

Run with the intended Odoo virtualenv as the Odoo service account. Its PostgreSQL role needs CREATEDB and its filesystem account needs access to the configured data directory. The Odoo configuration supplies the PostgreSQL connection, addons_path, and data_dir; this command does not use the shared database alias registry. Defaults target _pmisuite18; override --config and --odoo-root for another Odoo 18 instance. Dependencies must already be installed.

Keep the new database inaccessible to all Odoo services and other writers until creation succeeds, by stopping the relevant service or excluding the target through its database selection. Initialization has intermediate commits and temporarily uses Odoo's initial accounts. This command starts no HTTP server or cron workers, but selected addons can execute installation hooks with external effects. Review and authorize the module selection before execution.

Preview and create

Only the database name is required. With the intended Odoo virtualenv activated:

/srv/pmiverse/_pmiconfig/scripts/create/create_database.py example_new

This uses the built-in administrator (base.user_admin, normally user ID 2) with login admin, installs the module list from the shared config, and generates its password in /srv/pmiverse/_pmiprivate/example_new_init_pass. Supply --admin-login only to override the login. Existing credential files are still refused unless explicitly selected as input with --admin-password-file.

Preview needs only Python's standard library. It reads the shared module defaults when --modules is omitted, but does not load Odoo, read the Odoo configuration or password file, generate/save a password, contact PostgreSQL, or check module availability. It shows the default password output path when no input file is given:

/srv/pmiverse/_pmisuite18/venv/bin/python \
  /srv/pmiverse/_pmiconfig/scripts/create/create_database.py example_new \
  --admin-login admin@example.invalid \
  --company-name 'Example Company' --country SI \
  --modules contacts,sale_management --dry-run

When --modules is omitted, the command reads modules from [create_database] in ../../config/create_database.conf, relative to this checkout regardless of the working directory. The initial list is base,web; edit it to set the shared default modules. For example:

[create_database]
modules = base,web,contacts,sale_management

An explicit --modules contacts replaces the configured list, while --modules '' selects only the mandatory base and web. Both sources use the same validation and deduplication. Missing or malformed defaults stop the command before Odoo loads unless --modules explicitly overrides them. --help does not read defaults. The separate --config option still selects the Odoo runtime configuration; it does not select this shared defaults file.

Remove --dry-run to create the database. Without --admin-password-file, the command generates a cryptographically random password (32 random bytes encoded as URL-safe text) and saves it to /srv/pmiverse/_pmiprivate/<database>_init_pass, for example /srv/pmiverse/_pmiprivate/example_new_init_pass. The filename contains the literal suffix _init_pass, not the password. There is no interactive prompt.

The directory is created with mode 0700 if absent, and the file with mode 0600. An existing directory must be owned by the executing service account and have no group/other permissions; the script does not change its permissions. The account needs permission to create this directory, or an administrator must prepare it separately. Symlink directories and existing output files (including symlinks) are refused. Password persistence completes before database creation; failure to save it stops creation. Only the path is printed, never the password.

To supply your own password instead, use --admin-password-file /secure/path/admin-password: an owner-only regular UTF-8 file owned by the executing account (typically mode 0600). Symlinks are refused; one trailing newline is allowed. This reads the supplied file and creates no default password file. Passwords are never command-line arguments.

Retrieve the saved password as its owning account and hand it to the end user through a secure channel. Manage or remove the file separately after handoff. Generated files are retained on subsequent provisioning failures and may not correspond to a usable account in an incomplete database. Inspect them before retrying; a retry never overwrites them. To intentionally reuse a saved password after resolving the database failure, pass its path with --admin-password-file.

--admin-login defaults to admin; --admin-name defaults to Administrator. An email-shaped login also sets the administrator's email. This updates base.user_admin through the ORM, preserving its normal Odoo permissions and password hashing. It does not change Odoo's database-manager master password (admin_passwd).

--company-name is optional. --country sets the company's country and default currency before installing the selected modules, which matters for fiscal localization. If omitted, Odoo's initial company settings remain. The initial language is US English; additional languages and user preferences can be set in the UI. No jurisdiction, tax configuration, outbound mail, or payment provider is inferred.

Handoff and failure handling

Success means the requested modules are installed and the active administrator has Settings access. Ensure the runtime service uses the same checkout, addon paths, database connection, and data directory, and permits the new name through db_name/dbfilter. Start or enable the service, then open /web/login?db=example_new on its normal URL. Complete company/legal details, localization and taxes, users/access, application settings, and integrations. Review the initial currency and fiscal localization before recording transactions.

Existing databases or filestore paths, including dangling symlinks, are refused. There is no overwrite, resume, drop, or automatic rollback mode. A failure exits nonzero and retains any partially created database and filestore for inspection; keep them offline. A second invocation refuses the retained target. Clean it up only after inspection and separate authorization, or choose a fresh name. Creation uses Odoo's PostgreSQL creation routine and template0; a concurrent database creation is rejected by PostgreSQL and is never adopted.

--help lists the full interface. Shared Bash completion includes options and file paths but does not suggest existing database names for the new target. Editing this repository installs no shortcut or service and creates no database.

Development validation

The implementation guide explains the shared helpers, configuration precedence, initialization phases, failure boundaries, and a focused test command. This module also supplies password I/O and offline runtime loading to administrator recovery; changes to those helpers must preserve both workflows.

tests/test_create_database.py uses synthetic Odoo/ORM doubles and private temporary files. It exercises creation order, administrator setup, module-state verification, collision refusal, password handling, and retained partial failure. tests/test_script_cli.py -k create_database checks help and completion in its isolated sandbox. These checks do not replace an explicitly authorized disposable Odoo/PostgreSQL integration run.