本页内容

  • 准备工作
  • 第 1 步 - 配置防火墙规则
  • 第 2 步 - 分配主机名
  • 第 3 步 - 安装并配置 PostgreSQL / 配置基于主机的认证 / 配置 PostgreSQL 监听地址 / 启用并启动 PostgreSQL 服务
  • 第 4 步 - 安装 Odoo / 安装 Python 3.10 / 安装依赖并准备安装 / 下载 Odoo 文件 / 搭建 Virtualenv Python 环境 / 安装 Python 依赖 / 创建第三方插件目录
  • 第 5 步 - 配置 Odoo / 创建 Odoo 服务 / 创建 Odoo 日志目录 / 设置文件权限 / 启动 Odoo 服务
  • 第 6 步 - 安装并配置 Nginx
  • 第 7 步 - 安装 SSL
  • 第 8 步 - 配置 Nginx
  • 第 9 步 - 启动 Odoo
  • 第 10 步 - 更新 Odoo
  • 第 11 步 - 使用 Fail2Ban 加固 Odoo
  • 总结
  • 配置基于主机的认证
  • 配置 PostgreSQL 监听地址
  • 启用并启动 PostgreSQL 服务
  • 安装 Python 3.10
  • 安装依赖并准备安装
  • 下载 Odoo 文件
  • 搭建 Virtualenv Python 环境
  • 安装 Python 依赖
  • 创建第三方插件目录
  • 创建 Odoo 服务
  • 创建 Odoo 日志目录
  • 设置文件权限
  • 启动 Odoo 服务

Odoo(前身为 OpenERP)是一套自托管的开源应用套件,包含超过 10,000 个面向各类业务需求的应用,涵盖 CRM、电子商务、会计、库存、项目管理以及销售点(POS)等。这些应用完全集成,并可通过熟悉的 Web 界面访问。

本教程将指导我们在 Rocky Linux 9 服务器上安装 Odoo 16 套件。

准备工作

  • 一台最低 2GB 内存的 Rocky Linux 9 服务器,用于托管 Odoo 套件。
  • 第二台最低 2GB 内存的 Rocky Linux 9 服务器,用于托管 PostgreSQL 数据库。不过,你也可以将数据库安装在与 Odoo 相同的服务器上,但在生产环境中,强烈建议将其安装在独立的服务器上。你也可以选择任意云服务商提供的托管数据库方案。
  • 内存需求取决于使用该套件的并发用户数量。有关如何计算系统需求的详细说明,请参阅 Odoo 官方文档。
  • 保持系统更新。$ sudo dnf update
  • 在两台服务器上均拥有 sudo 权限的非 root 用户。
  • 应安装 Fail2Ban。此步骤为可选项。你可以参考我们关于在 Rocky Linux 上安装 Fail2Ban 的指南来完成。
  • 应禁用 SELinux。
  • 系统所需的部分软件包。$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -y 其中部分软件包可能已在你的系统中安装。

一台最低 2GB 内存的 Rocky Linux 9 服务器,用于托管 Odoo 套件。

第二台最低 2GB 内存的 Rocky Linux 9 服务器,用于托管 PostgreSQL 数据库。不过,你也可以将数据库安装在与 Odoo 相同的服务器上,但在生产环境中,强烈建议将其安装在独立的服务器上。你也可以选择任意云服务商提供的托管数据库方案。

内存需求取决于使用该套件的并发用户数量。有关如何计算系统需求的详细说明,请参阅 Odoo 官方文档。

保持系统更新。

$ sudo dnf update

在两台服务器上均拥有 sudo 权限的非 root 用户。

应安装 Fail2Ban。此步骤为可选项。你可以参考我们关于在 Rocky Linux 上安装 Fail2Ban 的指南来完成。

应禁用 SELinux。

系统所需的部分软件包。

$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -y

其中部分软件包可能已在你的系统中安装。

第 1 步 - 配置防火墙规则

第一步是配置防火墙。Rocky Linux 使用 Firewalld 防火墙。在本教程中,我们假设你已在两台服务器上都安装了 Firewalld 防火墙。

检查防火墙状态。

$ sudo firewall-cmd --state
running

防火墙通过不同的区域(zone)工作,我们将使用默认的 public 区域。列出防火墙当前激活的所有服务和端口。

$ sudo firewall-cmd --zone=public --list-all

它应显示如下输出。

public
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

在 Odoo 服务器上,我们需要开放端口 22、80、443、6010、5432 和 8069。其中 22 用于 SSH,80 用于 HTTP,443 用于 HTTPS,6010 用于 Odoo 通信,5432 由 PostgreSQL 使用,8069 用于 Odoo 服务器应用。

运行以下命令在 Odoo 服务器上开放所需端口。

$ sudo firewall-cmd --zone=public --add-port={6010,5432,8069,8072}/tcp
$ sudo firewall-cmd --zone=public --add-service=http
$ sudo firewall-cmd --zone=public --add-service=https

检查防火墙状态。

$ sudo firewall-cmd --zone=public --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: cockpit dhcpv6-client http https ssh
  ports: 6010/tcp 5432/tcp 8069/tcp 8072/tcp
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

在 PostgreSQL 服务器上,我们需要开放端口 22、6010 和 5432。使用以下命令开放它们。

$ sudo firewall-cmd --zone=public --add-port={6010,5432}/tcp

将全部更改设为永久生效,并重新加载防火墙使更改生效。

$ sudo firewall-cmd --runtime-to-permanent
$ sudo firewall-cmd --reload

第 2 步 - 分配主机名

你可以使用服务器的 IP 地址,或者(如果可用)使用其完全限定域名(FQDN)。在本教程中,我们将使用 FQDN,因此需要在两台服务器上设置主机名。

使用以下命令在 Odoo 服务器上设置主机名。

$ sudo hostnamectl set-hostname odoo.yourdomain.com

使用以下命令在 PostgreSQL 服务器上设置主机名。

$ sudo hostnamectl set-hostname postgresql.yourdomain.com

在 Odoo 服务器上,打开 /etc/hosts 文件。

$ sudo nano /etc/hosts

确保其内容如下所示。

127.0.0.1 	localhost
127.0.0.1	odoo.yourdomain.com		odoo
10.1.1.10	postgresql.yourdomain.com	postgresql

在 PostgreSQL 服务器上,打开该文件并确保其内容如下所示。

127.0.0.1 	localhost
127.0.0.1	postgresql.yourdomain.com	postgresql
10.1.2.10	odoo.yourdomain.com		odoo

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

第 3 步 - 安装并配置 PostgreSQL

Rocky Linux 9 默认附带 PostgreSQL 13,并提供 postgresql:15 模块流。不过,我们将安装撰写本教程时可获取的最新版本——来自官方仓库的 PostgreSQL 16。

安装 PostgreSQL 仓库 RPM。

$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

禁用内置的 PostgreSQL 模块。

$ sudo dnf -qy module disable postgresql

安装 PostgreSQL 16。

$ sudo dnf install -y postgresql16-server postgresql16-contrib

初始化数据库。

$ sudo /usr/pgsql-16/bin/postgresql-16-setup initdb

启用并启动 PostgreSQL 服务。

$ sudo systemctl enable postgresql-16
$ sudo systemctl start postgresql-16

检查服务状态。

$ sudo systemctl status postgresql-16

你应该会看到类似的输出。

? postgresql-16.service - PostgreSQL 16 database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-04-07 02:22:42 UTC; 3s ago
       Docs: https://www.postgresql.org/docs/16/static/
    Process: 8673 ExecStartPre=/usr/pgsql-16/bin/postgresql-16-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
   Main PID: 8678 (postgres)
      Tasks: 7 (limit: 10819)
     Memory: 17.4M
        CPU: 60ms
     CGroup: /system.slice/postgresql-16.service
             ??8678 /usr/pgsql-16/bin/postgres -D /var/lib/pgsql/16/data/
             ??8679 "postgres: logger "
             ??8680 "postgres: checkpointer "
             ??8681 "postgres: background writer "
             ??8683 "postgres: walwriter "
             ??8684 "postgres: autovacuum launcher "
             ??8685 "postgres: logical replication launcher "

Apr 07 02:22:42 postgresql systemd[1]: Starting PostgreSQL 16 database server...
Apr 07 02:22:42 postgresql postgres[8678]: 2024-04-07 02:22:42.370 UTC [8678] LOG:  redirecting log output to logging collector process
Apr 07 02:22:42 postgresql postgres[8678]: 2024-04-07 02:22:42.370 UTC [8678] HINT:  Future log output will appear in directory "log".
Apr 07 02:22:42 postgresql systemd[1]: Started PostgreSQL 16 database server.

接下来,我们需要创建数据库用户 odoo。系统会提示你为该角色设置密码,请输入一个你自选的强密码。

$ sudo -u postgres createuser odoo -U postgres -dP

选项 -u 以 postgres 用户身份执行命令。

选项 -U 指定用于连接的用户名。

选项 -d 授予该用户创建数据库的权限。

选项 -p 提示输入新用户的密码。

配置基于主机的认证

我们需要赋予 PostgreSQL 服务连接 Odoo 服务器的权限。

首先,停止 PostgreSQL 服务。

$ sudo systemctl stop postgresql-16

要找出 PostgreSQL 存放客户端认证文件的位置,请运行以下命令启动 PostgreSQL 命令行。

$ sudo -u postgres psql

运行以下查询以查找该文件的位置。

postgres=# SHOW hba_file;

你将收到如下输出。

              hba_file              
------------------------------------
 /var/lib/pgsql/16/data/pg_hba.conf
(1 row)

输入 exit 退出命令行。

打开文件 /var/lib/pgsql/16/data/pg_hba.conf 进行编辑。

$ sudo nano /var/lib/pgsql/16/data/pg_hba.conf

在文件末尾粘贴以下一行。

host		all		odoo		odoo.yourdomain.com		scram-sha-256

这一行授予 odoo 用户连接本服务器上所有数据库的权限。你也可以使用具体数据库名称来代替 all 关键字。

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

配置 PostgreSQL 监听地址

接下来,我们需要允许数据库服务器监听远程连接。

启动 PostgreSQL 命令行并运行以下命令以定位 PostgreSQL 配置文件。

$ sudo -u postgres psql
postgres=# SHOW config_file;

你将收到如下输出。

              config_file               
----------------------------------------
 /var/lib/pgsql/16/data/postgresql.conf
(1 row)

输入 exit 退出命令行。

打开文件 /var/lib/pgsql/16/data/postgresql.conf 进行编辑。

$ sudo nano /var/lib/pgsql/16/data/postgresql.conf

将 listen_addresses 这一行从

#listen_addresses = 'localhost' # what IP address(es) to listen on;

改为:

listen_addresses = '*'

* 表示监听所有 IP 地址。你也可以将其改为你的 Odoo 实例的 IP 地址。

listen_addresses = 'localhost, <odoo_server_ip>'

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

启用并启动 PostgreSQL 服务

配置已完成,现在可以启动 PostgreSQL 服务了。

$ sudo systemctl start postgresql-16	

第 4 步 - 安装 Odoo

安装 Python 3.10

Rocky Linux 9 自带 Python 3.9,而 Odoo 17 需要 Python 3.10 及以上版本。因此,我们需要先安装它。

你可以先检查当前可用的版本。

$ python --version
Python 3.9.18

安装 Python 所需的依赖。

$ sudo dnf groupinstall "Development Tools"
$ sudo dnf install readline-devel ncurses-devel openssl-devel sqlite-devel tk-devel gdbm-devel libc6-dev libbz2-dev libffi-dev zlib1g-dev
$ sudo dnf install -y openssl-devel bzip2-devel libffi-devel readline-devel ncurses-devel sqlite-devel tk-devel

从 Python 官网下载源代码。撰写本教程时,最新的 3.10.x 版本为 3.10.14,本教程即采用该版本。

$ wget https://www.python.org/ftp/python/3.10.14/Python-3.10.14.tgz

解压压缩包。

$ tar xzf Python-3.10.14.tgz

切换到解压后的目录。

$ cd Python-3.10.14

配置源代码。

$ ./configure --enable-optimizations

安装 Python 3.10.14。这里使用 altinstall 命令,以免覆盖系统自带的 Python 版本。

$ sudo make altinstall

确认安装成功。

$ python3.10 -V
OR
$ python3.10 --version

你应该会看到如下输出。

Python 3.10.14

接下来,我们需要将 Python 3.10 设为默认 Python 版本。为服务器上安装的每个 Python 版本创建符号链接。在创建符号链接时,命令中应包含确切的 Python 版本号。运行以下命令创建符号链接。

$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.10 1
$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 2

要查看可用的 Python 版本,请使用以下命令。

$ sudo update-alternatives --config python3

你应该会看到如下输出。

There are 2 programs which provide 'python3'.

  Selection    Command
-----------------------------------------------
   1           /usr/local/bin/python3.10
*+ 2           /usr/bin/python3.9

Enter to keep the current selection[+], or type selection number:

选择编号 1 切换到 Python 3.10。

注销并重新登录终端以使 Python 版本切换生效。此后,你可以直接使用 python 命令来调用 Python 3.10.14。

安装依赖并准备安装

在 Odoo 服务器上创建一个新系统用户 odoo,用于管理 Odoo 进程,其主目录为 /opt/odoo。这样可以避免因使用 root 用户运行而带来安全风险。

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

安装 Odoo 17 部署所需的系统依赖。

$ sudo dnf install -y git libxslt-devel bzip2-devel openldap-devel libjpeg-devel freetype-devel libpq-devel

安装 Nodejs。Rocky Linux 9 自带 Node 18.x(当前 Nodejs 的 LTS 版本)。不过,我们将使用官方 Nodesource 仓库来安装。

添加 Node 20 仓库。

$ curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -

安装 Nodejs。

$ sudo dnf -y install nodejs

确认 Node 版本。

$ node --version
v20.12.1

使用 Node 安装 Less CSS 包。如果你使用的是从右到左(RTL)书写的语言界面,还需安装 rtlcss 包。

$ sudo npm install -g less rtlcss

安装 wkhtmltopdf。我们将使用 Wkhtmltopdf GitHub 打包仓库中的 RPM 包。撰写本教程时可获取的最新版本为 0.12.6.1 r3。

下载 Wkhtmltopdf 的 RPM 包。

$ cd ~
$ wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox-0.12.6.1-3.almalinux9.x86_64.rpm

安装 Wkhtmltopdf 所需的字体。

$ sudo dnf install xorg-x11-fonts-75dpi.noarch xorg-x11-fonts-Type1.noarch

安装 Wkhtmltopdf。

$ sudo rpm -i wkhtmltox-0.12.6.1-3.almalinux9.x86_64.rpm

检查已安装的 wkhtmltopdf 版本。

$ wkhtmltopdf --version
wkhtmltopdf 0.12.6.1 (with patched qt)

下载 Odoo 文件

切换到 Odoo 系统用户。

$ sudo su - odoo

将 Odoo 的 GitHub 仓库克隆到你的系统。

$ git clone https://github.com/odoo/odoo.git --depth 1 --branch 17.0 --single-branch

在我们的部署中,Odoo 将被放置到 /opt/odoo 目录中进行安装。这将创建 /opt/odoo/odoo 目录,我们将使用该目录完成安装。

搭建 Virtualenv Python 环境

此步骤为可选项,但强烈推荐,因为为 Odoo 使用独立的 Python 虚拟环境有助于避免与操作系统自带 Python 模块产生冲突,尤其是在进行系统升级时。

为此,我们将使用 virtualenv。

  • 为 Odoo 创建一个新的 virtualenv 环境。$ python3 -m venv odoo-env
  • 激活虚拟环境。我们在系统用户的主目录下创建该环境,你也可以自由选择任意位置。$ source odoo-env/bin/activate
  • 为保险起见,更新 PIP。(odoo-env) $ pip3 install --upgrade pip
  • 在虚拟环境中安装 Python 的 wheel 包。$ pip3 install wheel

为 Odoo 创建一个新的 virtualenv 环境。

$ python3 -m venv odoo-env

激活虚拟环境。我们在系统用户的主目录下创建该环境,你也可以自由选择任意位置。

$ source odoo-env/bin/activate

为保险起见,更新 PIP。

(odoo-env) $ pip3 install --upgrade pip

在虚拟环境中安装 Python 的 wheel 包。

$ pip3 install wheel

安装 Python 依赖

安装 Odoo 17 所需的 Python 依赖。

$ pip3 install -r /opt/odoo/odoo/requirements.txt

依赖安装需要一些时间,请耐心等待。

通过查看已安装的 Python 模块列表,检查依赖是否安装正确。

$ pip3 list
Package           Version
----------------- --------
attrs             23.2.0
Babel             2.9.1
beautifulsoup4    4.12.3
cached-property   1.5.2
certifi           2024.2.2
cffi              1.16.0
chardet           4.0.0
cryptography      3.4.8
decorator         4.4.2
docopt            0.6.2
docutils          0.17
ebaysdk           2.1.5
freezegun         1.1.0
geoip2            2.9.0
gevent            21.8.0
greenlet          1.1.2
idna              2.10
isodate           0.6.1
Jinja2            3.0.3
libsass           0.20.1
lxml              4.8.0
MarkupSafe        2.0.1
maxminddb         2.6.0
num2words         0.5.10
ofxparse          0.21
passlib           1.7.4
Pillow            9.0.1
pip               24.0
platformdirs      4.2.0
polib             1.1.1
psutil            5.9.0
psycopg2          2.9.2
pyasn1            0.6.0
pyasn1_modules    0.4.0
pycparser         2.22
pydot             1.4.2
pyOpenSSL         21.0.0
pyparsing         3.1.2
PyPDF2            1.26.0
pyserial          3.5
python-dateutil   2.8.1
python-ldap       3.4.0
python-stdnum     1.17
pytz              2024.1
pyusb             1.2.1
qrcode            7.3.1
reportlab         3.6.8
requests          2.25.1
requests-file     2.0.0
requests-toolbelt 1.0.0
rjsmin            1.1.0
setuptools        65.5.0
six               1.16.0
soupsieve         2.5
urllib3           1.26.5
vobject           0.9.6.1
Werkzeug          2.0.2
wheel             0.43.0
xlrd              1.2.0
XlsxWriter        3.0.2
xlwt              1.3.0
zeep              4.1.0
zope.event        5.0
zope.interface    6.2

退出 Python 虚拟环境。

$ deactivate

创建第三方插件目录

$ mkdir /opt/odoo/odoo/custom-addons

该目录应添加到 addons_path 参数中,该参数定义了 Odoo 查找模块的目录位置。随后退出 Odoo 系统用户。

$ exit

第 5 步 - 配置 Odoo

复制默认的 Odoo 配置文件以创建新的配置文件。

$ sudo cp /opt/odoo/odoo/debian/odoo.conf /etc/odoo.conf

打开该文件进行编辑。

$ sudo nano /etc/odoo.conf

编辑该文件,使其内容如下。

[options]
; This is the password that allows database operations:
admin_passwd = admin
db_host = postgresql.yourdomain.com
db_port = False
db_user = odoo
db_password = odoo_password
addons_path = /opt/odoo/odoo/addons, /opt/odoo/odoo/custom-addons
xmlrpc_port = 8069
default_productivity_apps = True

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

admin_passwd 选项是在 Odoo 图形界面中执行管理操作的密码。请务必设置一个安全的密码。

db_host 选项是 PostgreSQL 服务器的 FQDN 或 IP 地址。

db_port 选项设为 false,因为使用的是 PostgreSQL 默认端口 5432。如果你想使用其他端口,需要修改此值。

db_user 选项是 PostgreSQL 用户的名称。

db_password 选项是我们在 PostgreSQL 服务器上先前创建的 'odoo' 用户的密码。

addons_path 选项是默认的插件路径。你也可以通过逗号分隔添加自定义的插件路径。

xmlrpc_port 选项是 Odoo 监听的端口。

default_productivity_apps 选项确保默认的生产力应用(即员工、邮件营销、项目和调查)保持启用。这四个应用是 Odoo 社区版(Community Edition)的默认应用。在企业版(Enterprise)中,还有额外的生产力应用默认可启用,包括预约、知识库、排班和签章。

创建 Odoo 服务

为确保 Odoo 在系统重启后依然保持运行,我们需要为其创建一个系统服务。

创建文件 /lib/systemd/system/odoo-server.service 并打开进行编辑。

$ sudo nano /lib/systemd/system/odoo-server.service

在其中粘贴以下代码。

[Unit]
Description=Odoo Open Source ERP and CRM
Requires=postgresql-16.service
After=network.target postgresql-16.service

[Service]
Type=simple
SyslogIdentifier=odoo-server
User=odoo
Group=odoo
ExecStart=/opt/odoo/odoo-env/bin/python3 /opt/odoo/odoo/odoo-bin --config=/etc/odoo.conf --addons-path=/opt/odoo/odoo/addons/ --logfile /var/log/odoo/odoo-server.log
WorkingDirectory=/opt/odoo/odoo/
StandardOutput=journal+console
KillMode=mixed

[Install]
WantedBy=multi-user.target

将 /home/ 替换为你安装 Python 虚拟环境时选择的路径。

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

创建 Odoo 日志目录

$ sudo mkdir /var/log/odoo

设置文件权限

设置 odoo-server.service 文件的权限,使其仅能被 Odoo 用户读取或执行。

$ sudo chmod 755 /lib/systemd/system/odoo-server.service
$ sudo chown odoo: /lib/systemd/system/odoo-server.service

设置 Python 环境、Odoo 安装目录以及日志目录的归属。

$ sudo chown -R odoo: /opt/odoo/
$ sudo chown -R odoo: /opt/odoo/odoo-env
$ sudo chown -R odoo: /var/log/odoo

限制 Odoo 配置文件的访问权限。

$ sudo chown odoo: /etc/odoo.conf
$ sudo chmod 640 /etc/odoo.conf

启动 Odoo 服务

启动并启用 Odoo 服务。

$ sudo systemctl start odoo-server
$ sudo systemctl enable odoo-server

检查服务状态。

$ sudo systemctl status odoo-server
? odoo-server.service - Odoo Open Source ERP and CRM
     Loaded: loaded (/usr/lib/systemd/system/odoo-server.service; enabled; preset: disabled)
     Active: active (running) since Tue 2024-04-09 23:59:38 UTC; 1s ago
   Main PID: 102598 (python3)
      Tasks: 4 (limit: 10736)
     Memory: 69.6M
        CPU: 895ms
     CGroup: /system.slice/odoo-server.service
             ??102598 /opt/odoo/odoo-env/bin/python3 /opt/odoo/odoo/odoo-bin --config=/etc/odoo.conf --addons-path=/opt/odoo/odoo/addons/ --logfile /var/log/odoo/odoo-server.log

Apr 09 23:59:38 odoo.yourdomain.com systemd[1]: Started Odoo Open Source ERP and CRM.

第 6 步 - 安装并配置 Nginx

Rocky Linux 9 自带较旧版本的 Nginx。你需要使用官方 Nginx 仓库来安装最新版本。

创建并打开文件 /etc/yum.repos.d/nginx.repo 进行编辑。

$ sudo nano /etc/yum.repos.d/nginx.repo

在其中粘贴以下代码。

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。我们将使用 Nginx 的 mainline 版本,因此在上述文件中通过将 mainline 段落下的 enabled 设为 1 启用了 mainline 仓库,而非 stable 版本。你也可以任选其一。

安装 Nginx。

$ sudo dnf install -y nginx

验证安装。

$ nginx -v
nginx version: nginx/1.25.4

启用并启动 Nginx 服务。

$ sudo systemctl enable nginx --now

检查服务状态。

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: active (running) since Wed 2024-04-10 06:52:14 UTC; 3s ago
       Docs: http://nginx.org/en/docs/
    Process: 103452 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 103453 (nginx)
      Tasks: 3 (limit: 10736)
     Memory: 3.1M
        CPU: 17ms
     CGroup: /system.slice/nginx.service
             ??103453 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??103454 "nginx: worker process"
             ??103455 "nginx: worker process"

第 7 步 - 安装 SSL

我们需要安装 Certbot 来生成 Let's Encrypt 提供的免费 SSL 证书。我们将使用 Snapd 包管理器来完成。这需要 EPEL(Extra Packages for Enterprise Linux)仓库的支持。

安装 EPEL 仓库。

$ sudo dnf install -y epel-release

Rocky Linux 9 默认未安装 Snapd。请安装 Snapd 包。

$ sudo dnf install -y snapd

启用并启动 Snap 服务。

$ sudo systemctl enable snapd --now

安装 Snap core 包,并确保你的 Snapd 版本为最新。

$ sudo snap install core
$ sudo snap refresh core

创建 Snapd 运行所需的符号链接。

$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh

安装 Certbot。

$ sudo snap install --classic certbot

使用以下命令创建指向 /usr/bin 目录的符号链接,以确保 Certbot 命令可被直接调用。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

验证 Certbot 是否正常工作。

$ certbot --version
certbot 2.10.0

生成证书。我们还需要创建一个 DHParams 证书。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d odoo.yourdomain.com

生成 Diffie-Hellman 密钥交换证书。

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

检查 Certbot 续期调度服务。

$ sudo systemctl list-timers

你会发现 snap.certbot.renew.service 是计划运行的服务之一。

NEXT                        LEFT          LAST                        PASSED   UNIT                         ACTIVATES
....                        ....          ....                        ......   ....                         .........
Wed 2024-04-10 13:32:11 UTC 1h 42min left Wed 2024-04-10 11:43:41 UTC 5min ago dnf-makecache.timer          dnf-makecache.service
Wed 2024-04-10 19:08:00 UTC 7h left       -                           -        snap.certbot.renew.timer     snap.certbot.renew.service
Thu 2024-04-11 00:00:00 UTC 12h left      Wed 2024-04-10 00:00:36 UTC 11h ago  logrotate.timer              logrotate.service

对该过程进行一次空运行(dry run),检查 SSL 续期是否正常工作。

$ sudo certbot renew --dry-run

如果未出现错误,说明一切就绪,你的证书将自动续期。

第 8 步 - 配置 Nginx

要通过 Nginx 运行 Odoo,我们需要让 Odoo 监听本地(localhost)。为此,请先停止 Odoo 服务。

$ sudo systemctl stop odoo-server

打开 Odoo 服务器配置文件。

$ sudo nano /etc/odoo.conf

向其中添加以下行。

xmlrpc_interface = 127.0.0.1
proxy_mode = True

为 Odoo 创建一个 Nginx 配置文件。

$ sudo nano /etc/nginx/conf.d/odoo.conf

粘贴以下代码。

#odoo server
upstream odoo {
 server 127.0.0.1:8069;
}
upstream odoochat {
 server 127.0.0.1:8072;
}
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}
map $sent_http_content_type $content_type_csp {
    default "";
    ~image/ "default-src 'none'";
}

# http -> https
server {
   listen 80;
   listen [::]:80;
   server_name odoo.yourdomain.com;
   return 301 https://$host$request_uri;
}

server {
 listen 443 ssl;
 listen [::]:443 ssl;
 http2 on;
 http3 on;
 quic_retry on;

 server_name odoo.yourdomain.com;

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

 # Add Headers for odoo proxy mode
 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/odoo.yourdomain.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/odoo.yourdomain.com/privkey.pem;
 ssl_trusted_certificate /etc/letsencrypt/live/odoo.yourdomain.com/chain.pem;

 ssl_session_timeout 30m;
 ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
 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_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
 ssl_prefer_server_ciphers off;
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_dhparam /etc/ssl/certs/dhparam.pem;

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

 # Redirect longpoll requests to odoo longpolling port
 location /longpolling {
   proxy_pass http://odoochat;
 }

 location /websocket {
   proxy_pass http://odoochat;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection $connection_upgrade;
   proxy_set_header X-Forwarded-Host $http_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;
   proxy_cookie_flags session_id samesite=lax secure;  # requires nginx 1.19.8
 }

 # Redirect requests to odoo backend server
 location / {
  # Add Headers for odoo proxy mode
   proxy_set_header X-Forwarded-Host $http_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;
   proxy_redirect off;
   proxy_pass http://odoo;
   proxy_cookie_flags session_id samesite=lax secure;  # requires nginx 1.19.8
 }

 # common gzip
 gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript;
 gzip on;

 # Serve static files right away
 location ~ ^/[^/]+/static/.+$ {
   # root and try_files both depend on your addons paths
   root /opt/odoo/odoo;
   try_files /opt/odoo/odoo/addons$uri @odoo;
   expires 24h;
   add_header Content-Security-Policy $content_type_csp;
 }
}

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

打开文件 /etc/nginx/nginx.conf 进行编辑。

$ sudo nano /etc/nginx/nginx.conf

在 include /etc/nginx/conf.d/*.conf; 这一行之前添加以下行。

server_names_hash_bucket_size 64;

按 Ctrl + X 并在提示时输入 Y 保存文件。

测试 Nginx 配置。

$ sudo nginx -t

如果未出现错误,说明配置无误,可以重启 Nginx 服务了。

$ sudo systemctl restart nginx

第 9 步 - 启动 Odoo

完成所有配置后,我们可以重新启动 Odoo 服务。

$ sudo systemctl start odoo-server

在你的浏览器中通过 https://odoo.yourdomain.com 访问 Odoo。也可以在浏览器中打开 http://<你的IP地址>:8069 或 http://odoo.yourdomain.com:8069。如果一切正常,你将看到 Odoo 的数据库创建界面。

在 Rocky Linux 9 上安装 Odoo 17 ERP 企业管理系统

选择你的邮箱和密码以创建登录凭据。主密码(master password)即你在 /etc/odoo.conf 文件中设置的 admin_passwd。填写其余所有字段。

勾选「演示数据(Demo Data)」字段,以使用样例数据填充数据库。请勿在面向公网的服务器上安装演示数据。包含演示数据的数据库带有默认登录名和密码,可能被他人借此入侵你的系统并造成严重问题,即便在测试/开发环境中也是如此。我们仅出于教程演示目的使用它。

点击「创建数据库(Create database)」按钮以继续完成安装。首次创建数据库时,插件页面加载较慢,请勿刷新页面。数据库创建完成后,系统会自动跳转到如下登录页面。

在 Rocky Linux 9 上安装 Odoo 17 ERP 企业管理系统

输入上一步创建的凭据登录 Odoo ERP,随后将进入如下所示的控制台(dashboard)页面。页面会预先填充演示数据。如果你在数据库创建页面没有勾选演示数据选项,则会看到一个不同的、更简洁的控制台。

在 Rocky Linux 9 上安装 Odoo 17 ERP 企业管理系统

从此刻起,你就可以开始使用 Odoo 来管理你的业务了。

第 10 步 - 更新 Odoo

停止 Odoo 服务。

$ sudo systemctl stop odoo-server

切换到 Odoo 系统用户。

$ sudo su - odoo

从 GitHub 拉取最新源代码。

$ git fetch
$ git rebase --autostash

如果你手动修改过源代码,第二条命令可能会遇到代码冲突。系统会列出冲突的文件,你需要手动修改这些文件并重新运行该命令以解决问题。

如果你想放弃这些冲突的更改,可以运行以下命令重置源代码。

$ git reset --hard

激活 Python 虚拟环境。

$ source odoo-env/bin/activate

安装 Python 依赖。

$ pip3 install -r /opt/odoo/odoo/requirements.txt

退出 Python 虚拟环境。

$ deactivate

启动 Odoo 服务。

$ sudo systemctl start odoo-server

第 11 步 - 使用 Fail2Ban 加固 Odoo

此步骤为可选项,但如果你已安装 Fail2Ban,可以为 Odoo 添加配置以对其进行保护。

创建并打开 odoo-login.conf 文件进行编辑。

$ sudo nano /etc/fail2ban/jail.d/odoo-login.conf

在其中粘贴以下代码。

[odoo-login]
enabled = true
port = http,https
bantime = 900  ; 15 min ban
maxretry = 10  ; if 10 attempts
findtime = 60  ; within 1 min  /!\ Should be adjusted with the TZ offset
logpath = /var/log/odoo.log  ;  set the actual odoo log path here

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

创建并打开 odoo-login.conf 过滤器文件进行编辑。

$ sudo nano /etc/fail2ban/filter.d/odoo-login.conf

在其中粘贴以下代码。

[Definition]
failregex = ^ \d+ INFO \S+ \S+ Login failed for db:\S+ login:\S+ from <HOST>
ignoreregex =

按 Ctrl + X 关闭编辑器,并在提示保存时按 Y。

重启 Fail2Ban。

$ sudo systemctl restart fail2ban

总结

至此,我们关于在 Rocky Linux 9 服务器上安装和配置 Odoo 的教程就结束了。如果你有任何疑问,请在下方评论区留言。