在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
配置有问题:
# Handle / requests
location / {
proxy_redirect off;
proxy_pass http://odoo;
}
这里的proxy_redirect off;是错误额的
这个也是官方教程里给的,我亲自部署过应该没问题,不过现在17了应该会有些不同。