Skip to content

宝塔面板部署 ​

适合谁 ​

服务器上已经装了(或者准备装)宝塔 Linux 面板,希望尽量用鼠标完成部署的新手。 全程只有少量命令需要在宝塔的“终端”里粘贴执行。

最终效果:

  • https://shop.example.com/ → 用户前台
  • https://shop.example.com/admin/ → 管理后台
  • 后端程序由宝塔的「进程守护管理器」守护,崩溃或重启服务器后自动拉起。

准备 ​

项目要求
服务器64 位 Linux(CentOS 7+/Debian/Ubuntu 均可),1 核 1 GB 内存起步
域名例如 shop.example.com,已添加 A 记录指向服务器 IP
宝塔面板7.x 或更新版本,已安装 Nginx(在软件商店安装,版本任意)
文件zebra-store 程序、storefront/dist、admin/dist、config.example.yml(见下方“获取程序和网页”)

获取程序和网页 ​

一共需要三样东西:

东西是什么怎么得到
zebra-store后端程序(一个文件)在 backend/ 编译
storefront/dist用户前台网页在 storefront/ 打包
admin/dist管理后台网页在 admin/ 打包,必须带 --base=/admin/

在你自己的电脑(装好 Rust ≥ 1.90 和 Node.js ≥ 20)上执行:

bash
git clone <仓库地址> zebra-store && cd zebra-store

# 1) 后端:给 Linux 服务器编译一个不依赖任何系统库的静态程序
cargo install cargo-zigbuild        # 第一次需要;macOS 还要 brew install zig
cd backend
rustup target add x86_64-unknown-linux-musl
cargo zigbuild --release -p zs-server --target x86_64-unknown-linux-musl
# 产物:backend/target/x86_64-unknown-linux-musl/release/zebra-store
cd ..

# 2) 用户前台
cd storefront && npm ci && npm run build && cd ..        # 产物:storefront/dist

# 3) 管理后台(放在 /admin/ 路径下)
cd admin && npm ci && npx vite build --base=/admin/ && cd ..   # 产物:admin/dist

直接在 Linux 服务器上编译

如果你就在 x86_64 Linux 服务器上编译,后端可以简单地用 cargo build --release -p zs-server,产物在 backend/target/release/zebra-store。 服务器是 ARM(arm64)的话,把上面的 x86_64-unknown-linux-musl 换成 aarch64-unknown-linux-musl。

为什么后台要加 --base=/admin/

后台网页默认假设自己放在网站根目录。我们把它放在 https://你的域名/admin/, 所以打包时要告诉它“我的根路径是 /admin/”,否则打开后台时 JS 文件会 404,页面一片空白。

步骤 ​

1. 安装宝塔和 Nginx ​

如果还没装宝塔,按 宝塔官网 的一键安装命令安装,装完用浏览器登录面板。 第一次登录时,宝塔会推荐安装 LNMP / LAMP 套件:只勾选 Nginx 即可(数据库默认用 SQLite,不需要 MySQL;想用 MySQL 再勾选)。

宝塔软件商店安装 Nginx宝塔软件商店安装 Nginx

2. 放开防火墙端口 ​

宝塔左侧 安全 → 确认 80 和 443 端口已放行。 不要放行 8081:后端只给本机的 Nginx 访问。如果云服务商有“安全组”,也要放行 80 和 443。

3. 创建网站 ​

宝塔左侧 网站 → 添加站点:

  • 域名:shop.example.com
  • 根目录:保持默认 /www/wwwroot/shop.example.com
  • FTP:不创建;数据库:不创建;PHP 版本:纯静态

宝塔添加站点宝塔添加站点

4. 上传前台和后台网页 ​

宝塔左侧 文件 → 进入 /www/wwwroot/shop.example.com:

  1. 删除宝塔自动生成的 index.html、404.html(保留 .user.ini 等隐藏文件即可);
  2. 把 storefront/dist 里面的所有文件上传到这个目录(上传后这里应该直接有 index.html 和 assets/);
  3. 在这个目录里新建文件夹 admin,把 admin/dist 里面的所有文件上传进去(上传后应有 admin/index.html)。

上传压缩包更快

先在本机把 dist 打成 zip,上传后在宝塔文件管理器里右键 解压。

上传后的网站目录上传后的网站目录

5. 上传后端程序 ​

在 文件 里新建目录 /www/zebra,上传:

  • zebra-store(后端程序)
  • config.example.yml,上传后重命名为 config.yml

然后打开宝塔 终端(左侧菜单),粘贴执行:

bash
cd /www/zebra
mkdir -p data uploads
chmod +x zebra-store
chown -R www:www /www/zebra
chmod 600 config.yml

www 是宝塔运行网站用的用户,后端也用它运行,这样它能读写 data/ 和 uploads/。

6. 修改配置文件 ​

在宝塔文件管理器里双击 /www/zebra/config.yml 编辑。

写配置文件 ​

从仓库复制 backend/config.example.yml,改名为 config.yml,至少改下面这些 (每一项的含义见 配置文件详解):

yaml
app:
  secret_key: 第一串随机字符          # openssl rand -hex 24 生成
server:
  host: 127.0.0.1                    # 只让本机的反向代理访问后端
  port: 8081
  mode: release
jwt:
  secret: 第二串随机字符
user_jwt:
  secret: 第三串随机字符
bootstrap:
  default_admin_username: admin
  default_admin_password: 你的管理员密码   # 只在第一次启动时用来创建超级管理员
database:
  url: sqlite://data/zebra.db?mode=rwc    # 相对“运行目录”,即 <程序目录>/data/zebra.db
upload:
  dir: uploads                            # 相对“运行目录”
cors:
  allowed_origins: ["https://shop.example.com"]

三个密钥

app.secret_key、jwt.secret、user_jwt.secret 必须是三个不同的值,每个至少 16 个字符, 不能保留示例里的 change-me-…,否则程序拒绝启动并在日志里写明是哪一项。 app.secret_key 用来加密数据库里的敏感字段(支付密钥等),上线后不要再改,改了之前加密的数据就解不开了。

宝塔部署时 config.yml 放在 /www/zebra,下面守护进程的“运行目录”也设成 /www/zebra, 所以数据库文件是 /www/zebra/data/zebra.db,图片在 /www/zebra/uploads/。

7. 用「进程守护管理器」运行后端 ​

  1. 宝塔 软件商店 → 搜索 进程守护管理器(Supervisor)→ 安装;
  2. 打开它 → 添加守护进程:
字段填写
名称zebra-store
启动用户www
运行目录/www/zebra
启动命令/www/zebra/zebra-store --config /www/zebra/config.yml serve
进程数量1(必须是 1)
  1. 保存后状态应为“运行中”。点 日志 能看到启动日志,出现 listening 和 0.0.0.0:8081 或 127.0.0.1:8081 就成功了。

进程守护管理器添加 zebra-store进程守护管理器添加 zebra-store

在终端里再确认一次:

bash
curl -s http://127.0.0.1:8081/api/v1/public/config | head -c 120

能看到以 {"status_code":0 开头的内容就说明后端正常。

不想装进程守护管理器?用 systemd

在终端里创建 /etc/systemd/system/zebra-store.service:

ini
[Unit]
Description=Zebra Store
After=network-online.target
Wants=network-online.target

[Service]
User=www
Group=www
WorkingDirectory=/www/zebra
ExecStart=/www/zebra/zebra-store --config /www/zebra/config.yml serve
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

然后执行 systemctl daemon-reload && systemctl enable --now zebra-store。两种方式只能选一种,否则会抢同一个端口。

8. 配置 Nginx:转发接口 + 单页应用 ​

哪些路径要转给后端 ​

前台和后台只是静态网页,所有数据都来自后端。反向代理必须把下面这些路径转发给后端 127.0.0.1:8081, 并保留原始的 Host 头:

路径用途
/api/所有接口,包括支付回调和对接接口
/uploads/上传的图片
/sitemap.xml、/robots.txt搜索引擎
/shared/异次元发卡把本站当上游时调用(异次元对接)
/plugin/open-api/萌次元协议把本站当上游时调用(萌次元对接)

其余路径:/admin/ 开头的返回后台网页,其他的返回前台网页;找不到文件时返回对应的 index.html (前台和后台都是单页应用,刷新 /products/xxx 这类地址时服务器上并没有这个文件)。

一定要保留 Host 头

后端靠 Host 判断访问的是主站还是哪个分站,生成支付回调地址时也会用到。

宝塔自带的“反向代理”页面一次只能转发一个目录,而且会改写一些默认设置,所以最稳妥的做法是直接改站点配置文件:

网站 → 点 shop.example.com 的 设置 → 配置文件,找到 server { … } 里 #REWRITE-END 这一行,在它的下面粘贴:

nginx
    # ---------- Zebra Store ----------
    client_max_body_size 20m;

    location ~ ^/(api|uploads|shared|plugin/open-api)/ {
        proxy_pass http://127.0.0.1:8081;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 120s;
    }
    location = /sitemap.xml { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; }
    location = /robots.txt  { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; }

    # 管理后台(单页应用)
    location = /admin { return 308 /admin/; }
    location /admin/ {
        try_files $uri $uri/ /admin/index.html;
    }
    # 用户前台(单页应用)
    location / {
        try_files $uri $uri/ /index.html;
    }
    # ---------- Zebra Store end ----------

保存。如果宝塔提示 location / 重复,说明站点的 伪静态 里已经有 location /:到 伪静态 标签页把内容清空保存,再回来保存配置文件。

不要开启宝塔的“缓存”

如果之前用宝塔的「反向代理」页面加过 /api,请删除那条反向代理,改用上面的配置。 接口响应一旦被缓存,买家会看到别人的数据或过期的订单状态。

宝塔站点配置文件宝塔站点配置文件

9. 申请 SSL 证书 ​

网站 → shop.example.com 的 设置 → SSL → Let's Encrypt → 勾选域名 → 申请。 申请成功后打开右上角的 强制 HTTPS。宝塔会自动续期。

宝塔申请 Let's Encrypt 证书宝塔申请 Let's Encrypt 证书

让后端拿到买家的真实 IP ​

风控、限流和登录日志都需要买家的真实 IP。反向代理通过 X-Forwarded-For 头把 IP 传给后端, 但后端只相信 server.trusted_proxies 里列出的代理。默认值是 127.0.0.1/32 和 ::1/128, 反向代理和后端在同一台机器上时不用改。

反向代理在别的机器或者 Docker 容器里时,把它的 IP 或网段加进去,例如:

yaml
server:
  trusted_proxies: ["127.0.0.1/32", "::1/128", "172.28.0.0/24"]

0.0.0.0/0 这种“相信所有人”的写法会被拒绝,因为那样任何人都能伪造 IP。

宝塔的 Nginx 和后端在同一台机器上,保持默认即可。

10. 数据库选择 ​

  • SQLite(默认,推荐新手):什么都不用做,数据就在 /www/zebra/data/zebra.db。

  • MySQL:宝塔左侧 数据库 → 添加数据库:数据库名 zebra、用户名 zebra、设置密码、访问权限选 本地服务器, 字符集选 utf8mb4。然后把 config.yml 改成:

    yaml
    database:
      url: mysql://zebra:你的数据库密码@127.0.0.1:3306/zebra

    在进程守护管理器里 重启 zebra-store,表会自动创建。密码里有 @、:、/、# 等符号时要先做 URL 编码 (例如 @ 写成 %40),或者干脆换一个只含字母数字的密码。更多说明见 切换数据库。

切换数据库不会搬数据

从 SQLite 换成 MySQL 后是一个全新的空库,原来的数据不会自动迁移。请在开张之前决定好。

验证 ​

逐项检查:

  • [ ] https://你的域名/ 能打开前台,标题是你的站点名;
  • [ ] https://你的域名/admin/ 能打开后台登录页,用 admin 和配置里的密码能登录;
  • [ ] https://你的域名/api/v1/public/config 返回一段 JSON(开头是 {"status_code":0);
  • [ ] 在 https://你的域名/products 页面按 F5 刷新,不会出现 404;
  • [ ] 后台 内容管理 → 素材管理 上传一张图片,能正常显示(说明 /uploads/ 转发正常);
  • [ ] 浏览器地址栏有小锁,证书有效。

登录后台后,按 部署完成后要做的事 继续。

升级 ​

  1. 先按下面的方法备份;
  2. 在本机编译新版本,得到新的 zebra-store、storefront/dist、admin/dist;
  3. 进程守护管理器里 停止 zebra-store;
  4. 用新文件覆盖 /www/zebra/zebra-store(覆盖后在终端执行 chmod +x /www/zebra/zebra-store);
  5. 覆盖网站目录里的前台文件、admin/ 里的后台文件(旧的 assets/ 可以先删除再上传);
  6. 启动 zebra-store。新版本启动时会自动补齐新表和新字段,业务数据保留。

备份 ​

  • 宝塔 计划任务 → 添加 备份目录:目录选 /www/zebra(包含数据库、图片和配置),周期每天;
  • 用 MySQL 时再加一条 备份数据库 任务;
  • 建议同时勾选上传到对象存储或另一台机器。

备份 ​

要备份的只有三样:数据库、上传目录 uploads/、配置文件 config.yml(里面有加密密钥)。

bash
# SQLite 在线备份(不用停服务;需要 sqlite3:apt install sqlite3)
sqlite3 数据目录/zebra.db ".backup '/root/backup/zebra-$(date +%F).db'"
tar czf /root/backup/uploads-$(date +%F).tgz -C 程序目录 uploads
cp 程序目录/config.yml /root/backup/config-$(date +%F).yml

MySQL / PostgreSQL、定时备份和恢复步骤见 备份与升级。

常见问题 ​

打开网站是宝塔的默认页 / 404 网站根目录里还留着宝塔生成的 index.html,或者 storefront/dist 是整个文件夹传上去的(变成了 dist/index.html)。 根目录下应该直接是 index.html 和 assets/。

打开 /admin/ 一片空白 后台打包时没有加 --base=/admin/,或者后台文件没放在 admin/ 子目录里。按 F12 看控制台,如果 JS 文件 404 就是这个原因。

页面能打开但一直加载、提示网络错误 后端没有运行或 /api/ 没有转发。在终端执行 curl http://127.0.0.1:8081/api/v1/public/config 检查后端; 再检查配置文件里的 location ~ ^/(api|… 是否粘贴在了 server { } 里面。

进程守护管理器显示已停止,日志提示 secret 三个密钥没改或者相同,按日志提示修改 config.yml 后重启。

日志提示 Permission denied / unable to open database file/www/zebra 的所有者不是 www,重新执行 chown -R www:www /www/zebra。

上传图片失败 检查 client_max_body_size 20m; 是否加上;再检查 /www/zebra/uploads 是否属于 www。

斑马小铺 Zebra Store:dujiao-next 的 Rust + Vue 3 复刻版