FRP Multi-Ports

## 架构概览

```
域名 example.xyz
  → Apache (服务器 :80)
    → frps (服务器 :8080, vhost_http_port)
      → frpc 隧道 (端口 7000)
        → 本地服务 (多端口)
```

## 涉及的文件

| 位置 | 文件 | 作用 |
|------|------|------|
| 本地 | `/opt/frp_0.69.1_linux_amd64/frpc.toml` | frp 客户端,注册代理 |
| 本地 | `/home/user/.config/systemd/user/frpc.service` | frpc 的 systemd 服务 |
| 服务器 | `/opt/frp/frps.toml` | frp 服务端,含 `vhost_http_port = 8080` |
| 服务器 | `/etc/apache2/sites-enabled/000-default.conf` | Apache 转发请求到 frps |
| 本地项目 | `/opt/electrical/next.config.ts` | Next.js 的 `basePath` 配置 |

## 当前代理配置 (frpc.toml)

```toml
[common]
server_addr = xxx.xxx.xxx.xxx
server_port = 7000
auth.token = secure-token-example
tls.enable = true

[opengrok-web]
type = http
local_port = 8090
custom_domains = example.xyz
locations = /opengrok

[elec-web]
type = http
local_port = 3000
custom_domains = example.xyz
locations = /elec
```

## 当前 Apache 配置 (服务器)

```apache
ProxyPass /opengrok http://127.0.0.1:8080/opengrok
ProxyPassReverse /opengrok http://127.0.0.1:8080/opengrok
ProxyPass /elec http://127.0.0.1:8080/elec
ProxyPassReverse /elec http://127.0.0.1:8080/elec
```

## 添加新子地址的步骤

假设新增 `/foo` 指向本地端口 `5000`:

### 1. 本地 frpc.toml 添加代理

```toml
[foo-web]
type = http
local_port = 5000
custom_domains = example.xyz
locations = /foo
```

### 2. 服务器 Apache 添加转发

```apache
ProxyPass /foo http://127.0.0.1:8080/foo
ProxyPassReverse /foo http://127.0.0.1:8080/foo
```

### 3. 重启服务

```bash
# 本地
systemctl --user restart frpc

# 服务器
systemctl reload apache2
```

### 4. 如果是 Next.js 项目,需设 basePath

```ts
// next.config.ts
const nextConfig: NextConfig = {
  basePath: "/foo",
  // ...
};
```

然后重新构建:`npx next build && npx next start -p 5000`

## 关键注意事项

- **同一域名必须用 `locations` 区分**:两个 HTTP 代理不能在相同 `custom_domains` 下都没有 `locations`,会报 `router config conflict`
- **不用引号**:frp 0.69.1 解析 TOML 有兼容问题,值不加引号更稳定
- **不要用 `[[proxies]]` 数组格式**:本版本不支持,代理名会被错误解析
- **Next.js 必须 `basePath`**:否则 CSS/JS 路径 `/_next/...` 无法通过 frp 路由正确加载

Previous Article
Next Article