Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ jobs:
- name: Verify what reaches root or a superuser (certificates, downloads, venvs, neutralisation)
run: python tools/verify_privilege.py

- name: Verify the PostgreSQL install steps (port, scram, listen_addresses, pg_hba)
run: python tools/verify_postgres_setup.py

- name: Verify nginx and fail2ban accept the generated configuration
run: |
sudo apt-get update -qq
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ All notable changes to this project are documented here. The format is based on
with the host `python3` only when it can build the version, else with a CPython installed by uv (pinned,
SHA-256-checked) into `/opt/odoo-python`. setuptools is pinned per version (`<58` up to 13, `<81` up to 16) and
Odoo 12's `pyldap` is replaced. Before, Odoo 14 did not install on Ubuntu 24.04 (its requirements stop at
Python 3.10) and Odoo 15–16 did not start there (setuptools 81 removed the `pkg_resources` they import).
Python 3.10) and Odoo 15–16 did not start there (setuptools 82 removed the `pkg_resources` they import).
- **OCB.** The install asks for the core — official Odoo or OCA's OCB; a replica runs the source's core.
- New instances get `without_demo = all` (Odoo ≤ 18) and `data_dir = /var/lib/odoo/<instance>`, outside the
home. The PostgreSQL floor of the Odoo version is checked when PostgreSQL is installed.
Expand Down Expand Up @@ -43,6 +43,25 @@ All notable changes to this project are documented here. The format is based on

### Fixed

- **Installs that failed on supported hosts.**
- **Python.** Odoo 15 on Debian 12 (Python 3.11) and Odoo 14 on a host Python 3.10 hit the `gevent==21.8.0` pin,
which has no wheel there and no longer builds; they now get uv's interpreter.
- **PostgreSQL 13** (Debian 11) stored the role's password as md5, which the scram `pg_hba` rule refuses.
- **nginx.** The first HTTPS install on Ubuntu 22.04 and Debian 11 wrote `proxy_cookie_flags` for an nginx that
was not installed yet (1.18 rejects it).
- **An existing database role** kept its old password while `odoo.conf` got the new one; the install now asks
which password to use.
- **arm64** got the amd64 wkhtmltopdf package.
- **Corrected facts.** Odoo 16's Python maximum is 3.12, as `odoo/__init__.py` states, not 3.13: Debian 13's
3.13 now gets uv's 3.12. Odoo 15–18 state their range outright (official, not derived). setuptools removed
`pkg_resources` in 82.
- **Update configuration** keeps `odoo.conf`'s other sections and multi-line values, and writes each key once.
Before, a key written in two cases made the file unreadable for Odoo.
- **PostgreSQL steps.**
- Local commands use the instance's port.
- Remote access survives a distribution's `conf.d` and restarts PostgreSQL only when needed.
- uv is always the pinned one.

- **A neutralised copy could still reach the outside.**
- Several rules named columns some versions lack, so they were skipped silently and left those copies in
production:
Expand Down
10 changes: 8 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ python3 tools/verify_neutralisation.py --odoo 18=/path/venv/bin/python:/path/odo
python3 tools/verify_ops_configs.py # nginx -t and fail2ban on the generated config
python3 tools/verify_secrets.py # secrets in no process argument, preview or error
python3 tools/verify_privilege.py # certificates, downloads, venv replication, neutralisation as owner
python3 tools/verify_postgres_setup.py # PostgreSQL install steps: port, scram, listen_addresses, pg_hba
```

`tools/verify_data_safety.py`, `tools/verify_secrets.py`, `tools/verify_privilege.py` and
`tools/verify_ops_configs.py` also run in CI.
`tools/verify_data_safety.py`, `tools/verify_secrets.py`, `tools/verify_privilege.py`,
`tools/verify_postgres_setup.py` and `tools/verify_ops_configs.py` also run in CI.
`tools/verify_data_safety.py` executes the generated scheduled-backup script, the
retention prune and the delete step against stub binaries, and the template copy, forced drop and purge
discovery against a PostgreSQL cluster of its own (it needs `initdb` and refuses to run as root). Run it after
Expand All @@ -69,6 +70,11 @@ against stubs, and the neutralisation as the copy's owner against a PostgreSQL c
trigger in the copy tries to make its owner a superuser. Run it after changing those planners or
`_post_db_mode_commands`.

`tools/verify_postgres_setup.py` runs the PostgreSQL steps of an install against a cluster of its own on a port
other than 5432, storing md5 by default as PostgreSQL 13 does and with a `conf.d` file, and checks the role's
scram password, `listen_addresses` set with one restart, and the `pg_hba` rule added once. Run it after changing
those planners.

`tools/verify_install_runtime.py` is not part of CI: it downloads the pinned uv (and refuses a wrong
checksum), installs the interpreter the matrix picks, builds a real venv for each Odoo checkout you pass and
starts `odoo-bin --version`; for Odoo <= 16 it also shows the unpinned setuptools breaks it. It needs network
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ the whole configuration; otherwise the previous vhost and links are put back, so
enabled to stop nginx (and every instance) at its next restart.

The vhosts accept uploads up to 2 GB and compress with gzip. The HTTPS vhost follows Odoo's deployment guide:
TLS 1.2/1.3 with its cipher list, HSTS, and the `session_id` cookie marked `secure` (nginx ≥ 1.19.8).
TLS 1.2/1.3 with its cipher list, HSTS, and the `session_id` cookie marked `secure` (nginx ≥ 1.19.3).

For HTTPS you pick a certificate strategy:

Expand Down
24 changes: 14 additions & 10 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,35 @@ assuming a single stack:
| OS family | Debian/Ubuntu (**apt**) | Package steps target apt. A non-apt OS is detected and warned, not driven blindly. |
| Ubuntu | 22.04 (jammy), 24.04 (noble) | Validated primary targets. Newer releases work; the wkhtmltopdf table maps noble → the jammy build. |
| Debian | 11 (bullseye), 12 (bookworm) | wkhtmltopdf assets pinned for both. |
| nginx | 1.18 → 1.25+ | HTTP/2 directive form chosen by detected version; `proxy_cookie_flags` written from 1.19.8. `tools/verify_ops_configs.py` runs `nginx -t` on the generated vhosts with the nginx the host distribution ships (1.24 on Ubuntu 24.04). |
| nginx | 1.18 → 1.25+ | HTTP/2 directive form chosen by detected version; `proxy_cookie_flags` written from 1.19.3. The version is the installed nginx's, or the one apt would install when the plan installs it; when neither is known the vhost is written for an older nginx. `tools/verify_ops_configs.py` runs `nginx -t` on the generated vhosts with the nginx the host distribution ships (1.24 on Ubuntu 24.04). |
| PostgreSQL | 13+ | Local drops use `dropdb --force` (13+); Odoo's own floor per version is below. Every supported Ubuntu/Debian ships 13 or newer. |
| Odoo Community | 12 → 19 | Per-version interpreter, setuptools, config keys — see the table below. Official Odoo or OCB. |
| wkhtmltopdf | 0.12.6.1-3 (patched) | jammy/noble, bookworm, bullseye assets, each SHA-256-pinned; other codenames use the distro package or skip. |
| CPU architecture | x86_64 (amd64), aarch64 | The pinned uv exists for both; an Odoo version that needs uv's Python cannot be installed on another architecture. The patched wkhtmltopdf assets are amd64 only (use the distro package elsewhere). |
| CPU architecture | x86_64 (amd64), aarch64 | The pinned uv exists for both; an Odoo version that needs uv's Python cannot be installed on another architecture. The patched wkhtmltopdf has amd64 and arm64 builds for Ubuntu 22.04/24.04 and Debian 11/12; elsewhere the distribution package is offered when it has one. |

## Odoo versions

Python ranges are those Odoo declares; a maximum marked *derived* is the newest interpreter bucket the branch's
`requirements.txt` declares (only Odoo 19 states one outright). The fallback interpreter is the one uv installs
Python ranges are those Odoo declares: Odoo 15–19 state their range outright (`MIN_PY_VERSION` /
`MAX_PY_VERSION` in `odoo/__init__.py`, `odoo/release.py` from 19). Odoo 14's maximum is *derived*: the newest
interpreter bucket its `requirements.txt` declares. The fallback interpreter is the one uv installs
when the host's cannot build the version. The facts are declared once, in `instance_manager/support.py`;
`tools/verify_install_runtime.py` builds a venv for a given Odoo checkout with them and starts it.

| Odoo | Python | Fallback (uv) | setuptools | PostgreSQL floor | Notes |
|------|--------|---------------|------------|------------------|-------|
| 12 | 3.5 – no maximum stated | 3.8 | `<58` | not stated | host used only up to 3.8; `pyldap` → `python-ldap==3.1.0` |
| 13 | 3.6 – no maximum stated | 3.8 | `<58` | not stated | host used only up to 3.8 |
| 14 | 3.7 – 3.10 (derived) | 3.8 | `<81` | 12 | |
| 15 | 3.7 – 3.12 (derived) | 3.12 | `<81` | 12 | |
| 16 | 3.7 – 3.13 (derived) | 3.12 | `<81` | 12 | never a host 3.10 (gevent pin) |
| 17 | 3.10 – 3.14 (derived) | 3.12 | current | 12 | never a host 3.10 (gevent pin) |
| 18 | 3.10 – 3.14 (derived) | 3.12 | current | 12 | never a host 3.10 (gevent pin) |
| 14 | 3.7 – 3.10 (derived) | 3.8 | `<81` | 12 | never a host 3.10 (gevent pin) |
| 15 | 3.7 – 3.12 (official) | 3.12 | `<81` | 12 | never a host 3.10 or 3.11 (gevent pin) |
| 16 | 3.7 – 3.12 (official) | 3.12 | `<81` | 12 | never a host 3.10 (gevent pin) |
| 17 | 3.10 – 3.14 (official) | 3.12 | current | 12 | never a host 3.10 (gevent pin) |
| 18 | 3.10 – 3.14 (official) | 3.12 | current | 12 | never a host 3.10 (gevent pin) |
| 19 | 3.10 – 3.14 (official) | 3.12 | current | 13 | demo data off by default in Odoo itself |

On Ubuntu 24.04 (Python 3.12) the host interpreter builds Odoo 15–19; Odoo 12–14 get uv's 3.8.
On Ubuntu 24.04 (Python 3.12) the host interpreter builds Odoo 15–19; Odoo 12–14 get uv's 3.8. The gevent pin is
the `gevent==21.8.0` row of each branch's `requirements.txt`: that release has no wheel for those interpreters and
its source no longer builds, so uv's interpreter is used instead. `setuptools<81` keeps `pkg_resources`, which
Odoo ≤ 16 imports and setuptools 82 removed.

## Out of scope

Expand Down
11 changes: 10 additions & 1 deletion instance_manager/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,6 @@ def tf(template: str, *args: object, **kwargs: object) -> str:
"Odoo admin_passwd (master password)": "admin_passwd de Odoo (contraseña maestra)",
"Expose the Odoo database manager over HTTP (list_db)? Recommended: No": "¿Exponer el gestor de bases de datos de Odoo por HTTP (list_db)? Recomendado: No",
"The database manager will be reachable over HTTP (create/duplicate/drop/restore), guarded only by the master password. Keep a strong master password and a dbfilter.": "El gestor de bases de datos quedará accesible por HTTP (crear/duplicar/eliminar/restaurar), protegido solo por la contraseña maestra. Mantén una contraseña maestra fuerte y un dbfilter.",
"Database manager disabled (list_db = False). Create the first database via CLI (odoo-bin -d <db> -i base --stop-after-init) or by temporarily re-enabling it.": "Gestor de bases de datos desactivado (list_db = False). Crea la primera base de datos por CLI (odoo-bin -d <db> -i base --stop-after-init) o reactivándolo temporalmente.",
"dbfilter (binds host/database)": "dbfilter (vincula host/base de datos)",
"Restrict the instance to specific database(s) with a dbfilter (recommended)?": "¿Restringir la instancia a una o varias bases de datos con un dbfilter (recomendado)?",
"No dbfilter set: the instance will not filter databases (all are reachable). Recommended only when the manager is disabled or a single database is served.": "Sin dbfilter: la instancia no filtrará bases de datos (todas quedan accesibles). Recomendado solo si el gestor está desactivado o se sirve una única base de datos.",
Expand Down Expand Up @@ -981,4 +980,14 @@ def tf(template: str, *args: object, **kwargs: object) -> str:
'Restore the dump as role {}': 'Restaurar el dump como rol {}',
"'cli' servers send through odoo.conf's smtp_server": "los servidores 'cli' envían por el smtp_server de odoo.conf",
'The copy failed: its unfinished database {} is dropped.': 'La copia ha fallado: se elimina su base de datos a medias {}.',
"Listen on every address (listen_addresses = '*')": "Escuchar en todas las direcciones (listen_addresses = '*')",
'Reload PostgreSQL (pg_hba)': 'Recargar PostgreSQL (pg_hba)',
'Install uv {} (checksum-verified) unless it is there': 'Instalar uv {} (verificado por checksum) salvo que ya esté',
'Set the role to the password entered (update other instances that use it)': 'Poner al rol la contraseña introducida (actualiza las otras instancias que lo usen)',
"Keep the role's password (type it now)": 'Mantener la contraseña del rol (escríbela ahora)',
'The PostgreSQL role {} already exists. Which password should this instance use?': 'El rol de PostgreSQL {} ya existe. ¿Qué contraseña debe usar esta instancia?',
'Current password of role {}': 'Contraseña actual del rol {}',
'Database manager disabled (list_db = False). Create the first database as the instance user: sudo -u <instance> <home>/venv/bin/python <home>/odoo/odoo-bin -c <odoo.conf> -d <db> -i base --stop-after-init, or re-enable the manager for a while.': 'Gestor de bases de datos desactivado (list_db = False). Crea la primera base de datos como el usuario de la instancia: sudo -u <instancia> <home>/venv/bin/python <home>/odoo/odoo-bin -c <odoo.conf> -d <bd> -i base --stop-after-init, o reactiva el gestor un momento.',
'verify-full checks the server against a CA: place it at {}/.postgresql/root.crt, readable by the instance user, before the install runs.': 'verify-full comprueba el servidor contra una CA: colócala en {}/.postgresql/root.crt, legible por el usuario de la instancia, antes de ejecutar la instalación.',
'The gevent port must differ from the HTTP port.': 'El puerto gevent debe ser distinto del puerto HTTP.',
}
Loading
Loading