> For the complete documentation index, see [llms.txt](https://espier.gitbook.io/espier/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://espier.gitbook.io/espier/xi-tong-bu-shu/bu-shu-fang-an/install.md).

# 单机部署方案

## 约定

* 操作系统：Centos 7.0 x64
* 域名: 文档内域名规划参见 [系统部署/准备/域名](https://github.com/bryantyan/espier-docs/tree/f1b72d96424898684552cce9df5b400d91b18a9b/deploy/deploy/prepare/domain.md)
* 操作权限: root

## 服务清单

* supervisorctl > 3.0
* neo4j 3.5.x
* mysql 5.7
* nginx + fpm
* npm > 6.0
* redis \~ 4.x
* php 7.2

## 基础服务部署

### 调整时间

```
timedatectl set-timezone Asia/Shanghai
```

### 安装sudo

```
yum install sudo
```

### 安装PHP

```
yum -y install epel-release
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install yum-utils
yum-config-manager --enable remi-php72

yum install php72 \
            php72-php-gd \
            php72-php-json \
            php72-php-mbstring \
            php72-php-mysqlnd \
            php72-php-xml \
            php72-php-opcache \
            php72-php-bcmath \
            php72-php-pecl-swoole \
            php72-php-pecl-mongodb \
            php72-php-pecl-zip \
            php72-php-pecl-redis4 \
            php72-php-pcntl \
            php72-php-pecl-apcu

ln /opt/remi/php72/root/usr/bin/php /usr/bin/php
```

验证

```
php --version
php --modules
```

### 安装composer

```
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
/usr/bin/composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
```

### 安装supervisor

版本对于3.0

安装supervisor

```
yum install -y epel-release
yum install -y supervisor
```

开启supervisorctl

```
systemctl enable supervisord.service
```

### 创建用户和组

```
groupadd www
useradd --shell /sbin/nologin -g www www
```

### 安装php-fpm

安装php-fpm

```
yum install php72-php-fpm
```

开启php-fpm

```
systemctl enable php72-php-fpm.service
```

修改用户权限, 将用户和组从apache 改为www

```
/etc/opt/remi/php72/php-fpm.d/www.conf
```

```
user = www
group = www
```

### 安装npm

1. 添加**Node.js** **Yum**仓库

   ```
   curl -sL https://rpm.nodesource.com/setup_12.x | bash -
   ```
2. 安装**Node.js**

   ```
   yum install -y nodejs
   ```
3. 检查**Node.js**和**NPM**版本

   ```
   node -v

   v12.6.0
   Also, check the version of npm.

   npm -v

   6.9.0
   ```

参考: [How To Install Latest Nodejs on CentOS/RHEL 7/6](https://tecadmin.net/install-latest-nodejs-and-npm-on-centos/)

### 安装nginx

安装nginx

```
yum install nginx
```

开启nginx

```
systemctl enable nginx.service
```

### 安装crontabs

```
yum install crontabs
```

```
systemctl enable crond.service
```

```
systemctl start crond.service
```

### 安装redis

安装redis

```
yum install -y redis
```

开启redis

```
yum enable redis
```

修改配置文&#x4EF6;**/etc/redis.conf**

```
# requirepass foobared
requirepass    #指定密码为 redis1234
```

启动redis

```
systemctl start redis
```

测试

```
redis-cli -h 127.0.0.1 -a redis1234
keys *
```

### 安装neo4j

1. 导入签名并且添加neo4j的源到本地centos源中

   ```
   rpm --import https://debian.neo4j.org/neotechnology.gpg.key
   cat <<EOF>  /etc/yum.repos.d/neo4j.repo
   [neo4j]
   name=Neo4j RPM Repository
   baseurl=https://yum.neo4j.org/stable
   enabled=1
   gpgcheck=1
   EOF
   ```
2. 安装neo4j
   * 用**root**权限安装neo4j社区版

     ```
     yum install neo4j-3.5.7
     ```
3. 运行以下命令会返回已安装的Neo4j的版本:

   ```
   rpm -qa | grep neo4j
   ```
4. 修改默认**密码**

   生产环境使用时需要修改初始密码, 否则会安装使用时报错.

   ```
   # neo4j-admin set-initial-password <password>
   neo4j-admin set-initial-password neo4j1234
   ```

### 安装mysql

{% hint style="info" %}
如果使用云方提供的RDS, 请忽略安装
{% endhint %}

添加mysql7的源到本地centos源中

```
yum install -y https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
```

安装mysql

```
yum install -y mysql-server
```

修改配置文&#x4EF6;**/etc/my.conf**(配置位置取决于安装方式)

{% hint style="info" %}
如果使用阿里云的RDS可以忽略此步骤
{% endhint %}

```
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
```

开启mysql

```
systemctl enable mysqld
```

启动mysql

```
systemctl start mysqld
```

在安装过程中，为MySQL**root**用户生成一个临时密码

```
grep 'temporary password' /var/log/mysqld.log
```

输出:

```
2016-12-01T00:22:31.416107Z 1 [Note] A temporary password is generated for root@localhost: mqRfBU_3Xk>r
```

请记录下密码, 在此例里中为**mqRfBU\_3Xk>r**

```
mysql_secure_installation
```

会提示你输入默认的**root**密码, 输入好后, 会被要求改掉密码.

输出

```
The existing password for the user account root has expired. Please set a new password.

New password:
```

输入一个新的12个字符的密码，该密码至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符。在提示时重新输入.

在此例中设置为, **Wka25ijklmng0ada-x**

您将收到关于新密码强度的反馈，然后您将立即被提示再次更改密码.

输出

```
Estimated strength of the password: 100
Change the password for root ? (Press y|Y for Yes, any other key for No) :
```

我们将按下**Y**，然后进入所有后续问题，以便删除匿名用户、禁止远程根登录、删除测试数据库并访问它，并重新加载特权表.

命令行连接**mysql**

```
mysql -uroot -p"Wka25ijklmng0ada-x"
```

创建应用数据库

```
CREATE DATABASE espier_bloated CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

参考: [How To Install MySQL on CentOS 7](https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-centos-7)

## 系统应用部署

部署几部分

商家端(VUE) + API端

### 配置授权

安装swoole-loader

确认PHP扩展目录

```
# php -r 'phpinfo();' | grep -i '^extension_dir'

extension_dir => /opt/remi/php72/root/usr/lib64/php/modules => /opt/remi/php72/root/usr/lib64/php/modules
```

本例中&#x4E3A;**/opt/remi/php72/root/usr/lib64/php/modules**

```
curl https://business.swoole.com/static/loader2.0.0/swoole_loader72.so > /opt/remi/php72/root/usr/lib64/php/modules/swoole_loader72.so
```

php扩展配置文件位置

```
# php -r 'phpinfo();' | grep -i 'Scan this dir for additional'

Scan this dir for additional .ini files => /etc/opt/remi/php72/php.d
```

设置授权

{% hint style="info" %}
注意配置license的正确位置, 默认license.zl在代码包(espier-bloated)根目录下
{% endhint %}

```
{ \
    echo "extension=swoole_loader72.so"; \
    echo "swoole_license_files=/var/www/html/license.zl";  \
} > /etc/opt/remi/php72/php.d/60-swoole_loader.ini
```

重启fpm

```
systemctl enable php72-php-fpm.service
```

### 部署API服务(php)

#### 配置

后端代码

```
mkdir -p /var/www/espier-bloated
chown -R www:www /var/www/espier-bloated
```

放置代码&#x5230;**/var/www/espier-bloated**目录中

修改配&#x7F6E;**.env**, 拷&#x8D1D;**.env.production**文件做为模版.

1. 配置数据库

   ```
   DB_HOST=127.0.0.1
   DB_PORT=3306
   DB_DATABASE=espier_bloated
   DB_USERNAME=root
   DB_PASSWORD=Wka25ijklmng0ada-x
   ```
2. 配置REDIS

   ```
   # REDIS 相关配置
   REDIS_CLIENT=predis
   REDIS_HOST=redis-ali-espier-master
   REDIS_PASSWORD=redis1234
   REDIS_MEMBERS_PORT=6379
   ```
3. 配置队列

   ```
   QUEUE_DRIVER=redis
   ```
4. 配置neo4j

   ```
   NEO4J_DEFAULT_PROTOCOL=bolt
   NEO4J_DEFAULT_HOST=127.0.0.1
   NEO4J_DEFAULT_PORT=7687
   NEO4J_DEFAULT_USERNAME=neo4j
   NEO4J_DEFAULT_PASSWORD=neo4j1234
   ```
5. 配置缓存

   ```
   CACHE_DRIVER=redis
   ```
6. 配置七牛

   [如何获取Access Key和Secret Key](https://developer.qiniu.com/af/kb/1479/how-to-access-or-locate-the-access-key-and-secret-key)

   [icon.png](https://github.com/bryantyan/espier-docs/tree/f1b72d96424898684552cce9df5b400d91b18a9b/test.md)

   ```
   # 图片CDN域名
   QINIU_IMAGE_DOMAIN=b-img-cdn.yuanyuanke.cn
   # 图片bucket
   QINIU_IMAGE_NAME=espier-images
   # 导入导出文件CDN域名
   QINIU__FILE_DOMAIN=https://b-import-cdn.yuanyuanke.cn
   导入导出bucket
   QINIU_FILE_NAME=espier-import-files
   # 七牛Access Key
   QINIU_ACCESS_KEY=
   # 七牛Secret Key
   QINIU_SECRET_KEY=
   ```
7. 配置微信开放平台第三方平台相关配置

   需要根据实际

   ```
   # 微信开放平台对应第三方平台APPID
   WECHAT_APPID=
   # 微信开放平台对应第三方平台APPSECRET
   WECHAT_SECRET=
   # 微信开放平台对应第三方平台 消息校验Token
   WECHAT_TOKEN=
   # 微信开放平台对应第三方平台 消息加解密Key
   WECHAT_AES_KEY=
   WECHAT_DEBUG=true
   ```
8. 配置商城小程序模版

   模版ID, 需要添加到小程序模版库，获得模版ID, 参考:[开发者平台小程序模板](https://developers.weixin.qq.com/community/develop/doc/000c6c3524cff06575466ccd35ec00)

   ```
   # 商城小程序模版相关配置
   # 小程序模版ID号
   YYKWEISHOP_TEMPLATE_ID=
   # 小程序模版版本
   YYKWEISHOP_VERSION=
   # request合法域名
   YYKWEISHOP_REQUESTDOMAIN=https://b.yuanyuanke.cn
   # socket合法域名
   YYKWEISHOP_WSREQUESTDOMAIN=wss://b-websocket.yuanyuanke.cn
   # uploadFile(上传文件)合法域名
   YYKWEISHOP_UPLOADDOMAIN=https://b.yuanyuanke.cn
   # downloadFile(下载文件)合法域名
   YYKWEISHOP_DOWNLOADDOMAIN1=https://mmbiz.qpic.cn
   YYKWEISHOP_DOWNLOADDOMAIN2=https://b.yuanyuanke.cn
   YYKWEISHOP_DOWNLOADDOMAIN3=https://wx.qlogo.cn
   ```
9. 配置腾讯位置服务

{% hint style="info" %}
腾讯位置服务需要申请账号配置KEY, KEY对接口的访问是有配额的, 配额内是免费的.
{% endhint %}

在[腾讯位置服务Key管理](https://lbs.qq.com/console/mykey.html?console=mykey), 可以查询到Key, 并且可以查询到配额.

{% hint style="danger" %}
为了开发环境方便, 提供只为开发环境公用的免费KEY. 因为是公共的, 无法保证一定可用.
{% endhint %}

```
QQMAP_KEY=PSPBZ-KQ5CW-CSGRF-ON2S4-K2HQJ-XEBQG
```

1. 配置支付通知接口

   ```
   WECHAT_PAYMENT_NOTIFY=https://b.yuanyuanke.cn/wechatAuth/wxpay/notify
   ```

完整的例子

```
# 标识应用环境, 本地环境设置为local
APP_ENV=local
# 调试模式, 正式环境可以关闭
APP_DEBUG=true
# 时区不要修改
APP_TIMEZONE=PRC

# 数据库相关配置
# DB_CONNECTION默认不需要改
DB_CONNECTION=default
# 数据库主机
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=espier_bloated
DB_USERNAME=root
DB_PASSWORD=Wka25ijklmng0ada-x

# 缓存驱动, 默认使用redis
CACHE_DRIVER=redis
# 队列驱动, 默认使用redis
QUEUE_DRIVER=redis

# 七牛相关配置
QINIU_IMAGE_DOMAIN=b-img-cdn.yuanyuanke.cn
QINIU_IMAGE_NAME=espier-image
QINIU__FILE_DOMAIN=https://b-import-cdn.yuanyuanke.cn
QINIU_FILE_NAME=espier-file
QINIU_ACCESS_KEY=
QINIU_SECRET_KEY=

# 短信会用到, 如果需要商派短信, 误删
PRISM_URL=http://openapi.shopex.cn/api
PRISM_KEY=7zfgrchh
PRISM_SECRET=ykiy27tqhlnbn6ndaddr

# JWT 相关配置, 可根据需要调整或不调整
JWT_SECRET=ker4H1sp4TsdDvcVJMa72SMW8Zsh3drv
JWT_TTL=300
JWT_REFRESH_TTL=20160

# 微信第三方平台设置. 本地开发环境不配置, 会影响到调用微信的相关页面, 整体不影响后台开发.
WECHAT_APPID=
WECHAT_SECRET=
WECHAT_TOKEN=
WECHAT_AES_KEY=
WECHAT_DEBUG=true

# 支付通知接口
WECHAT_PAYMENT_NOTIFY=https://b.yuanyuanke.cn/wechatAuth/wxpay/notify

# dingo标准配置, 根据实际场景进行配置
API_PREFIX=api
API_NAME="Espier API"
API_STANDARDS_TREE=vnd
API_STRICT=false
API_DEBUG=false
API_VERSION=v1
API_SUBTYPE=espier
API_CONDITIONAL_REQUEST=false
API_TOKEN=Os6Bass1oT5vig2Yod0yiT8dU0as5cIn

RPCCALL_DRIVER=dingo

# 腾讯地图接口KEY, 建议根据项目进行申请
QQMAP_KEY=PSPBZ-KQ5CW-CSGRF-ON2S4-K2HQJ-XEBQG

# REDIS 相关配置
REDIS_CLIENT=predis
REDIS_HOST=redis-ali-espier-master
REDIS_PASSWORD=redis1234
REDIS_MEMBERS_PORT=6379


LICENSE_PRODUCTION_URL=https://service.ec-os.net/api/yyk/register
LICENSE_PRODUCT=yyk

# 商城小程序相关配置
# 小程序模版ID号
YYKWEISHOP_TEMPLATE_ID=
YYKWEISHOP_REQUESTDOMAIN=https://b.yuanyuanke.cn
YYKWEISHOP_WSREQUESTDOMAIN=wss://b-websocket.yuanyuanke.cn
# 小程序版本
YYKWEISHOP_VERSION=
YYKWEISHOP_DOWNLOADDOMAIN1=https://mmbiz.qpic.cn
YYKWEISHOP_DOWNLOADDOMAIN2=https://b.yuanyuanke.cn
YYKWEISHOP_DOWNLOADDOMAIN3=https://wx.qlogo.cn


WEBSOCKET_SERVER_PORT=9051
WEBSOCKET_SERVER_HOST=b-websocket.yuanyuanke.cn

SENTRY_LARAVEL_DSN=https://eb0daff7a4244e2e8e8131e178952c55:d13add823922418f859c081feb671d73@report.shopex.cn/41

SUPER_ADMIN_LOGIN_NAME=yykpms
SUPER_ADMIN_LOGIN_PASSWORD=c0f50922ef5c2d72adac424fca752aa97523fa33

NEO4J_DEFAULT_PROTOCOL=http
NEO4J_DEFAULT_HOST=distribution-neo4j-neo4j-core-0.distribution-neo4j-neo4j.espier.svc.cluster.local
NEO4J_DEFAULT_PORT=7474
NEO4J_DEFAULT_USERNAME=neo4j
NEO4J_DEFAULT_PASSWORD=oPMfxPwMwY

BROKERAGE_URI=
BROKERAGE_URI_ITEM=
ALIPAY_PAYMENT_NOTIFY=
ALIPAY_PAYMENT_RETURN=

H5_BASE_URL=
```

#### 安装

安装composer扩展包

```
cd /var/www/espier-blaoted
composer install
```

数据库迁移

```
cd /var/www/espier-blaoted
./artisan doctrine:migrations:migrate
```

### 部署商家端(vue)

商家端代码

代码build好后build目录里的文件直接copy至此目录

1. 创建项目目录

   ```
   mkdir -p /var/www/espier-retail-manage
   ```
2. 放置代码 通常会通过git的方式进行部署及更新

   修改**app/config/test.env.js**

   ```
   module.exports = {
     NODE_ENV: '"testing"',
     BASE_API: '"https://b.yuanyuanke.cn/api"',
     //WXIMG_URL: '"https://bbc54.shopex123.com/image/"',
     WXIMG_URL: '""',
     WXAUTHCALL_Url: '"https://b.yuanyuanke.cn/"'
   }
   ```
3. 安装npm宝

   ```
   cd /var/www/espier-retail-manage/app

   npm installl
   ```
4. 代码编译目录 **/var/www/espier-retail-manage/app/config/index.js**

   ```
   assetsRoot: path.resolve(__dirname, '../test'),
   ```

   编译后的文件&#x5728;**/var/www/espier-retail-manage/app/test**下
5. 代码编译

   ```
   npm run build-test
   ```
6. 更改权限

   ```
   chown -R www:www /var/www/espier-retail-manage
   ```

### 配置nginx

修改/etc/nginx/nginx.conf, 将权限nginx 改为www

```
use www;
```

创建项目nginx配置

```
vim /etc/nginx/conf.d/espier.conf
```

{% hint style="danger" %}
需要配置ssl证书, 在下边配置的所有**配置ssl**处.
{% endhint %}

```
server
{
    listen 443;
    # 配置ssl

    server_name b.yuanyuanke.cn;

    location /api/ {
        access_log /var/log/nginx/espier-bloated.log;
        proxy_pass http://localhost:8080;
    }

    location /wechatAuth/ {
        access_log /var/log/nginx/espier-wechatauth.log;
        proxy_pass http://localhost:8080;
    }

    location / {
        proxy_pass http://localhost:8081;
    }
}

# 配置API服务(espier-bloated)
server {

    listen 8080;
    listen [::]:8080;

    server_name localhost;
    root /var/www/espier-bloated/public;
    index index.php index.html index.htm;

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        add_header Access-Control-Allow-Origin '*' always;
        add_header Access-Control-Allow-Headers "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With";
        add_header Access-Control-Expose-Headers "Authorization";
        add_header Access-Control-Allow-Methods "DELETE, GET, HEAD, POST, PUT, OPTIONS, TRACE, PATCH";

        if ($request_method = OPTIONS ) {
            return 200;
        }

        fastcgi_pass localhost:9000;
        fastcgi_read_timeout 150;
        fastcgi_index index.php;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

# 配置商家端(espier-retail-manage)
server {
    listen 8081;
    listen [::]:8081;

    server_name localhost;

    location / {
        root   /var/www/espier-retail-manage/app/test;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html =404;
    }

    location /wximage/ {
        set $hostx "";
        set $addrs "";
        if ( $uri ~ "^/wximage/http./+([^/]+)/(.+)$") {
            set $hostx $1;
            set $addrs $2;
        }
        resolver 8.8.8.8;
        proxy_pass http://$hostx/$addrs;
        proxy_set_header referer "http://read.html5.qq.com/image";
    }
}

配置websocket服务
server
{
    listen 443;

    # 配置ssl

    server_name b-websocket.yuanyuanke.cn;

    location / {
        proxy_pass http://localhost:9051/;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
```

### 配置定时任务

```
crontab -e
```

```
*    *    *    *    *       sudo -E -u www php /var/www/espier-bloated/artisan schedule:run >> /var/log/espier-cront.log 2>&1
```

### 配置队列服务

修改队列配置

```
vim /etc/supervisord.d/super-queue.ini
```

```
[program:bloated-queue-default]
command=/var/www/espier-bloated/artisan queue:work --queue=default --delay=3 --memory=128 --timeout=30 --sleep=1 --tries=3
stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-default.log
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
numprocs=1
user=www
startsecs=3
startretries=100000

[program:bloated-queue-slow]
command=/var/www/espier-bloated/artisan queue:work --queue=slow --delay=3 --memory=128 --timeout=1800 --sleep=1 --tries=3
stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-slow.log
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
redirect_stderr=true
autostart=true
autorestart=true
numprocs=1
user=www
startsecs=3
startretries=100000

[program:bloated-queue-sms]
command=/var/www/espier-bloated/artisan queue:work --queue=sms --delay=3 --memory=128 --timeout=1800 --sleep=1 --tries=3
stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-bloated-queue-sms.log
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
redirect_stderr=true
autostart=true
autorestart=true
numprocs=1
user=www
startsecs=3
startretries=100000
```

### 配置websocket服务

配置websocket

```
vim /etc/supervisord.d/super-websocket.ini
```

```
[program:websocket]
command=/var/www/espier-bloated/artisan websocket:start
stdout_logfile=/var/www/espier-bloated/storage/logs/supervisor-websocket.log
redirect_stderr=true
autostart=true
autorestart=true
numprocs=1
user=www
startsecs=3
startretries=100000
```

## 服务启动

启动队列任务, websocket服务

```
systemctl start supervisord.service
```

启动nginx

```
systemctl start nginx.service
```

启动php-fpm

```
systemctl start php72-php-fpm.service
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://espier.gitbook.io/espier/xi-tong-bu-shu/bu-shu-fang-an/install.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
