---
url: /docs/3.0/deploy.md
---
# CatchAdmin 部署指南

> 详细的 CatchAdmin 生产环境部署教程和最佳实践

:::warning
很多开发者在部署 CatchAdmin 时遇到问题，这里提供了完整详细的部署文档。本文档包含了从前端构建到服务器配置的全部步骤，基本涵盖了所有部署场景。

请仔细阅读文档，大部分问题都能在这里找到解决方案。如果遇到特殊情况确实需要协助，目前提供付费部署支持服务，收费标准为 `100` 元/次。先付费后服务，感谢理解 🙏
:::

## 前端项目

在构建 CatchAdmin 前端项目前，需要先配置生产环境的 API 地址。在前端项目根目录下创建或编辑 `.env.production` 文件：

```
# base api
// 例如 https://api.catchadmin.com/api/

VITE_BASE_URL = '正式环境的 API 地址'
```

配置完成后，使用以下命令构建 CatchAdmin 前端项目：

```bash
yarn run build
# 或者使用 npm
npm run build
```

### 打包出现报错

如果打包出现 ts 过多的类型错误，而你对类型又不太敏感的话，对应用没有影响。一个快速的解决办法就是修改 `package.json 文件` build 命令

```json
{
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build", // [!code --]
    "build": "vite build", // [!code ++]
    "preview": "vite preview"
  }
}
```

构建完成后，前端项目根目录会生成 `dist` 目录，这是 CatchAdmin 前端的生产版本，包含经过优化的静态资源文件，可直接部署到 Web 服务器。

:::tip 性能优化建议

1. 建议在 Web 服务器上启用 `Gzip` 压缩，可显著提升页面加载速度
2. 配置静态资源缓存策略，提升用户体验
3. 使用 CDN 加速静态资源访问
   :::

## 后端

CatchAdmin 后端基于 PHP 开发，部署相对简单。将 PHP 项目代码上传到服务器即可。

**推荐部署方式**：

1. 上传源代码到服务器，不包含 `vendor` 目录
2. 在服务器上执行 `composer install --no-dev` 安装生产环境依赖
3. 配置正确的文件权限和目录结构

如果遇到依赖安装的网络问题，请参考 [使用镜像](./faq.md#镜像) 解决方案。

:::warning 重要提醒
如果使用了 CatchAdmin 脚手架初始化项目，部署时需要注意：

* **排除 `web` 目录**：这是前端开发目录，不需要与后端一起上传
* **前端部署**：只需要上传构建后的 `dist` 目录
* **分离部署**：前后端建议分开部署，便于维护和扩展
  :::

### 上线注意点

* `.env` 环境文件是否配置好？
* 数据库表是否同步?
* 数据表的数据是否同步，主要是**权限菜单**表`permissions`里是否同步
* 模块是否开启? 模块如果没有开启，整个项目都会无法正常运行 (`这个步骤只针对 Laravel 主项目`)
  :::tip
  一定要检查线上项目`storage/app/modules.json` 是否存在。如果不存在，要将本地项目`storage/app/modules.json`上传到服务器
  :::
* 模块如果正常开启的状态下，路由还是无法正常工作 (`这个步骤只针对 Laravel 主项目`)
  :::tip
  * 首先是用 php artian route:clear
  * 然后查看路由 php artisan route:list
  * 最后缓存路由 php artisan route:cache
    :::

## 部署

:::warning
如果你使用的是宝塔相关的，一定不要完全复制下面的配置。因为宝塔有很多预配置项，例如 https ssl 配置是不需要你自己手动配置
:::

### 分开部署（双域名）

推荐的 CatchAdmin 部署方式是前后端分离部署，分别使用不同的域名或子域名：

**部署架构示例**：

* 前端项目：`admin.yourdomain.com` → `/www/admin` 目录
* 后端 API：`api.yourdomain.com` → `/www/api` 目录

:::tip 部署建议

* 目录路径可根据实际服务器环境调整

* 分离部署便于独立维护和扩容

* 支持前后端独立更新，降低部署风险
  :::

* `/www/admin` 上传 `dist` 目录内容到 admin 目录中

* `/www/api` 上传后端项目到 api 目录中

::: code-group

```php [前端项目]
server
{
    listen 80;
    server_name admin.catchadmin.com;
    return 301 https://admin.catchadmin.com$request_uri;
}

server
{
    listen  443  ssl http2;
    server_name admin.catchadmin.com;
    index.html index.php index.htm default.php default.htm default.html;


    ssl_certificate       # pem文件的路径
    ssl_certificate_key   # key文件的路径

    # ssl验证相关配置
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    root /www/admin;
    location / {
    	try_files $uri $uri/ /index.html =404;
    }
}

```

```php [后端项目]
server
{
    listen 80;
    server_name api.catchadmin.com;
    return 301 https://api.catchadmin.com$request_uri;
}


server
{
    listen  443  ssl http2;
    server_name api.catchadmin.com;
    index index.html index.php index.htm default.php default.htm default.html;
    root /www/api/public;

    ssl_certificate     /etc/nginx/acme/catchadmin.com/catchadmin.com.cer;  # pem文件的路径
    ssl_certificate_key  /etc/nginx/acme/catchadmin.com/catchadmin.com.key; # key文件的路径
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    location / {
       if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=/$1  last;
        break;
      }
    }

   # PHP 支持
    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    ## nginx log 自己配置
    access_log;
    error_log;
}

```

:::

### 合并部署（单域名）

如果只有一个域名或希望简化部署架构，可以将 CatchAdmin 前后端部署在同一域名下：

**部署结构**：

* 后端项目：`yourdomain.com/api` → PHP 项目根目录
* 前端项目：`yourdomain.com/` → 放置在后端项目的 `public/admin` 目录下

这种方式适合小型项目或资源有限的场景。

```php

server
{
    listen 80;
    server_name api.catchadmin.com;
    return 301 https://api.catchadmin.com$request_uri;
}


server
{
    listen  443  ssl http2;
    server_name api.catchadmin.com;
    index index.html index.php index.htm default.php default.htm default.html;
    root /www/api/public;

    ssl_certificate     # pem文件的路径
    ssl_certificate_key  # key文件的路径
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    # 因为接口都是以 api.catchadmin.com/api 开头，所以可以很好的使用 location
    # 如果访问 api.catchadmin.com/api 目录 则用 php 解释下
    location /api {
       if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=/$1  last;
        break;
      }
    }

    # 如果访问根目录 api.catchadmin.com/， 则直接访问前端项目
    location / {
      root /www/api/public/admin;
      try_files $uri $uri/ /index.html;
    }

    # 上传的静态目录 location
    location /uploads/ {
      alias /www/api/storage/uploads/;
      autoindex on;
    }


     #PHP 支持
    location ~ \.php$ {
          try_files $uri /index.php =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
    }
}

```

如果使用宝塔部署，`location` 配置静态目录的可能会无法工作，这是由于宝塔的预配置导致的，目前我个人使用下面如图得方法解决了

![宝塔单域名部署](https://image.catchadmin.com/202411280949472.png)

### Octane 高性能部署

对于需要高性能的 CatchAdmin 项目，可以使用 Laravel Octane 提升并发处理能力：

**Octane 优势**：

* 显著提升 API 响应速度
* 更好的内存利用率
* 支持 WebSocket 等高级特性

**适用场景**：高并发访问、实时数据处理、大量 API 调用的企业级应用

```php
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server
{
    listen 80;
    server_name api.catchadmin.com;
    return 301 https://api.catchadmin.com$request_uri;
}


server
{
   listen  443  ssl http2;
    server_name api.catchadmin.com;
    index index.html index.php index.htm default.php default.htm default.html;
    root /www/api/public;

    ssl_certificate     # pem文件的路径
    ssl_certificate_key  # key文件的路径
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    # 因为接口都是以 api.catchadmin.com/api 开头，所以可以很好的使用 location
    # 如果访问 api.catchadmin.com/api 目录 则用 php 解释下
    location /api {
       if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=/$1  last;
        break;
      }
    }

    # 如果访问根目录 api.catchadmin.com/， 则直接访问前端项目
    location / {
      root /www/api/public/admin;
      try_files $uri $uri/ /index.html;
    }

    # 上传的静态目录 location
    location /uploads/ {
      alias /www/api/public/storage/uploads/;
      autoindex on;
    }

    location @octane {
        set $suffix "";

        if ($uri = /index.php) {
            set $suffix ?$query_string;
        }

        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_pass http://172.18.0.2:9800$suffix;
    }
}

```
