在Ubuntu 20.04 LTS上安装部署Odoo15并设置Nginx SSL反向代理

安装odoo的方法很多,最简单的是用deb包来安装,或者使用docker来部署,当然如果你想自己定义一些东西,可以考虑源码安装方式,下面我就是用的源码安装方式。

在正式安装之前先确保你的VPS能够访问Github,以及一个域名(设置Nginx SSL代理的时候需要)。

安装依赖

第一步是安装Git 、Pip 、Node.js 和开发构建Odoo所需的工具:

sudo apt update
sudo apt install git python3-pip build-essential wget python3-dev python3-venv \
    python3-wheel libfreetype6-dev libxml2-dev libzip-dev libldap2-dev libsasl2-dev \
    python3-setuptools node-less libjpeg-dev zlib1g-dev libpq-dev \
    libxslt1-dev libldap2-dev libtiff5-dev libjpeg8-dev libopenjp2-7-dev \
    liblcms2-dev libwebp-dev libharfbuzz-dev libfribidi-dev libxcb1-dev

创建系统用户

在 root 用户下运行 Odoo 会带来安全风险。我们将创建一个新的系统用户和组,主目录为/opt/odoo15来运行 Odoo 服务。为此,请运行以下命令:

sudo useradd -m -d /opt/odoo15 -U -r -s /bin/bash odoo15

您可以随意命名用户,只要您创建一个同名的 PostgreSQL 用户即可。

安装和配置 PostgreSQL

Odoo 使用 PostgreSQL 作为数据库后端。PostgreSQL 包含在标准的 Ubuntu 存储库中。安装很简单:

sudo apt install postgresql

安装服务后,创建一个与之前创建的系统用户同名的 PostgreSQL 用户。在这个例子中,那就是odoo15:

sudo su - postgres -c "createuser -s odoo15"

安装 wkhtmltopdf

wkhtmltopdf 是一组开源命令行工具,用于将 HTML 页面渲染为 PDF 和各种图像格式。要在 Odoo 中打印 PDF 报告,您需要安装该wkhtmltox软件包。

Ubuntu 存储库中包含的 wkhtmltopdf 版本不支持页眉和页脚。Odoo 的推荐版本是 version 0.12.5。我们将从 Github 下载并安装该软件包:

sudo wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.bionic_amd64.deb

下载文件后,键入以下命令进行安装:

sudo apt install ./wkhtmltox_0.12.5-1.bionic_amd64.deb

安装和配置 Odoo 15

我们将在隔离的Python 虚拟环境中从源代码安装 Odoo 。

首先,更改为用户 “odoo15”:

sudo su - odoo15

从 GitHub 克隆 Odoo 15 源代码:

git clone https://www.github.com/odoo/odoo --depth 1 --branch 15.0 /opt/odoo15/odoo

为 Odoo 创建一个新的 Python 虚拟环境:

cd /opt/odoo15
python3 -m venv odoo-venv

激活虚拟环境:

source odoo-venv/bin/activate

Odoo 依赖项在 requirements.txt 文件中指定。使用 pip3 安装所有必需的 Python 模块:

pip3 install wheel
pip3 install -r odoo/requirements.txt
如果在安装过程中遇到任何编译错误,请确保安装了本Installing Prerequisites节中列出的所有必需依赖项。

完成后,键入以下命令停用环境:

deactivate

我们将为 第三方插件创建一个新目录和一个单独的目录:

mkdir /opt/odoo15/odoo-custom-addons

稍后我们会将这个目录添加到addons_path参数中。该参数定义了 Odoo 搜索模块的目录列表。

切换回您的sudo用户:

exit

创建一个配置文件,内容如下:

sudo vi /etc/odoo15.conf
[options]
; This is the password that allows database operations:
admin_passwd = my_admin_passwd
db_host = False
db_port = False
db_user = odoo15
db_password = False
addons_path = /opt/odoo15/odoo/addons,/opt/odoo15/odoo-custom-addons
不要忘记将 更改my_admin_passwd为更安全的内容。

创建 Systemd 单元文件

单元文件是一种配置 ini 样式的文件,其中包含有关服务的信息。

打开您的文本编辑器 并创建一个以odoo15.service以下内容命名的文件:

sudo vi /etc/systemd/system/odoo15.service
[Unit]
Description=Odoo15
Requires=postgresql.service
After=network.target postgresql.service

[Service]
Type=simple
SyslogIdentifier=odoo15
PermissionsStartOnly=true
User=odoo15
Group=odoo15
ExecStart=/opt/odoo15/odoo-venv/bin/python3 /opt/odoo15/odoo/odoo-bin -c /etc/odoo15.conf
StandardOutput=journal+console

[Install]
WantedBy=multi-user.target

通知 systemd 存在新的单元文件:

sudo systemctl daemon-reload

启动 Odoo 服务并通过运行以下命令使其在启动时启动:

sudo systemctl enable --now odoo15

验证服务是否已启动并正在运行:

sudo systemctl status odoo15

安装Nginx

sudo apt install nginx

安装 Certbot

sudo apt install certbot

生成强 Dh (Diffie-Hellman) 组

Diffie–Hellman 密钥交换 (DH) 是一种通过不安全的通信通道安全地交换加密密钥的方法。

通过键入以下命令生成一组新的 2048 位 DH 参数:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

您也可以使用最长 4096 位的密钥长度,但生成可能需要 30 分钟以上,具体取决于系统熵。

获取 Let’s Encrypt SSL 证书

为了获得域的 SSL 证书,我们将使用 Webroot 插件,该插件通过创建一个临时文件来验证${webroot-path}/.well-known/acme-challenge目录中请求的域。Let’s Encrypt 服务器向临时文件发出 HTTP 请求,以验证请求的域是否解析为运行 certbot 的服务器。

为了更简单,我们将把所有的 HTTP 请求映射.well-known/acme-challenge到一个目录,/var/lib/letsencrypt.

以下命令将创建目录并使其可用于 Nginx 服务器:

sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp www-data /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt

为了避免重复代码,我们将创建两个片段并将它们包含在所有 Nginx 服务器块文件中。

打开您的文本编辑器 并创建第一个片段letsencrypt.conf:

sudo vi /etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}

接下来,创建第二个片段 ,ssl.conf其中包括Mozilla推荐的芯片 ,启用 OCSP 装订、HTTP 严格传输安全 (HSTS) 并强制执行少数以安全为中心的 HTTP 标头。

sudo vi /etc/nginx/snippets/ssl.conf
ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

创建letsencrypt.conf代码段后,打开域服务器阻止文件并包含如下所示的代码段:

sudo vi /etc/nginx/sites-available/example.com.conf
server {
  listen 80;
  server_name example.com www.example.com;

  include snippets/letsencrypt.conf;
}

要启用新的服务器块,请创建从文件到sites-enabled目录的符号链接:

sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/

重新启动 Nginx 服务 以使更改生效:

sudo systemctl restart nginx

您现在可以使用 webroot 插件运行 Certbot 并通过发出以下命令获取 SSL 证书文件:

sudo certbot certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com

如果成功获取 SSL 证书,certbot 将打印以下消息:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2020-10-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

为Odoo15配置 SSL 反向代理

sudo vi /etc/nginx/sites-enabled/example.com.conf

以下配置设置 SSL 终止、HTTP 到 HTTPS 重定向 、WWW 到非 WWW 重定向、缓存静态文件并启用GZip 压缩。

# Odoo servers
upstream odoo {
 server 127.0.0.1:8069;
}

upstream odoochat {
 server 127.0.0.1:8072;
}

# HTTP -> HTTPS
server {
    listen 80;
    server_name www.example.com example.com;

    include snippets/letsencrypt.conf;
    return 301 https://example.com$request_uri;
}

# WWW -> NON WWW
server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    proxy_read_timeout 720s;
    proxy_connect_timeout 720s;
    proxy_send_timeout 720s;

    # Proxy headers
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;

    # SSL parameters
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # log files
    access_log /var/log/nginx/odoo.access.log;
    error_log /var/log/nginx/odoo.error.log;

    # Handle longpoll requests
    location /longpolling {
        proxy_pass http://odoochat;
    }

    # Handle / requests
    location / {
       proxy_redirect off;
       proxy_pass http://odoo;
    }

    # Cache static files
    location ~* /web/static/ {
        proxy_cache_valid 200 90m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoo;
    }

    # Gzip
    gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
    gzip on;
}

完成后,重新启动 Nginx 服务:

sudo systemctl restart nginx

告诉 Odoo 启用多处理并使用代理和更改绑定接口

默认情况下,Odoo 在多线程模式下工作。对于生产部署,建议更改为多处理服务器,因为它可以提高稳定性并更好地利用系统资源。

要启用多处理,您需要编辑 Odoo 配置并设置非零数量的工作进程。worker 的数量是根据系统中 CPU 内核的数量和可用的 RAM 内存计算的。

根据官方的Odoo 文档 ,要计算工人数量和所需的RAM 内存 大小,您可以使用以下公式和假设:

工人数计算

理论最大worker数=(system_cpus * 2)+ 1
1 个工人可以服务 ~= 6 个并发用户
Cron 工作者也需要 CPU
RAM内存大小计算

我们会认为所有请求中有 20% 是重请求,80% 是轻请求。大量请求使用大约 1 GB 的 RAM,而较轻的请求使用大约 150 MB 的 RAM
需要的内存 = number_of_workers * ( (light_worker_ratio * light_worker_ram_estimation) + (heavy_worker_ratio * heavy_worker_ram_estimation) )
如果您不知道系统上有多少 CPU,请使用以下grep 命令:

grep -c ^processor /proc/cpuinfo

假设您有一个具有 4 个 CPU 内核、8 GB RAM 内存和 30 个并发 Odoo 用户的系统。

30 users / 6 = 5 (5 是理论所需的工人数量)
(4 * 2) + 1 = 9 ( 9 是理论最大工人数)
根据上面的计算,您可以使用 5 个工人 + 1 个工人作为 cron 工人,总共 6 个工人。

根据worker数量计算RAM内存消耗:

RAM = 6 * ((0.8150) + (0.21024)) ~= 2 GB of RAM
计算表明,Odoo 安装将需要大约 2GB 的 RAM。

默认情况下,Odoo 服务器侦听8069所有接口上的端口。要禁用对 Odoo 实例的直接访问,您可以阻止8069所有公共接口的端口或强制 Odoo 仅侦听本地接口。

我们修改Odoo的设置文件为下面就行

sudo vi /etc/odoo15.conf
proxy_mode = True
xmlrpc_interface = 127.0.0.1
netrpc_interface = 127.0.0.1
limit_memory_hard = 2684354560
limit_memory_soft = 2147483648
limit_request = 8192
limit_time_cpu = 600
limit_time_real = 1200
max_cron_threads = 1
workers = 5

重启 Odoo 服务以使更改生效:

sudo systemctl restart odoo15

如果想以后方便迁移以及一台机器上运行多个Odoo实例可以看我写的另外一篇如何用docker部署odoo

类似文章

2条评论

    1. 这个也是官方教程里给的,我亲自部署过应该没问题,不过现在17了应该会有些不同。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注