1 25/10/2026 11 min

Scelta dell’architettura su Ubuntu 20.04

Odoo 14 su Ubuntu 20.04 funziona bene se separi subito i ruoli: sistema operativo pulito, PostgreSQL dedicato, utente applicativo senza privilegi, servizio systemd per il processo Odoo e Nginx come reverse proxy davanti. È la configurazione più prevedibile in produzione perché ti lascia un punto chiaro di osservazione per ogni layer: porta applicativa, log, database e front-end HTTP.

Su una macchina singola la scelta più lineare è questa: Odoo ascolta in locale sulla porta 8069, Nginx espone 80 e 443, PostgreSQL resta accessibile solo da localhost. Se più avanti vuoi alleggerire il server, il primo collo di bottiglia da spostare non è Nginx ma il database e, in seconda battuta, il worker process di Odoo.

Prima di partire tieni presente un limite pratico: Odoo 14 è una release datata rispetto all’attuale ecosistema Python e librerie di sistema. Su Ubuntu 20.04 si installa senza forzature particolari, ma non conviene improvvisare con dipendenze prese a mano da repository esterni se non hai già deciso come gestire aggiornamenti e rollback.

Pacchetti di base e preparazione del sistema

Parti con aggiornamento del sistema e installazione dei pacchetti necessari. L’obiettivo è evitare errori banali durante la compilazione di dipendenze Python e l’uso di LDAP, PDF, immagini e rendering lato server.

sudo apt update
sudo apt -y upgrade
sudo apt -y install git wget curl gnupg2 ca-certificates lsb-release build-essential \ python3 python3-pip python3-venv python3-dev python3-wheel \ libxml2-dev libxslt1-dev libldap2-dev libsasl2-dev libssl-dev \ libjpeg-dev libpq-dev libffi-dev libopenjp2-7-dev libtiff5-dev \ zlib1g-dev liblcms2-dev libwebp-dev libharfbuzz-dev libfribidi-dev \ fontconfig xfonts-75dpi xfonts-base

Il pacchetto più importante da non dimenticare è libpq-dev, perché Odoo parla con PostgreSQL tramite driver Python e senza i file di sviluppo il build dell’ambiente virtuale si rompe. I pacchetti grafici servono soprattutto per wkhtmltopdf, che Odoo usa per generare PDF coerenti con i report.

PostgreSQL: utente dedicato e istanza locale

Odoo non va installato con il database esposto in rete se non hai un motivo preciso. Su Ubuntu 20.04 installa PostgreSQL dal repository ufficiale della distro e lascia il servizio in ascolto solo localmente. Questo riduce superficie d’attacco e semplifica la diagnostica.

sudo apt -y install postgresql
sudo systemctl enable --now postgresql
sudo systemctl status postgresql --no-pager

Verifica subito che il servizio sia attivo e che l’accesso locale funzioni. Odoo usa un utente PostgreSQL dedicato, in genere chiamato odoo14 o odoo, con permessi di creazione database ma non di superuser.

sudo -u postgres createuser -s odoo14
sudo -u postgres psql -c "\du"

Se preferisci mantenere i privilegi più stretti, puoi evitare il flag -s e assegnare solo i permessi necessari al ruolo applicativo. In installazioni standard, però, molti operatori usano un ruolo con capacità di creare database per semplificare la gestione multi-database di Odoo. La scelta va fatta in base al tuo modello operativo, non per comodità cieca.

Utente di sistema e directory applicativa

Il processo Odoo non deve girare come root. Crea un utente di sistema senza login interattivo, poi prepara una struttura file ordinata per codice sorgente, log e moduli custom. Questo ti aiuta anche nei backup incrementali.

sudo adduser --system --home=/opt/odoo14 --group odoo14
sudo mkdir -p /opt/odoo14/{src,custom-addons,log,venv}
sudo chown -R odoo14:odoo14 /opt/odoo14

La separazione tra src e custom-addons è utile quando aggiorni il codice o fai troubleshooting dei moduli locali. Se metti tutto nello stesso albero, dopo qualche mese non distingui più ciò che arriva dal core da ciò che hai sviluppato o installato a mano.

Scaricare Odoo 14 e creare l’ambiente Python

Clona il ramo 14.0 dal repository ufficiale e crea un ambiente virtuale dedicato. Evita installazioni Python globali: quando aggiorni una libreria, non vuoi rompere il resto del server.

sudo -u odoo14 bash -lc '
cd /opt/odoo14/src
if [ ! -d odoo ]; then git clone https://github.com/odoo/odoo.git -b 14.0 --depth 1 odoo
fi
cd /opt/odoo14
python3 -m venv venv
./venv/bin/pip install --upgrade pip wheel setuptools
./venv/bin/pip install -r /opt/odoo14/src/odoo/requirements.txt
'

Se il comando di installazione fallisce, la prima cosa da controllare è la presenza dei pacchetti di sviluppo già installati a livello di sistema. In particolare, errori su psycopg2, lxml o Pillow di solito indicano dipendenze OS mancanti, non un problema di Odoo.

In ambienti con policy più rigide conviene salvare un file di lock delle dipendenze Python già installate, così hai un riferimento per il rollback del virtualenv. Non è un sostituto del codice sorgente, ma ti salva quando devi ricostruire l’ambiente in fretta dopo una manutenzione.

Configurazione di Odoo: file, log e parametri essenziali

Il file di configurazione deve vivere fuori dal repository e deve essere leggibile solo dall’utente applicativo. Un esempio tipico è /etc/odoo14.conf. Dentro metti i parametri minimi: password master, database, addons custom, log file e porta di ascolto locale.

sudo tee /etc/odoo14.conf > /dev/null <<'EOF'
[options]
admin_passwd = cambia_questa_password
db_host = False
db_port = False
db_user = odoo14
db_password = False
addons_path = /opt/odoo14/src/odoo/addons,/opt/odoo14/custom-addons
xmlrpc_port = 8069
logfile = /opt/odoo14/log/odoo14.log
proxy_mode = True
EOF
sudo chown odoo14:odoo14 /etc/odoo14.conf
sudo chmod 640 /etc/odoo14.conf

La direttiva proxy_mode = True è importante se Nginx termina TLS davanti a Odoo. Senza questa opzione, Odoo può interpretare male gli header del proxy e generare URL o redirect incoerenti. Se non la imposti, il problema emerge spesso solo quando accedi dall’esterno, non in locale.

Non lasciare la password master in chiaro in un documento operativo condiviso. Se devi passare il file a un altro operatore, redigi il valore e distribuiscilo con un canale separato o ruotalo subito dopo il test iniziale.

Servizio systemd per Odoo 14

Il servizio systemd ti garantisce avvio automatico, restart controllato e log centralizzati. È il modo giusto per far girare Odoo su Ubuntu 20.04 in ambiente server.

sudo tee /etc/systemd/system/odoo14.service > /dev/null <<'EOF'
[Unit]
Description=Odoo 14
After=network.target postgresql.service [Service]
Type=simple
User=odoo14
Group=odoo14
ExecStart=/opt/odoo14/venv/bin/python3 /opt/odoo14/src/odoo/odoo-bin -c /etc/odoo14.conf
WorkingDirectory=/opt/odoo14/src/odoo
StandardOutput=journal+console
StandardError=journal+console
Restart=always
RestartSec=5 [Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now odoo14
sudo systemctl status odoo14 --no-pager

Se il servizio non parte, non andare subito a modificare la configurazione. Prima leggi il journal e verifica se il problema è di permessi, dipendenze Python mancanti o path sbagliati. Il comando più utile è questo:

journalctl -u odoo14 -n 100 --no-pager

Nel 90% dei casi di avvio fallito, il messaggio nel journal è sufficiente a capire se Odoo non trova il file di configurazione, non riesce a connettersi a PostgreSQL o sta fallendo all’importazione di un modulo Python. Il vantaggio di systemd è proprio questo: un punto unico per vedere il crash reale, non il sintomo lato browser.

Nginx come reverse proxy e terminazione TLS

Esponi Odoo tramite Nginx invece di pubblicare direttamente la porta 8069. Ti serve per HTTPS, buffering, header corretti e gestione dei file statici in modo più robusto. In produzione è la configurazione standard.

sudo apt -y install nginx
sudo tee /etc/nginx/sites-available/odoo14 > /dev/null <<'EOF'
upstream odoo14 { server 127.0.0.1:8069;
} server { listen 80; server_name odoo.example.com; access_log /var/log/nginx/odoo14.access.log; error_log /var/log/nginx/odoo14.error.log; location / { proxy_pass http://odoo14; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; }
}
EOF
sudo ln -s /etc/nginx/sites-available/odoo14 /etc/nginx/sites-enabled/odoo14
sudo nginx -t
sudo systemctl reload nginx

Se usi un certificato TLS, aggiungi il blocco HTTPS con redirect da 80 a 443 e certificato gestito da Let’s Encrypt o dalla tua PKI interna. Non serve inventare configurazioni complesse: per la maggior parte dei casi bastano header corretti e timeout lunghi, perché Odoo può impiegare tempo a generare report o aggiornare moduli.

Un dettaglio che molti trascurano: i timeout del proxy devono essere coerenti con il tipo di uso. Se fai installazioni con report pesanti o importazioni massicce, i valori troppo bassi generano errori apparenti di rete che in realtà sono semplici scadenze del proxy.

Certificato TLS e hardening minimo

Se il server è esposto su Internet, TLS non è opzionale. Con Let’s Encrypt puoi automatizzare il rinnovo, ma il punto importante è che il nome DNS punti davvero al server giusto prima di richiedere il certificato.

sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx -d odoo.example.com

Verifica poi che il rinnovo automatico sia attivo:

systemctl status certbot.timer --no-pager
sudo certbot renew --dry-run

Dal punto di vista della sicurezza, il minimo sensato è questo: database non esposto, file di configurazione con permessi stretti, servizio applicativo non root, password master diversa dalle credenziali del database e log accessibili solo agli amministratori. Se il server ospita anche altri siti, isola i virtual host e non mischiare le directory document root con gli asset Odoo.

Primo avvio, creazione database e verifica funzionale

Quando il servizio è su, apri il browser su http://server:8069 solo per un test interno oppure su https://odoo.example.com se Nginx e TLS sono già pronti. La prima schermata ti chiede la creazione del database. Qui inserisci la master password, il nome del database, email amministrativa e lingua.

Se la pagina non compare, controlla prima il layer più vicino al problema: Odoo in ascolto, Nginx attivo, DNS corretto. I controlli rapidi sono questi:

ss -ltnp | grep 8069
systemctl status odoo14 --no-pager
nginx -t
curl -I http://127.0.0.1:8069
curl -I https://odoo.example.com

Se il comando curl locale risponde ma il dominio pubblico no, il problema è quasi sempre nel reverse proxy o nel DNS. Se il dominio risponde ma la UI resta bianca o si ferma al caricamento, il problema è spesso nei file statici, nei permessi o in un modulo custom che rompe il bootstrap.

Moduli custom, aggiornamenti e manutenzione ordinaria

Ogni modulo custom va trattato come codice applicativo vero, non come una cartella da copiare a mano e dimenticare. Tienilo in /opt/odoo14/custom-addons, versionalo in Git e documenta dipendenze, manifest e compatibilità con il core 14.0.

Quando aggiorni Odoo o aggiungi moduli, fai sempre un backup del database e della directory custom. Il rollback pratico è semplice: ripristino del dump PostgreSQL, ripristino del codice sorgente e restart del servizio. Senza questo flusso, ogni change diventa un salto nel buio.

pg_dump -U odoo14 -Fc nome_db > /backup/nome_db_$(date +%F).dump
sudo tar -czf /backup/odoo14_custom_$(date +%F).tar.gz /opt/odoo14/custom-addons

Per gli aggiornamenti del core, non fare overwrite casuali del repository. Usa un branch controllato, testa in staging e confronta i log prima e dopo. La metrica che ti interessa non è solo “il servizio parte”, ma anche tempo di risposta della home, error rate sui login e stabilità dei worker durante un’apertura massiva di moduli o report.

Problemi tipici e diagnosi rapida

Ci sono quattro guasti ricorrenti che vedrai quasi subito in produzione o in pre-produzione. Il primo è il database non raggiungibile: il journal mostra errori di connessione e la pagina iniziale non carica. Il secondo è una dipendenza Python mancante, che emerge durante l’avvio del servizio. Il terzo è un errore di configurazione del proxy, che produce redirect errati o contenuti incompleti. Il quarto è un modulo custom difettoso, spesso riconoscibile da stack trace ripetuti nel log applicativo.

Per isolare il problema, ragiona per layer: DNS, edge Nginx, processo Odoo, PostgreSQL, storage. Questa sequenza evita di perdere tempo su ipotesi sbagliate. Se il problema è a livello di storage, per esempio spazio disco esaurito, Odoo può smettere di scrivere log o allegati e il sintomo esterno sembra generico. Controlla sempre anche lo spazio libero e gli inode.

df -h
df -i
free -h
journalctl -u odoo14 -n 50 --no-pager
tail -n 50 /opt/odoo14/log/odoo14.log

Struttura finale consigliata

Se devi mettere Odoo 14 in produzione su Ubuntu 20.04, la struttura che regge meglio nel tempo è questa: sistema aggiornato, PostgreSQL locale, utente dedicato, ambiente virtuale Python separato, configurazione fuori dal repository, systemd per il lifecycle e Nginx davanti con TLS. È una base semplice da capire e abbastanza robusta da non costringerti a riprogettare tutto al primo ticket serio.

Una volta completata l’installazione, il vero lavoro inizia con osservabilità e disciplina operativa: log leggibili, backup verificati, moduli custom versionati e controllo dei permessi. Se questi elementi mancano, l’installazione “funziona” solo fino al primo cambio o al primo incidente. Assunzione: ambiente single-server con traffico normale e necessità di esporre Odoo via HTTPS su dominio pubblico.