版本:v1.0
适用环境:Ubuntu + Apache2 + Node.js + PM2
网站根目录:/var/www/html
域名:jiangzao.cc


0. 核心原则

降噪研究所的工具统一按下面的结构上线:

公开访问路径:
https://jiangzao.cc/tools/工具名/

真实应用目录:
/var/www/html/apps/工具名/

当前线上版本:
/var/www/html/apps/工具名/current

历史版本:
/var/www/html/apps/工具名/releases/v1
/var/www/html/apps/工具名/releases/v2

有后端的工具额外增加 API 路径:

https://jiangzao.cc/api/tools/工具名/

一句话:

/tools/工具名/ 是用户访问入口
/apps/工具名/current 是当前线上版本
/apps/工具名/releases/v1、v2 是真实代码目录
/api/tools/工具名/ 是后端接口入口

1. 工具类型

1.1 静态工具

静态工具只需要浏览器运行,不需要 Node 后端。

示例:

视频报价计算器 quote-calculator
封面阴影工具
简单格式转换工具

特点:

有 index.html
有 CSS / JS
没有 server.js
没有数据库
没有后端接口

访问路径:

/tools/quote-calculator/

1.2 后端工具

后端工具需要 Node 服务、API、缓存、数据库或上传目录。

示例:

封面检测器 thumbnail-checker
选题雷达 topic-radar
多平台数据复盘工具

特点:

有前端 web
有后端 api
可能有 .env
可能有 cache
可能有 uploads
可能有 db
需要 PM2 运行
需要 Apache 反向代理

访问路径:

/tools/thumbnail-checker/

API 路径:

/api/tools/thumbnail-checker/

2. 推荐总目录结构

/var/www/html/
├─ index.html
│
├─ tools/
│  ├─ quote-calculator -> /var/www/html/apps/quote-calculator/current
│  └─ thumbnail-checker -> /var/www/html/apps/thumbnail-checker/current
│
└─ apps/
   ├─ quote-calculator/
   │  ├─ current -> releases/v1
   │  └─ releases/
   │     └─ v1/
   │        ├─ index.html
   │        ├─ app.js
   │        ├─ config.js
   │        └─ assets/
   │
   └─ thumbnail-checker/
      ├─ current -> releases/v1/web
      ├─ releases/
      │  └─ v1/
      │     └─ web/
      │        ├─ index.html
      │        ├─ styles.css
      │        └─ script.js
      │
      ├─ api/
      │  ├─ server.js
      │  ├─ package.json
      │  ├─ ecosystem.config.cjs
      │  ├─ .env
      │  └─ config/
      │
      ├─ data/
      │  └─ cache/
      │     ├─ feed/
      │     ├─ image/
      │     └─ img43/
      │
      ├─ uploads/
      ├─ db/
      ├─ logs/
      └─ backups/

3. Apache 主配置

你的主配置文件:

sudo nano /etc/apache2/sites-available/000-default.conf

<VirtualHost *:443> 中建议使用:

<VirtualHost *:443>

        DocumentRoot /var/www/html
        ServerName jiangzao.cc

        # 网站根目录
        <Directory /var/www/html>
                Options -Indexes +FollowSymLinks
                AllowOverride None
                Require all granted
                DirectoryIndex index.html
        </Directory>

        # 工具公开入口目录
        # /var/www/html/tools/工具名 通过软链接指向 apps/工具名/current
        <Directory /var/www/html/tools>
                Options -Indexes +FollowSymLinks
                AllowOverride None
                Require all granted
                DirectoryIndex index.html
        </Directory>

        # 禁止用户通过 URL 直接访问 /apps/
        # 注意:这里用 LocationMatch,不要用 Directory 禁止 apps,
        # 否则 tools 软链接指向 apps 时可能被误拦截。
        <LocationMatch "^/apps(/|$)">
                Require all denied
        </LocationMatch>

        # 访问 /tools/xxx 时自动补 /
        RedirectMatch 301 ^/tools/([^/]+)$ /tools/$1/

        # 工具后端反代配置统一拆分到独立目录
        IncludeOptional /etc/apache2/jiangzao-conf.d/*.conf

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on
        SSLCertificateFile      /etc/apache2/cert/html/fullchain.pem
        SSLCertificateKeyFile   /etc/apache2/cert/html/private.key
        SSLCertificateChainFile /etc/apache2/cert/html/certificate.crt

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        </FilesMatch>

        <Directory /usr/lib/cgi-bin>
                SSLOptions +StdEnvVars
        </Directory>

</VirtualHost>

检查配置:

sudo apache2ctl configtest

看到:

Syntax OK

重载 Apache:

sudo systemctl reload apache2

4. Apache 后端配置目录

创建独立配置目录:

sudo mkdir -p /etc/apache2/jiangzao-conf.d

启用代理模块,只需要执行一次:

sudo a2enmod proxy proxy_http
sudo apache2ctl configtest
sudo systemctl reload apache2

后续每个有后端的工具,都单独放一个配置文件:

/etc/apache2/jiangzao-conf.d/thumbnail-checker-api.conf
/etc/apache2/jiangzao-conf.d/topic-radar-api.conf

5. 上线静态工具:视频报价计算器

工具名:

quote-calculator

访问路径:

https://jiangzao.cc/tools/quote-calculator/

5.1 创建目录

sudo mkdir -p /var/www/html/apps/quote-calculator/releases/v1
sudo mkdir -p /var/www/html/tools

5.2 上传文件

把报价计算器文件上传到:

/var/www/html/apps/quote-calculator/releases/v1/

目录应类似:

/var/www/html/apps/quote-calculator/releases/v1/
├─ index.html
├─ app.js
├─ config.js
└─ assets/

5.3 创建 current 软链接

不要手动创建 current 目录。

正确命令:

sudo ln -sfn /var/www/html/apps/quote-calculator/releases/v1 /var/www/html/apps/quote-calculator/current

此时:

current -> releases/v1

5.4 创建公开入口软链接

sudo ln -sfn /var/www/html/apps/quote-calculator/current /var/www/html/tools/quote-calculator

最终链路:

/tools/quote-calculator
↓
/apps/quote-calculator/current
↓
/apps/quote-calculator/releases/v1

5.5 设置权限

sudo chown -R www-data:www-data /var/www/html/apps/quote-calculator
sudo chown -h www-data:www-data /var/www/html/tools/quote-calculator

sudo find /var/www/html/apps/quote-calculator -type d -exec chmod 755 {} \;
sudo find /var/www/html/apps/quote-calculator -type f -exec chmod 644 {} \;

5.6 访问测试

https://jiangzao.cc/tools/quote-calculator/

6. 更新静态工具版本

假设报价计算器要上线 v2。

6.1 创建 v2 目录

sudo mkdir -p /var/www/html/apps/quote-calculator/releases/v2

6.2 上传新版文件

上传到:

/var/www/html/apps/quote-calculator/releases/v2/

6.3 切换 current 到 v2

sudo ln -sfn /var/www/html/apps/quote-calculator/releases/v2 /var/www/html/apps/quote-calculator/current
sudo systemctl reload apache2

用户访问地址不变:

https://jiangzao.cc/tools/quote-calculator/

6.4 回滚到 v1

sudo ln -sfn /var/www/html/apps/quote-calculator/releases/v1 /var/www/html/apps/quote-calculator/current
sudo systemctl reload apache2

7. 上线后端工具:封面检测器

工具名:

thumbnail-checker

前端访问:

https://jiangzao.cc/tools/thumbnail-checker/

后端 API:

https://jiangzao.cc/api/tools/thumbnail-checker/

PM2 服务名:

thumbnail-checker-api

Node 端口:

8787

7.1 推荐目录结构

/var/www/html/apps/thumbnail-checker/
├─ current -> releases/v1/web
│
├─ releases/
│  └─ v1/
│     └─ web/
│        ├─ index.html
│        ├─ styles.css
│        └─ script.js
│
├─ api/
│  ├─ server.js
│  ├─ package.json
│  ├─ ecosystem.config.cjs
│  ├─ .env
│  ├─ .env.example
│  └─ config/
│     └─ categories.json
│
├─ data/
│  └─ cache/
│     ├─ feed/
│     ├─ image/
│     └─ img43/
│
├─ uploads/
├─ db/
├─ logs/
└─ backups/

7.2 创建目录

sudo mkdir -p /var/www/html/apps/thumbnail-checker/releases/v1/web
sudo mkdir -p /var/www/html/apps/thumbnail-checker/api
sudo mkdir -p /var/www/html/apps/thumbnail-checker/data/cache/feed
sudo mkdir -p /var/www/html/apps/thumbnail-checker/data/cache/image
sudo mkdir -p /var/www/html/apps/thumbnail-checker/data/cache/img43
sudo mkdir -p /var/www/html/apps/thumbnail-checker/uploads
sudo mkdir -p /var/www/html/apps/thumbnail-checker/db
sudo mkdir -p /var/www/html/apps/thumbnail-checker/logs
sudo mkdir -p /var/www/html/apps/thumbnail-checker/backups
sudo mkdir -p /var/www/html/tools

7.3 上传前端文件

上传到:

/var/www/html/apps/thumbnail-checker/releases/v1/web/

前端文件:

index.html
styles.css
script.js

7.4 上传后端文件

上传到:

/var/www/html/apps/thumbnail-checker/api/

后端文件:

server.js
package.json
ecosystem.config.cjs
.env
.env.example
config/categories.json

注意:

.env 不要放在 web 目录
.env 不要放到 /tools/thumbnail-checker/
.env 不要公开

7.5 创建前端 current 软链接

sudo ln -sfn /var/www/html/apps/thumbnail-checker/releases/v1/web /var/www/html/apps/thumbnail-checker/current

7.6 创建公开入口软链接

sudo ln -sfn /var/www/html/apps/thumbnail-checker/current /var/www/html/tools/thumbnail-checker

最终链路:

/tools/thumbnail-checker
↓
/apps/thumbnail-checker/current
↓
/apps/thumbnail-checker/releases/v1/web

7.7 安装后端依赖

cd /var/www/html/apps/thumbnail-checker/api
npm install

7.8 PM2 配置

ecosystem.config.cjs 推荐写法:

module.exports = {
  apps: [
    {
      name: 'thumbnail-checker-api',
      script: './server.js',
      cwd: '/var/www/html/apps/thumbnail-checker/api',
      env: {
        NODE_ENV: 'production',
        PORT: 8787
      }
    }
  ]
};

启动:

cd /var/www/html/apps/thumbnail-checker/api
pm2 start ecosystem.config.cjs
pm2 save

查看状态:

pm2 list

查看日志:

pm2 logs thumbnail-checker-api

重启:

pm2 restart thumbnail-checker-api

停止:

pm2 stop thumbnail-checker-api

删除旧服务:

pm2 delete thumbnail-checker-api

7.9 Apache API 反向代理

创建独立配置文件:

sudo nano /etc/apache2/jiangzao-conf.d/thumbnail-checker-api.conf

写入:

ProxyPreserveHost On

ProxyPass /api/tools/thumbnail-checker/ http://127.0.0.1:8787/api/
ProxyPassReverse /api/tools/thumbnail-checker/ http://127.0.0.1:8787/api/

检查并重载:

sudo apache2ctl configtest
sudo systemctl reload apache2

7.10 设置权限

普通前端和后端代码:

sudo chown -R www-data:www-data /var/www/html/apps/thumbnail-checker
sudo chown -h www-data:www-data /var/www/html/tools/thumbnail-checker

sudo find /var/www/html/apps/thumbnail-checker -type d -exec chmod 755 {} \;
sudo find /var/www/html/apps/thumbnail-checker -type f -exec chmod 644 {} \;

.env 权限要更严格:

sudo chown www-data:www-data /var/www/html/apps/thumbnail-checker/api/.env
sudo chmod 600 /var/www/html/apps/thumbnail-checker/api/.env

后端可写目录:

sudo chown -R www-data:www-data /var/www/html/apps/thumbnail-checker/data
sudo chown -R www-data:www-data /var/www/html/apps/thumbnail-checker/uploads
sudo chown -R www-data:www-data /var/www/html/apps/thumbnail-checker/db
sudo chown -R www-data:www-data /var/www/html/apps/thumbnail-checker/logs

sudo chmod -R 755 /var/www/html/apps/thumbnail-checker/data
sudo chmod -R 755 /var/www/html/apps/thumbnail-checker/uploads
sudo chmod -R 755 /var/www/html/apps/thumbnail-checker/db
sudo chmod -R 755 /var/www/html/apps/thumbnail-checker/logs

7.11 访问测试

前端:

https://jiangzao.cc/tools/thumbnail-checker/

后端健康检查:

https://jiangzao.cc/api/tools/thumbnail-checker/health

如果后端正常,应该能返回健康检查信息。


8. 更新后端工具版本

以后封面检测器更新前端到 v2:

sudo mkdir -p /var/www/html/apps/thumbnail-checker/releases/v2/web

上传新版前端到:

/var/www/html/apps/thumbnail-checker/releases/v2/web/

切换:

sudo ln -sfn /var/www/html/apps/thumbnail-checker/releases/v2/web /var/www/html/apps/thumbnail-checker/current
sudo systemctl reload apache2

如果只是改前端,不需要重启 PM2。

如果改了后端代码:

cd /var/www/html/apps/thumbnail-checker/api
npm install
pm2 restart thumbnail-checker-api
pm2 save

9. 新增一个后端工具

假设新增:

topic-radar

访问:

/tools/topic-radar/

API:

/api/tools/topic-radar/

端口:

8788

目录:

/var/www/html/apps/topic-radar/
├─ current -> releases/v1/web
├─ releases/v1/web/
├─ api/
├─ data/
├─ uploads/
├─ db/
└─ logs/

前端软链接:

sudo ln -sfn /var/www/html/apps/topic-radar/releases/v1/web /var/www/html/apps/topic-radar/current
sudo ln -sfn /var/www/html/apps/topic-radar/current /var/www/html/tools/topic-radar

API 配置:

sudo nano /etc/apache2/jiangzao-conf.d/topic-radar-api.conf

写:

ProxyPreserveHost On

ProxyPass /api/tools/topic-radar/ http://127.0.0.1:8788/api/
ProxyPassReverse /api/tools/topic-radar/ http://127.0.0.1:8788/api/

PM2 服务名:

topic-radar-api

10. 命名规范

工具目录统一使用英文小写短横线:

quote-calculator
thumbnail-checker
topic-radar
video-review

对应:

/tools/quote-calculator/
/tools/thumbnail-checker/
/api/tools/thumbnail-checker/

PM2 服务名:

工具名-api

例如:

thumbnail-checker-api
topic-radar-api

Apache 配置文件:

工具名-api.conf

例如:

thumbnail-checker-api.conf
topic-radar-api.conf

11. 常用检查命令

查看软链接

ls -l /var/www/html/tools
ls -l /var/www/html/apps/quote-calculator
ls -l /var/www/html/apps/thumbnail-checker

应该看到类似:

quote-calculator -> /var/www/html/apps/quote-calculator/current
thumbnail-checker -> /var/www/html/apps/thumbnail-checker/current
current -> /var/www/html/apps/thumbnail-checker/releases/v1/web

检查 Apache

sudo apache2ctl configtest
sudo systemctl reload apache2

查看 Apache 日志

sudo tail -n 100 /var/log/apache2/error.log
sudo tail -n 100 /var/log/apache2/access.log

查看 PM2 服务

pm2 list
pm2 logs thumbnail-checker-api
pm2 restart thumbnail-checker-api
pm2 save

查看端口是否监听

sudo ss -lntp | grep 8787

如果后端正常,应看到 Node 服务监听 8787


12. 常见问题

12.1 访问工具 404

检查:

ls -l /var/www/html/tools
ls -l /var/www/html/apps/工具名

确认:

/tools/工具名 -> /apps/工具名/current
current -> releases/v1 或 releases/v1/web

确认真实目录里有:

index.html

12.2 访问工具 403

通常是权限或 Apache 配置问题。

检查配置里是否有:

Options -Indexes +FollowSymLinks
Require all granted

修复权限:

sudo chown -R www-data:www-data /var/www/html/apps/工具名
sudo find /var/www/html/apps/工具名 -type d -exec chmod 755 {} \;
sudo find /var/www/html/apps/工具名 -type f -exec chmod 644 {} \;

12.3 CSS / JS 加载失败

前端资源路径应该使用相对路径:

<link rel="stylesheet" href="./styles.css">
<script src="./script.js"></script>

不要写:

<link rel="stylesheet" href="/styles.css">
<script src="/script.js"></script>

因为 /script.js 会访问:

https://jiangzao.cc/script.js

而不是:

https://jiangzao.cc/tools/thumbnail-checker/script.js

12.4 API 404

检查前端请求路径是否正确:

const API_BASE = '/api/tools/thumbnail-checker';

请求应类似:

/api/tools/thumbnail-checker/health
/api/tools/thumbnail-checker/bilibili-feed
/api/tools/thumbnail-checker/bili-image

检查 Apache 反代配置:

cat /etc/apache2/jiangzao-conf.d/thumbnail-checker-api.conf

检查 Node 后端是否运行:

pm2 list
sudo ss -lntp | grep 8787

12.5 API 502

通常是 Node 后端没启动,或者端口不对。

检查 PM2:

pm2 list
pm2 logs thumbnail-checker-api

检查端口:

sudo ss -lntp | grep 8787

确认 Apache 配置:

ProxyPass /api/tools/thumbnail-checker/ http://127.0.0.1:8787/api/
ProxyPassReverse /api/tools/thumbnail-checker/ http://127.0.0.1:8787/api/

12.6 current 是普通目录,不是软链接

检查:

ls -l /var/www/html/apps/quote-calculator/

如果看到:

current

但没有:

current -> ...

说明它是普通目录。

删除后重新创建软链接:

sudo rm -rf /var/www/html/apps/quote-calculator/current
sudo ln -sfn /var/www/html/apps/quote-calculator/releases/v1 /var/www/html/apps/quote-calculator/current

13. 最终上线流程速查

静态工具第一次上线

sudo mkdir -p /var/www/html/apps/工具名/releases/v1
sudo mkdir -p /var/www/html/tools

# 上传文件到 releases/v1

sudo ln -sfn /var/www/html/apps/工具名/releases/v1 /var/www/html/apps/工具名/current
sudo ln -sfn /var/www/html/apps/工具名/current /var/www/html/tools/工具名

sudo chown -R www-data:www-data /var/www/html/apps/工具名
sudo chown -h www-data:www-data /var/www/html/tools/工具名

sudo apache2ctl configtest
sudo systemctl reload apache2

静态工具更新

sudo mkdir -p /var/www/html/apps/工具名/releases/v2

# 上传新版到 releases/v2

sudo ln -sfn /var/www/html/apps/工具名/releases/v2 /var/www/html/apps/工具名/current
sudo systemctl reload apache2

后端工具第一次上线

sudo mkdir -p /var/www/html/apps/工具名/releases/v1/web
sudo mkdir -p /var/www/html/apps/工具名/api
sudo mkdir -p /var/www/html/apps/工具名/data
sudo mkdir -p /var/www/html/apps/工具名/uploads
sudo mkdir -p /var/www/html/apps/工具名/db
sudo mkdir -p /var/www/html/apps/工具名/logs
sudo mkdir -p /var/www/html/tools

# 上传前端到 releases/v1/web
# 上传后端到 api

sudo ln -sfn /var/www/html/apps/工具名/releases/v1/web /var/www/html/apps/工具名/current
sudo ln -sfn /var/www/html/apps/工具名/current /var/www/html/tools/工具名

cd /var/www/html/apps/工具名/api
npm install
pm2 start ecosystem.config.cjs
pm2 save

sudo nano /etc/apache2/jiangzao-conf.d/工具名-api.conf

sudo apache2ctl configtest
sudo systemctl reload apache2

14. 最终记忆

静态工具:
/tools/工具名/ -> /apps/工具名/current -> /apps/工具名/releases/v1

后端工具:
/tools/工具名/ -> 前端 web
/api/tools/工具名/ -> Node 后端
PM2 管理 Node
Apache 负责反向代理
.env、db、cache、uploads、logs 不公开

标签: none

添加新评论