通过源码安装 Odoo
安装依赖
使用Debian发行版时,默认登录用户为带有管理员权限的 root,这时命令行显示的为#。在Ubuntu系统中,禁用了 root 账号,在安装时配置的初始用户可通过 sudo 来运行 root 权限的命令。首先我们应更新包索引,然后执行升级来确保所有安装的程序是最新的,命令如下:
sudo apt update
sudo apt upgrade -y
下一步,我们将安装PostgreSQL数据库,并让当前用户成为数据库超级用户,命令如下:
sudo apt install postgresql -y
sudo su -c "createuser -s $USER" postgres
我们将通过源码运行 Odoo,但在那之前,我们需要安装所需依赖。以下是所需的Debian包:
sudo apt-get install git python3-dev python3-pip -y
sudo apt install build-essential libxslt-dev libzip-dev libldap2-dev libsasl2-dev libssl-dev -y
还应记得安装打印报表所需的wkhtmltox,命令如下:
sudo apt-get install wkhtmltopdf
在 Odoo 的requirements.txt文件中。我们可以使用如下命令安装这些包:
wget https://raw.githubusercontent.com/odoo/odoo/12.0/requirements.txt
sudo -H pip3 install -r requirements.txt
既然我们有了所有的依赖,安装了数据库服务、系统包和 Python 包,我们就可以安装 Odoo 了。
准备独立的系统用户
从安全角度建议使用独立的用户运行 Odoo,这一用户不带有任何系统的特权。为此我们需要创建系统和数据库用户,使用命令如下:
sudo adduser --disabled-password --gecos "Odoo" odoo
sudo su -c "createuser odoo" postgres
createdb --owner=odoo odoo-prod
以上odoo 为用户名,odoo-prod用于运行 Odoo 实例的数据库名。odoo用户成为了odoo-prod数据库的所有者。也就说它对该数据库有创建和删除的权限,包括删除整个数据库的权限。如果你运行的是多租户服务器,应为每个租户创建一个类似 odoo 的指定系统用户。
小贴士:Odoo的设计即使在系统用户不是数据库所有者时也可以正确运行。但这可能会让设置变复杂,并且固化安全的好习惯是有一个主系统用户作为数据库的所有者、为每个实例创建一个指定的不带有超级用户权限的系统用户来运行服务。
注意这些是没有管理权限的普通用户,新建系统用户时会自动创建一个家目录。比如/home/odoo,用户可通过~快捷符号来表示自己的家目录。我们在用户 Odoo 对应的配置和文件中会使用到它。我们可以使用如下命令来以该用户打开一个会话:
sudo su odoo
exit
exit
命令终止会话并回到原用户。
源码安装
要不了多久,你的服务就会需要升级、打补丁。这时版本控制仓库会很有帮助。我们使用 git来从仓库中获取代码,就像我们在安装开发环境时的操作一样。下面我将使用 odoo 用户并将代码下载家目录中:
sudo su odoo
git clone https://github.com/odoo/odoo.git /home/odoo/odoo-12 -b 12.0 --depth=1
-b
选项确保获取的是正确的分支,–depth=1
选项会忽略修改历史并仅获取最新修订的代码,这样下载内容更精简,速度也更快。
小贴士:git在管理 Odoo 部署版本时是一个非常有价值的工具。注意本系列文章中仅仅涉及到代码版本管理的冰山一角。想要更加熟悉 git,值得花时间进一步学习,可从http://git-scm.com/doc开始。
到此为止,我们应该已经拥有源码安装 Odoo 的所有内容。可通过如下命令以指定用户会话检查是否正确启动并退出:
$ /home/odoo/odoo-12/odoo-bin --version
Odoo Server 12.0
$ exit
下面我们将设置一些在系统中使用的系统级别的文件和目录。
设置配置文件
在启动 Odoo 服务时添加–save参数会将配置保存到~/.odoorc文件中。我们将以这个文件作为服务配置的初始文件,将其保存到/etc/odoo下,使用命令如下:
sudo su -c "~/odoo-12/odoo-bin -d odoo-prod --db-filter='^odoo-prod$' --without-demo=all -i base --save --stop-after-init" odoo
这行命令中也会包含服务实例所使用的配置参数。
小贴士:老版本中的.openerp_serverrc配置文件还被支持,找到后会进行使用。如果安装 Odoo 10或之后版本的服务器上同时还安装了老版本的 Odoo,可能会引起混淆。这时你会发现–save选项没有更新.odoorc,而是更新了.openerp_serverrc文件。
下一步我们需要将配置文件放到系统的配置文件目录/etc 下,命令如下:
sudo mkdir /etc/odoo
sudo cp /home/odoo/.odoorc /etc/odoo/odoo.conf
sudo chown -R odoo /etc/odoo
sudo chmod u=r,g=rw,o=r /etc/odoo/odoo.conf # 安全加固使用
以上命令最后一行是可选的,但它提升了系统的安全性。它确保运行 Odoo 进程的用户可以读取但无法修改配置文件。这时你将无法修改数据库主密码,但在生产服务下这不是什么问题,因为应使用list_db=False
服务配置来禁用网页数据库管理员。我们还需为 Odoo 服务创建一个存储日志文件的目录。这通常放在/var/log
目录下,命令如下:
sudo mkdir /var/log/odoo
sudo chown odoo /var/log/odoo
现在让我们通过如下命令编辑配置文件并确保已配置了一些重要参数:
sudo nano /etc/odoo/odoo.conf
以下是大部分重要参数的推荐值:
[options]addons_path = /home/odoo/odoo-12/odoo/addons,/home/odoo/odoo-12/addons
admin_passwd = False
db_name = odoo-prod
dbfilter = ^odoo-prod$
http_port = 8069
list_db = False
logfile = /var/log/odoo/odoo-server.log
proxy_mode = True
without_demo = all
workers = 6
下面逐一讲解:
-
addons_path
是一组逗号分隔的用于查找插件模块的路径。读取顺序为从左到右,最左边目录的优先级最高。 -
admin_passwd
是访问网页客户端数据库管理功能的主密码。一定要设置复杂的密码,或者最好是设为 False来关闭这一功能。 -
db_name
是在服务启动时初始化的数据库实例。 -
dbfilter
用于过滤可访问的数据库,它是一个 Python 解释的正则表达式。为使用户无需弹出窗口选择数据库,并使未经身份验证的 URL 可正常运作,应设置为^dbname。它支持%h和%d占位符,由 HTTP 请求主机名和子域名进行替换。 -
http_port
是服务器监听的端口号,默认使用的是8069 -
list_db = False
在 RPC级别和 UI 上屏蔽数据库列表,并屏蔽数据库管理界面以及相应的 RPC 功能。 -
logfile
是服务日志写入的位置。对于系统服务,一般位于/var/log文件夹内。如果留空,日志会转而在标准输出中打印。 -
proxy_mode
在需要反向代理访问时应设为True,我们需要用到反向代理。 -
without_demo
在生产环境中应进行设置,这样新建的数据库中不会带有演示数据。 -
workers
的值在大于等于2时启用多进程,一会儿我们会进一步的讨论。
ℹ️Odoo 10中引入
http_port
参数来替代老版本中使用但现在已淘汰了的xmlrpc_port
参数。
从安全角度看,admin_passwd=False
和list_db=False
选项尤为重要。它们屏蔽掉对数据库管理功能的网页端访问,在生产环境和面向外网的 Odoo 服务中都应进行设置。
以下也是会用到的参数:
-
data_dir
是会话数据和附件存储的路径,记住将备份放在这里 -
http_interface
设置监听的地址。默认监听0.0.0.0,但在使用反向代理时应设置为127.0.0.1来仅响应本地请求。Odoo 11中引入它来代替淘汰了的xmlrpc_interface
参数。
我们可通过-c
或–config
选项来检查运行服务的设置:
sudo su -c "~/odoo-12/odoo-bin -c /etc/odoo/odoo.conf" odoo
通过上述设置运行 Odoo 不会在终端中有任何输出,因为修改都写到了配置文件中定义的日志文件中了。要追踪服务的操作,我们需要在终端中运行如下命令:
sudo tail -f /var/log/odoo/odoo-server.log
有时可能会需要将日志输出到标准输出中,最好的方法是复制一份不带logfile选项的配置文件。
小贴士:要在同一个终端窗口中运行多个终端会话,可以使用tmux这样的应用或者GNU Screen。可以使用Byobu,它基于GNU Screen或Tmux提供了好看的用户界面。
多进程工作进程
生产实例可能会处理大量的工作负载。默认服务运行单进程并只能使用CPU 的一个核心来处理请求,这是因为Python语言的全局解释器锁(GIL)。但是可使用多进程模式来处理并发请求,来充分利用多核的优势。workers=N选项设置使用的工作进程数,作为一个参照,可设置为1+2*P,其中 P为处理器的核数。最佳设置需要根据具体情况进行调优,因为这取决于服务器的负载以及多少其它像PostgreSQL这样大负载服务在运行。
为负载将workers设置高比低好,最低值应为6,因为这是大多数浏览器的并行连接数,最大值通常受服务器的 RAM 所限。普通使用模式的经验是,Odoo服务应能处理(1+2P)6个并发用户。
还有一些limit-配置参数可用于调优工作进程。在达到这些值时工作进程会被回收,相应的进程会停止并启动一个新进程。这可以防止服务器内存溢出以及防止某一进程过度使用服务器资源。
官方文档中对工作进程参数调优也给出了一些很好的建议,欲知详情,请参照官方文档Odoo 部署。
设置 Odoo 为系统服务
现在我们需要将 Odoo 设为系统服务,并在系统启动时自动开启。
在Ubuntu或Debian中,init程序负责服务的启动。Debian或其分支操作系统曾使用过sysvinit,Ubuntu曾使用过兼容的名为Upstart的启动程序。但最近都进行了修改,最新的Debian和Ubuntu发行版的init程序都使用了systemd。这表示现在有两种方式来安装系统服务,你需要根据操作系统的版本来选择正确的方法。Ubuntu 16.04或之后的版本中应使用systemd,但是很多云服务商还在使用更早的版本,所以很有可能你也会使用到这些老版本。要检查系统中是否使用systemd,可使用如下命令:
man init
这条命令会打印当前使用的 init 程序的文档,然后就可以查看所使用的启动服务。
ℹ️Window的子系统(WSL) 中的 Ubuntu环境仅适用于开发,它有可能发生些异常问题,完全不适合用于运行生产环境。在写本文时,man init显示启动服务为systemd,但并不能安装systemd服务,反而安装sysvinit服务时是正常的。
补充:如出现-bash: man: command not found,则通过sudo apt install man -y来执行安装
创建systemd服务
如果你使用的是较近的操作系统,如Debian 8或Ubuntu 16.04,你的启动服务就应该是systemd。要在系统中添加服务,只需创建一个描述服务的文件。我们创建/lib/systemd/system/odoo.service文件并加入如下内容:
[Unit]
Description=Odoo
After=postgresql.service
[Service]
Type=simple
User=odoo
Group=odoo
ExecStart=/home/odoo/odoo-12/odoo-bin -c /etc/odoo/odoo.conf
[Install]
WantedBy=multi-user.target
小贴士:Odoo源码中在debian/下包含一个odoo.service文件示例。你可以不用新建方件,直接把拷贝该文件然后进行所需修改。至少需要根据设置来修改ExecStart选项。
下一步我们需要使用如下命令来注册这个新服务:
sudo systemctl enable odoo.service
使用如下命令启动该服务:
sudo systemctl start odoo
使用如下命令检查该服务状态:
sudo systemctl status odoo
最后,如需停止服务,请使用如下命令:
sudo systemctl stop odoo
使用命令行检查 Odoo 服务
现在我们可以确定Odoo实例是否运行以及是否能正常对请求进行响应。如果Odoo正常运行,我们应该可以得到响应并且日志文件中不会报错。在服务器上通过如下命令可检测 Odoo 是否对HTTP请求进行响应:
curl http://localhost:8069
<html><head><script>window.location = '/web' + location.hash;</script></head></html>
此外通过如下命令可查看日志文件的内容:
sudo less /var/log/odoo/odoo-server.log
你还可以使用tail -f 来实时查看日志文件中新增的内容:
sudo tail -f /var/log/odoo/odoo-server.log
设置 Nginx 反向代理
虽然 Odoo 自身可以输出网页,但强烈建议在其上加一层反向代理。反向代理作为一个中间层来管理客户端所发送请求以及 Odoo 服务作出响应之间的数据流。使用反向代理有诸多好处。
从安全角度考虑,有以下几点:
-
处理并加固HTTPS协议来对数据流加密
-
隐藏内部网络特征
-
作为应用防火墙,限制所接受处理的 URL
然后从性能角度考虑,反向代理可提供如下显著的改进:
-
缓存静态内容,因而降低 Odoo 服务器的负载
-
压缩内容来加快加载时间
-
作为负载均衡器,在多台服务间分配负载
Apache是在考虑反向代理时的一个常用选择,Nginx 是近期在技术圈被热议的对其的替代。此处我们使用Nginx作为反向代理,并展示如何使用它来实现上述讨论的安全和性能方面的功能。
首先,我们应当安装Nginx,我们需要它监听默认的HTTP端口,所以需要确保没有被其它服务所占用。执行如下命令应该会报错:
$ curl http://localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
如果没有收到错误,应当禁用相应服务来让Nginx使用该端口。例如,关闭已有的Apache服务,使用sudo service apache2 stop。更好的选择是从服务器上删除该服务或重新配置让其监听其它端口,这样Nginx就可以正常使用HTTP和HTTPS端口(80 and 443) 了。
一旦完成上述操作,就可以安装Nginx了:
sudo apt-get install nginx -y
sudo service nginx start # 如尚未启动,启动Nginx服务
curl http://localhost
要确定Nginx是否正确运行,通过浏览器访问或在服务上执行curl http://localhost应该可以得到一个Welcome to nginx页面。
Nginx配置文件和Apache的方式基本相同,存储在/etc/nginx/available-sites/中,并可通过在/etc/nginx/enabled-sites/中添加软链接来激活。注意应同时关闭Nginx安装时默认带有的配置:
sudo rm /etc/nginx/sites-enabled/default
sudo touch /etc/nginx/sites-available/odoo
sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/odoo
使用nano或vi等编辑器来编辑 Nginx配置文件:
sudo nano /etc/nginx/sites-available/odoo
一个基本的针对Odoo服务的Nginx配置文件如下例所示:
upstream odoo {
server 127.0.0.1:8069;
}
upstream odoochat {
server 127.0.0.1:8072;
}
server {
listen 80;
# 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;
# 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;
}
# Redirect requests to odoo backend server
location / {
proxy_redirect off;
proxy_pass http://odoo;
}
# common gzip
gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript;
gzip on;
}
补充:添加域名请在server 配置区内添加对 server_name 的配置
首先为Odoo服务添加了upstream配置,监听了默认端口8069和8072。8069用于网页客户端和RPC请求,8072用于多进程时 Odoo 实时消息所需的长轮询(long polling)请求。
Nginx应在默认HTTP端口80上接收访问流量,然后重定向到upstream odoo服务中。这在server配置区中进行了定义。/longpolling 地址的访问流量会传递到upstream odoochat,剩余的流量则传递到upstream odoo。这里我们还添加了一些请求头的信息,这样 Odoo 后台服务就会知道这些是经过代理的流量。
出于安全考虑,应确保proxy_mode参数设为True。这是因为在Nginx作为代理时,所有的请求都会认为是来自本地而不是远程 IP 地址。在代理中设置X-ForwardedFor头以及启动–proxy-mode可解决这一问题。但是,如果不在代理级别强制header就启用–proxy-mode 会让其他人可以伪装远程地址。
在配置文件的最后,可以看到两条gzip相关的命令,它们用于对一些文件进行压缩,提升性能。可通过如下命令测试配置是否正确:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
如果出现错误,请检查配置文件中输入是否正确。常见的问题是默认的HTTP被其它服务所占用,如Apache或默认的Nginx网站,所以在重启Nginx服务前先通过本文中的命令确保并没有这种问题。在完成处理后,可使用如下命令重新加载新的配置:
sudo /etc/init.d/nginx reload
如果操作系统使用的是systemd,上述命令正确的版本应该是:
sudo systemctl reload nginx
通过如下命令可确认 Nginx 是否将访问流量重定向到了后台Odoo服务中:
$ curl http://localhost
<html><head><script>window.location = '/web' + location.hash;</script></head></html>
缓存静态内容
我们可以配置 Nginx 来缓存服务端静态文件,这样再次请求时就可以访问Nginx 中的缓存,而无需将请求传递到upstream odoo服务中。启用静态内容缓存可带来更快的响应时间并减少 Odoo 服务的工作负载。要启用这一设置,在location /longpolling区之前加入如下代码:
# cache static data
location ~* /web/static/ {
proxy_cache_valid 200 60m;
proxy_buffering on;
expires 864000;
proxy_pass http://odoo;
}
通过这一些命令,静态数据就可以缓存60分钟了。在这个期间的其它请求Nginx 会直接使用缓存进行响应。
服务和模块更新
一旦 Odoo 服务运行了一段时间,就会需要对其进行升级。这包括两个步骤:获取服务或模块的新版本、执行安装。
创建分阶环境
如果你按照通过源码安装 Odoo一节正确地进行了安装,应该就可以在暂存区仓库中获取并测试新版本源码。强烈建议创建一个生产环境数据库的拷贝,并使用它进行升级测试。如果odoo-prod是我们的生产环境数据库,可通过如下命令创建一个拷贝odoo-stage:
dropdb odoo-stage
createdb --owner=odoo odoo-stage
pg_dump odoo-prod | psql -d odoo-stage
sudo su odoo
cd ~/.local/share/Odoo/filestore/
cp -al odoo-prod odoo-stage # create filestore hardlinks
exit
在使用以上数据库拷贝之前,应进行清理,比如停止计划动作、关闭 email 服务(包含发送和接收消息)。根据你的设置来执行这些指定步骤,但通常可使用自动化脚本来执行。记住psql可用于在命令行直接执行SQL命令,如psql -d odoo-stage -c “<SQL命令>”。
小贴士:可通过createdb命令来更快地创建拷贝:createdb –owner=odoo –template=odoo-prod odoo-stage。但需要说明的是要运行该命令,不能有任何对odoo-prod数据库的连接,因此需要停止Odoo生产环境的服务。
更新 Odoo 源码
我们使用git pull 命令来从GitHub仓库获取最新的Odoo源码。在那之前,我们可以使用git tag命令来为当前使用的提交创建一个标签,这样可以可容易的对更新进行撤销,命令如下:
sudo su odoo
cd ~/odoo-12
git tag --force 12-last-prod
git pull
要让代码修改生效,我们需要重启Odoo服务。而要使用数据文件的修改生效,需要对模块进行升级。通常对Odoo稳定版本的修改都是代码的修复,因此无需冒险执行模块升级。如果需要对模块升级,可使用-u <module>附加参数,或者是-u base,它将升级所有模块。
现在可以启动Odoo的分阶服务了,它将使用在分阶数据库上使用升级代码:
~/odoo-12/odoo-bin -d odoo-stage --http-port=8080 -c /etc/odoo/odoo.conf # optionally
add: -u baseexit
Odoo 分阶服务通过在8080端口上进行配置。可通过浏览器访问http://xxx:8080来检查升级代码是否正确运作。如果出现了错误,可通过如下命令来返回上一个版本:
sudo su odoo
cd ~/odoo-12
git checkout 12-last-prod
exit
如果一切运行都如预期,则可安全地执行生产环境服务的升级,通常是通过重启来实现。如果想要执行实际的模块升级,建议的方法是停止服务、运行升级、再重启服务,命令如下:
sudo service odoo stop
sudo su -c "~/odoo-12/odoo-bin -c /etc/odoo/odoo.conf -u base --stop-after-init" odoo
sudo service odoo start
记住对在用Git 版本进行记录,可通过 git checkout回到修改前,这让我们可以在需要的时候进行回滚。强烈推荐在执行数据库升级前保存备份。在完成之后,可使用 Git 拉取新的版本到生产仓库并完成升级:
sudo su odoo
cd ~/odoo-12
git tag --force 12-last-prod
git pull
exit
sudo service odoo restart # or: sudo systemctl restart odoo