One-Click Odoo 18 Installation on Ubuntu 22.04: the Complete Guide
“I wish I could spin up Odoo with one command…”
Now you can. In this post you’ll learn how to drop a single shell script onto a fresh Ubuntu 22.04 (Jammy) server and walk away—five minutes later you’ll have a production-ready Odoo 18 stack (Python 3.12, PostgreSQL, Node 18, wkhtmltopdf 0.12.5, systemd service, log rotation) humming on the port of your choice.
🗺️ What you’ll find below
- Why a script beats the manual method
- Prerequisites & tested environment
- The installer script (copy-paste ready)
- Running it—literally one command
- What the script does under the hood
- Troubleshooting & common questions
- Wrapping up
1 Why automate?
- Consistency – zero “works-on-my-laptop” surprises.
- Speed – 200+ manual keystrokes crushed into 1.
- Idempotence – re-run anytime to heal a half-broken install.
- Safety – the Odoo Linux user is system-scoped, no login shell by default.
2 Prerequisites
| Item | Notes |
|---|---|
| Fresh Ubuntu 22.04 LTS server | Tested on 22.04.4 server & Jammy LXC containers |
| sudo privileges | Run the script as root or through sudo |
| Outbound internet | Fetches packages from apt, GitHub, NodeSource |
| 2 GB RAM + 2 CPU (minimum) | Odoo boots fine with less, but building wheels is faster |
Need Ubuntu 24.04? Swap in Python 3.12 from the default repo and skip the legacy libssl1.1 step—the rest is identical.
3 The one-click installer
Create a file called install_odoo18_22.sh (sudo nano install_odoo18_22.sh ) and paste the contents below.
(Feel free to add it to a gist or your Ansible repo later.)
#!/usr/bin/env bash
# ╔═════════════════════════════════════════════════════════════╗
# ║ One-click Odoo 18 installer for Ubuntu 22.04 LTS (Jammy) ║
# ╚═════════════════════════════════════════════════════════════╝
# Optional flags (defaults):
# --odoo-version 18.0
# --odoo-user odoo18
# --db-user odoo18
# --db-pass changeme
# --port 8069
# --log-dir /var/log/odoo18
# --config /etc/odoo18.conf
# --service odoo18
#
# Example:
# sudo ./install_odoo18_22.sh --db-pass "Sup3rSecret!" --port 8070
set -euo pipefail; IFS=$'\n\t'
# ─────────────────────── CLI flags ────────────────────────────
ODOO_VERSION=18.0 ODOO_USER=odoo18 DB_USER=odoo18 DB_PASS=changeme \
ODOO_PORT=8069 LOG_DIR=/var/log/odoo18 ODOO_CONF=/etc/odoo18.conf \
SERVICE_NAME=odoo18
while [[ $# -gt 0 ]]; do case $1 in
--odoo-version) ODOO_VERSION=$2; shift 2;;
--odoo-user) ODOO_USER=$2; shift 2;;
--db-user) DB_USER=$2; shift 2;;
--db-pass) DB_PASS=$2; shift 2;;
--port) ODOO_PORT=$2; shift 2;;
--log-dir) LOG_DIR=$2; shift 2;;
--config) ODOO_CONF=$2; shift 2;;
--service) SERVICE_NAME=$2; shift 2;;
-h|--help) grep '^# ' "$0"|sed 's/^# //' ; exit 0;;
*) echo "Unknown flag $1"; exit 1;;
esac; done
die(){ echo "❌ $*"; exit 1; }
echo "▶ Updating apt …"; apt update -y && apt upgrade -y
echo "▶ Enabling Python 3.12 (Deadsnakes) …"
apt install -y software-properties-common
add-apt-repository -y ppa:deadsnakes/ppa && apt update -y
echo "▶ Adding Node 18 repo …"
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - || echo "⚠️ Node repo skipped"
DEBIAN_FRONTEND=noninteractive apt install -y \
git curl wget build-essential sudo postgresql \
python3.12 python3.12-venv python3.12-dev python3-pip \
libxml2-dev libxslt1-dev zlib1g-dev libsasl2-dev libldap2-dev \
libssl-dev libffi-dev libjpeg-dev libpq-dev libjpeg8-dev liblcms2-dev \
libblas-dev libatlas-base-dev openssh-server fail2ban \
nodejs npm xfonts-75dpi xfonts-base
[[ -e /usr/bin/node ]] || ln -s /usr/bin/nodejs /usr/bin/node
npm install -g less less-plugin-clean-css || echo "⚠️ npm-less skipped"
# ── wkhtmltopdf 0.12.5 (static) ───────────────────────────────
if ! command -v wkhtmltopdf >/dev/null; then
echo "▶ Installing wkhtmltopdf 0.12.5 …"
wget -q https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.focal_amd64.deb
wget -q http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
dpkg -i libssl1.1_* || true; dpkg -i wkhtmltox_* || true
apt -f install -y && rm wkhtmltox_* libssl1.1_*
fi
# ── PostgreSQL role ───────────────────────────────────────────
systemctl enable --now postgresql
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" |
grep -q 1 || sudo -u postgres createuser --createdb --superuser --pwprompt "$DB_USER" <<<"$DB_PASS"$'\n'"$DB_PASS"
# ── System user & source ─────────────────────────────────────
adduser --system --home=/opt/$ODOO_USER --group "$ODOO_USER" 2>/dev/null || true
sudo -H -u "$ODOO_USER" bash -c "
cd /opt/$ODOO_USER
[[ -d odoo ]] || git clone --depth 1 --branch $ODOO_VERSION https://github.com/odoo/odoo.git
python3.12 -m venv venv
source venv/bin/activate
pip install -U pip wheel
pip install -r odoo/requirements.txt
"
# ── Config & service ─────────────────────────────────────────
cat >"$ODOO_CONF" <<EOF
[options]
admin_passwd = $(openssl rand -hex 16)
db_host = False
db_port = False
db_user = $DB_USER
db_password = $DB_PASS
addons_path = /opt/$ODOO_USER/odoo/addons
logfile = $LOG_DIR/odoo.log
xmlrpc_port = $ODOO_PORT
EOF
chown $ODOO_USER: "$ODOO_CONF"; chmod 640 "$ODOO_CONF"
mkdir -p "$LOG_DIR"; chown $ODOO_USER:root "$LOG_DIR"
cat >/etc/systemd/system/${SERVICE_NAME}.service <<EOF
[Unit]
Description=Odoo ${ODOO_VERSION}
After=network.target postgresql.service
[Service]
Type=simple
User=$ODOO_USER
ExecStart=/opt/$ODOO_USER/venv/bin/python3.12 /opt/$ODOO_USER/odoo/odoo-bin -c $ODOO_CONF
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
chmod 644 /etc/systemd/system/${SERVICE_NAME}.service
systemctl daemon-reload && systemctl enable --now ${SERVICE_NAME}.service
echo -e "\n🎉 Odoo $ODOO_VERSION is live on http://$(hostname -I|awk '{print $1}'):$ODOO_PORT\n"
Make it executable:
chmod +x install_odoo18_22.sh
4 Run it (the real “single click”)
sudo ./install_odoo18_22.sh --db-pass "ChangeMe!" --port 8069
Grab a coffee—the script:
- Updates the OS.
- Installs Python 3.12, Node 18, PostgreSQL 14, wkhtmltopdf 0.12.5.
- Creates a non-login odoo18 system user.
- Clones the Odoo 18 source and builds a virtual environment.
- Drops a hardened odoo18.conf in /etc.
- Registers a systemd service and starts it.
When you see “🎉 Odoo 18 is live”, point your browser to:
http://<SERVER-IP>:8069
and create your first database.
5 What just happened? (the short version)
| Stage | Highlights |
|---|---|
| System prep | Deadsnakes PPA + NodeSource repo |
| Dependencies | xfonts-75dpi & xfonts-base fix wkhtmltopdf deps |
| wkhtmltopdf | Static 0.12.5 build + legacy libssl1.1 (Odoo-approved) |
| PostgreSQL | Super-role with the password you set |
| Odoo env | /opt/odoo18/venv isolates Python libs |
| Service | systemctl status odoo18 for health checks |
| Logs | /var/log/odoo18/odoo.log rotates via logrotate defaults |
6 Troubleshooting & FAQs
| Symptom | Fix |
|---|---|
| wkhtmltopdf PDF header/footer misaligned | You’re on 0.12.6+—rerun script or reinstall 0.12.5 |
| psql: connection refused | systemctl status postgresql → start service |
| Need to SSH as odoo18 | sudo -H -u odoo18 bash (account is nologin by design) |
| Change port later | Edit xmlrpc_port in /etc/odoo18.conf & systemctl restart odoo18 |
7 Wrapping up
With one script and one command you’ve provisioned a fully-functional Odoo 18 stack on Ubuntu 22.04—ready for production or dev play. Clone the script into your IaC pipeline, bake it into a custom AMI, or hand it to a teammate who “just needs Odoo” by lunchtime.
Happy automating—and happy selling with Odoo 18!