Odoo:自建开源ERP系统

如何拉起开箱即用的企业级应用全家桶 Odoo,并使用 Pigsty 管理其后端 PostgreSQL 数据库。

Odoo 是一个开源的企业级 ERP 系统,提供了从 CRM、销售、采购、库存、生产、财务等全方位的企业管理功能。Odoo 也是一个典型的 Web 应用,底层使用 PostgreSQL 数据库作为存储。

将你所有的业务都汇总入一个平台,简单,高效,省钱,你自己的 ERP!


快速上手

在 “网络条件良好” 的情况下,你可以通过以下命令快速拉起一个 Odoo 实例,使用由 Pigsty 管理的外部 PostgreSQL 数据库:

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty 
pig sty init               # 安装 Pigsty
./bootstrap                # 安装 Pigsty 依赖
./configure -c app/odoo    # 使用 Odoo 配置模板 (请在这一步修改生成配置文件 pigsty.yml 中的各种密码!)
./install.yml              # 安装 Pigsty
./docker.yml               # 安装 Docker 模块
./app.yml                  # 拉起 Odoo

Odoo 默认监听在 8069 端口,你可以通过浏览器访问 http://<ip>:8069。默认的用户名和密码都是: admin

请注意,Odoo 无状态部分使用 Docker 拉起,然而中国大陆 DockerHub 被墙, 你可能需要参考教程 来配置 镜像站代理服务器 方可顺利完成最后一步。 在 Pigsty 商业版 中,我们可以帮您丝滑解决这个问题。


配置文件

conf/app/odoo.yml 中有一个模板配置文件,定义了单机 Odoo 所需的资源。

configure 之后,您应该根据自己的实际需求,修改这里的密码类参数。请注意修改密码务必匹配:例如你如果在 pg_users 中修改了 odoo 数据库用户的密码, 那么也同样要修改 all.children.odoo.vars.apps.<odoo>.conf.PG_PASSWORD 参数,以确保 Odoo 与 PostgreSQL 数据库的连接正常。

all:
  children:

    # the odoo application (default username & password: admin/admin)
    odoo:
      hosts: { 10.10.10.10: {} }
      vars:
        app: odoo   # specify app name to be installed (in the apps)
        apps:       # define all applications
          odoo:     # app name, should have corresponding ~/app/odoo folder
            file:   # optional directory to be created
              - { path: /data/odoo         ,state: directory, owner: 100, group: 101 }
              - { path: /data/odoo/webdata ,state: directory, owner: 100, group: 101 }
              - { path: /data/odoo/addons  ,state: directory, owner: 100, group: 101 }
            conf:   # override /opt/<app>/.env config file
              PG_HOST: 10.10.10.10            # postgres host
              PG_PORT: 5432                   # postgres port
              PG_USERNAME: odoo               # postgres user
              PG_PASSWORD: DBUser.Odoo        # postgres password
              ODOO_PORT: 8069                 # odoo app port
              ODOO_DATA: /data/odoo/webdata   # odoo webdata
              ODOO_ADDONS: /data/odoo/addons  # odoo plugins
              ODOO_DBNAME: odoo               # odoo database name
              ODOO_VERSION: 18.0              # odoo image version

    # the odoo database
    pg-odoo:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-odoo
        pg_users:
          - { name: odoo    ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_admin ] ,createdb: true ,comment: admin user for odoo service }
          - { name: odoo_ro ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_readonly ]  ,comment: read only user for odoo service  }
          - { name: odoo_rw ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_readwrite ] ,comment: read write user for odoo service }
        pg_databases:
          - { name: odoo ,owner: odoo ,revokeconn: true ,comment: odoo main database  }
        pg_hba_rules:
          - { user: all ,db: all ,addr: 172.17.0.0/16  ,auth: pwd ,title: 'allow access from local docker network' }
          - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }

    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

  vars:                               # global variables
    version: v3.3.0                   # pigsty version string
    admin_ip: 10.10.10.10             # admin node ip address
    region: default                   # upstream mirror region: default|china|europe
    node_tune: oltp                   # node tuning specs: oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql tuning specs: {oltp,olap,tiny,crit}.yml

    docker_enabled: true              # enable docker on app group
    #docker_registry_mirrors: ["https://docker.m.daocloud.io"] # use dao cloud mirror in mainland china
    proxy_env:                        # global proxy env when downloading packages & pull docker images
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.tsinghua.edu.cn"
      #http_proxy:  127.0.0.1:12345 # add your proxy env here for downloading packages or pull images
      #https_proxy: 127.0.0.1:12345 # usually the proxy is format as http://user:pass@proxy.xxx.com
      #all_proxy:   127.0.0.1:12345

    infra_portal: # domain names and upstream servers
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }
      minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      odoo         : { domain: odoo.pigsty, endpoint: "127.0.0.1:8069"   ,websocket: true }  #cert: /path/to/crt ,key: /path/to/key
      # setup your own domain name here ^^^, or use default domain name, or ip + 8069 port direct access
      # certbot --nginx --agree-tos --email your@email.com -n -d odoo.your.domain    # replace with your email & odoo domain

    #----------------------------------#
    # Credential: CHANGE THESE PASSWORDS
    #----------------------------------#
    #grafana_admin_username: admin
    grafana_admin_password: pigsty
    #pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    #pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor
    #pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    #patroni_username: postgres
    patroni_password: Patroni.API
    #haproxy_admin_username: admin
    haproxy_admin_password: pigsty

    repo_modules: infra,node,pgsql,docker
    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, pgsql-utility, docker ]
    repo_extra_packages: [ pg17-main ]
    pg_version: 17

Odoo 扩展插件

社区中有很多可用的 Odoo 模块,你可以通过下载并将它们放置在 addons 文件夹中来安装它们。

在上面的配置文件中,addons 目录默认为 /data/odoo/addons,把扩展 zip 包放进该目录即可将其“安装”。

要启用这些模块,首先在 Odoo 中进入 开发者模式

Settings -> Generic Settings -> Developer Tools -> Activate the developer Mode

然后,转到 > Apps -> Update Apps List, 然后你可以在面板中找到这些额外的模块并安装它们。

经常使用的免费模块请 参考这里 ,当然以及大家最需要的 Accounting Kit 模块。


对外服务

您可以直接用 IP 地址访问目标服务器上的 8069 端口,访问 Odoo Web 界面,但显然这样的方式对于严肃的场景过于儿戏。 以下是如何使用域名访问 Odoo 的说明与 Pigsty 配置方法:

在上面的配置文件中,已经为 Odoo 设置了在 Infra Nginx 上的反向代理,因此您可以通过 odoo.pigsty 的域名访问 Odoo 网络界面。

infra_portal: # 定义 Nginx 服务器配置
  # ...
  odoo : { domain: odoo.pigsty, endpoint: "127.0.0.1:8069" ,websocket: true }  #cert: /path/to/crt ,key: /path/to/key

如果您想要使用其他域名,请相应修改 domain 参数,如果您的 Odoo 部署在其他服务器上,请相应修改 endpoint 参数。 然后执行 ./infra.yml -t nginx_config,nginx_reload 生效。

在任何情况下通过域名访问 Odoo 都需要配置 DNS 解析,有三种典型的配置方式:

  • 使用真域名,通过云厂商/DNS服务商的解析服务,指向你的服务器公网IP
  • 使用内网 DNS,在你的内网 DNS 服务上添加指向你服务器的内网IP地址
  • 使用本地静态 DNS,在你览器所在主机(/etc/hosts)添加一条静态解析记录

HTTPS证书

如果您想要通过 HTTPS 访问 Odoo 服务,则需要申请 HTTPS 证书。

Pigsty 默认会为你的 Odoo 服务生成一个 “自签名CA” 生成的证书,这个证书是不被浏览器信任的,因此在浏览器中会提示不安全。你可以选择:

  • “我知道不安全,继续访问”
  • 使用 Chrome 浏览器时,你也可以使用敲击键入 thisisunsafe 来绕过证书验证
  • 将 Pigsty 创建的 pigsty-ca 加入信任的根 CA 列表。
  • 花钱当大冤种去买 HTTPS 证书
  • 使用 certbot 申请免费的 HTTPS 证书 (正规且推荐!)

如果你已经有 HTTPS 证书,你可以在 infra_portal 中指定 certkey

infra_portal:
  # ...
  odoo : { domain: odoo.pigsty.cc, endpoint: "127.0.0.1:8069" ,websocket: true ,cert: /etc/cert/odoo.pigsty.cc.crt   ,key: /etc/cert/odoo.pigsty.cc.key  }

然后使用 ./infra.yml -t nginx_config,nginx_launch 更新服务器配置并使其生效 。


免费HTTPS证书

如果你不想当大冤种花钱去买 HTTPS 证书,最简单的办法是使用 Let’s Encrypt 的免费 HTTPS 证书。

Pigsty 默认集成了 certbot,这里是 详细的教程,核心就是以下这行命令:

certbot --nginx --agree-tos --email your@email.com -n -d odoo.pigsty.cc

把上面的 email 换成你自己的邮件地址,域名换成你的域名,然后按照提示操作即可,全自动申请与配置。

请注意,使用 certbot 申请免费的 HTTPS 证书需要:

  • 你的服务器有网络访问,且可以通过公网访问(80/443端口)。
  • 你的域名正确指向这台服务器的公网IP地址,即在域名服务商处配置了正确的 A 记录

使用 Certbot 申请完证书后,默认会修改 Nginx 的配置文件,将 HTTP 服务器重定向到 HTTPS 服务器,而这可能并非你想要的。 你可以通过修改 Pigsty 配置文件中的 infra_portal 参数,将 Certbot 已经 成功签发证书的域名配置到 Nginx 的配置文件中。

infra_portal:
  # ...
  odoo : { domain: odoo.pigsty.cc, endpoint: "127.0.0.1:8069" ,websocket: true ,cert: /etc/cert/odoo.pigsty.cc.crt ,key: /etc/cert/odoo.pigsty.cc.key  }

这里,修改签发证书的服务器定义项,添加 certbot: <domain-name> ,这里的 <domain-name> 指的是 certbot 签发的文件名。 通常与 domain 一样,但如果你同时申请多个域名证书,certbot 会将其合并为一个证书,比如这里合并为两个文件:

Certificate is saved at: /etc/letsencrypt/live/pigsty.cc/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/pigsty.cc/privkey.pem

因此将证书中间的 pigsty.cc 抽出来填入 certbot,然后重新运行:

./infra.yml -t nginx_config,nginx_launch

即可让 Pigsty 重新生成 Nginx 配置文件,回退 Certbot 对配置进行的其他修改,只保留申请的证书。 以后需要续期更新证书的时候就不需要重复这个过程了,直接使用 certbot renew 即可。


最后修改 2025-02-27: update release note (bf999b0)