# Linux服务器部署

在无头 Ubuntu 服务器上部署 MoreLogin，并通过本地 API 自动执行浏览器 — 无需桌面环境。

## 你将取得什么成就

读完本指南后，您将拥有：

1. Ubuntu 24.04 无头服务器上运行的 MoreLogin 实例
2. 配置网络转发，以便外部计算机可以通过 CDP（Chrome DevTools 协议）进行连接
3. 一个有效的 Python 自动化脚本，用于创建、启动、控制和清理浏览器


## 架构概述

```
┌──────────────────────────────────────────────────────────┐
│                    Ubuntu 24.04 Server                   │
│                                                          │
│  ┌──────────────┐    ┌───────────────────────────────┐   │
│  │   xvfb       │───▶│  MoreLogin AppImage           │   │
│  │ (virtual     │    │  Local API :40000             │   │
│  │  display)    │    │  CDP debug :<dynamic>         │   │
│  │              │    │    (127.0.0.1, per profile)   │   │
│  └──────────────┘    └───────────────────────────────┘   │
│                              │                           │
│                        socat forwarding                  │
│                              │                           │
│                     0.0.0.0:40001 → 127.0.0.1:40000      │
│                     0.0.0.0:<N+1> → 127.0.0.1:<N>        │
└──────────────────────────────────────────────────────────┘
                               │
                          External machine
                     (Playwright / Puppeteer / Selenium)
```

> [!NOTE]
CDP 调试端口是**动态** — 每个浏览器都有自己的端口，由 `/api/env/start` 端点返回。上图使用 `<N>` 作为占位符。


## 先决条件

| 要求 | 详情 |
|  --- | --- |
| **操作系统** | Ubuntu 24.04 服务器 (x86_64) |
| **推荐规格** | 8 个 vCPU、8 GB RAM（支持 ~5 个并发浏览器环境） |
| **网络** | 出站互联网访问；打开入站端口 `40001` 和您选择的转发 CDP 端口，或改用 SSH 隧道 |
| **Python**（可选） | Python 3.8+ 和 `pip` 用于运行示例脚本 |


## 第 1 步 — 安装系统依赖项

通过 SSH 连接到您的服务器并安装所需的软件包：

```bash
# FUSE support (required for AppImage)
sudo apt install -y libfuse2t64

# GTK / accessibility / display libraries
sudo apt install -y libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0
sudo apt install -y libcups2
sudo apt install -y libgtk-3-0 libgdk-pixbuf2.0-0
sudo apt install -y libgbm1 libxkbcommon0 libasound2t64

# Virtual framebuffer (headless display)
sudo apt install -y xvfb

# TCP forwarder
sudo apt install -y socat
```

### 安装字体（可选）

如果浏览器页面呈现无文本或显示缺失字符，请安装相应的字体包：

```bash
# CJK (Chinese, Japanese, Korean)
sudo apt install -y fonts-noto-cjk fonts-noto-cjk-extra

# Arabic
sudo apt install -y fonts-noto-color-emoji fonts-noto-extra
```

> 对于其他语言，请安装匹配的[Noto 字体系列](https://fonts.google.com/noto) 软件包。


## 第 2 步 — 下载并启动 MoreLogin

### 2.1 下载AppImage

```bash
wget https://get.morelogin.com/client/prod/linux/x64/2.54.0/MoreLogin_x86_64_2.54.0.AppImage
chmod +x MoreLogin_x86_64_2.54.0.AppImage
```

> 将 `2.54.0` 替换为您的 MoreLogin 帐户或[下载页面](https://www.morelogin.com/download/) 上提供的最新版本。


### 2.2 后台启动 MoreLogin

使用 `xvfb-run` 提供虚拟显示，然后运行 AppImage：

```bash
nohup xvfb-run -a ./MoreLogin_x86_64_2.54.0.AppImage --no-sandbox > morelogin.log 2>&1 &
```

验证是否启动成功：

```bash
# Check the process is running
ps aux | grep MoreLogin
```

> 该过程可能需要 5-10 秒才能完全初始化。


## 第3步——通过API登录MoreLogin（必填）

> [!WARNING]
**您必须先登录，然后才能调用任何其他本地 API 端点。** 在无头服务器上，没有用于手动登录的 GUI，因此您必须通过 API 进行身份验证。如果没有这一步，所有 API 调用都将返回：

```json
{"status": "error", "code": 401, "message": "您的登录状态已过期，请重新登录"}
```


### 3.1 获取您的 API 凭证

打开 MoreLogin 桌面客户端（在您登录的任何计算机上）并导航至 **设置 → API 和 MCP**。从 **Open API** 部分复制 **APP ID** 和 **API Key**：

![MoreLogin API 设置 — 从 Open API 部分复制 APP ID 和 API Key](/assets/image.cfac9a4c31ae47e8434739e42cab4601ee08d737bba4fccba40f2f3bc78e9648.2f2649be.png)

### 3.2 通过 curl 登录

使用您的凭据调用登录端点：

```bash
curl -X POST http://127.0.0.1:40000/api/user/login \
  -H "Content-Type: application/json" \
  -d '{
    "apiId": "YOUR_APP_ID",
    "apiKey": "YOUR_API_KEY"
  }'
```

成功的响应如下所示：

```json
{"code": 0, "msg": null, "data": true}
```

### 3.3 验证登录

通过列出浏览器来确认 API 已准备就绪：

```bash
curl -s -X POST http://127.0.0.1:40000/api/env/page \
  -H "Content-Type: application/json" \
  -d '{"pageNo": 1, "pageSize": 1}'
```

> `{"code":0, ...}` 响应表示您已登录且 API 已准备就绪。


> **检查点：** 您的 MoreLogin 服务器已完全运行。继续进行[步骤 4](#step-4--configure-network-forwarding-socat) 进行远程访问，或者如果在同一服务器上运行脚本，则直接跳到[步骤 5](#step-5--quick-automation-example)。


> [!NOTE]
只要 MoreLogin 进程正在运行，登录会话就会持续存在。如果重新启动AppImage，则需要重新登录。


## 步骤 4 — 配置网络转发 (socat)

默认情况下，本地 API (`:40000`) 和 CDP 调试端口都绑定到 `127.0.0.1`。如果您需要从外部计算机（例如您的开发笔记本电脑）访问它们，请使用 `socat` 转发流量。

> [!WARNING]
**安全风险 - 不要将这些端口暴露给公共互联网。**
- 对于大多数端点，本地 API **没有内置身份验证**。
- CDP 调试端口授予浏览器实例的**完全远程控制**（读取 cookie、注入脚本、捕获屏幕截图）。

**建议：**
- 使用 **SSH 隧道** 而不是 socat 进行远程访问：`ssh -L 40000:127.0.0.1:40000 user@server`
- 如果您必须使用 socat，请使用防火墙规则将访问限制为 **仅限特定 IP**
- 使用 **VPN** 或云提供商安全组来限制入站流量
- **绝不**在没有 IP 限制的面向公众的服务器上打开到 `0.0.0.0` 的端口 `40001` / CDP 端口



### 4.1 转发本地API端口

```bash
nohup socat TCP-LISTEN:40001,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:40000 &
```

> 外部计算机现在可以访问位于 `http://<server-ip>:40001` 的 API。


### 4.2 转发 CDP 调试端口

当您通过 API 启动浏览器时，响应会包含**动态** `debugPort`（例如 `9222`）。每个浏览器环境可能接收不同的端口。转发它，以便外部自动化工具（Playwright、Puppeteer、Selenium）可以连接：

```bash
# Example: if debugPort=9222, forward to external port 9223 (debugPort + 1)
# Adjust both ports to match the actual debugPort returned by /api/env/start
nohup socat TCP-LISTEN:9223,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:9222 &
```

> [!WARNING]
同时运行多个浏览器时，请确保转发的端口不会与其他浏览器的调试端口发生冲突。例如，如果浏览器环境 A 收到 `debugPort=9222`，并且您转发到 `9223`，但浏览器环境 B 收到 `debugPort=9223`，则会出现端口冲突。考虑使用更大的偏移量或专用端口范围。


> [!TIP]
在生产中，在每次 `/api/env/start` 调用后使用返回的 `debugPort` **动态**创建 socat 转发。请参阅 [Python 示例](#52-create--start--automate--cleanup) 了解有效的实现。


> 如果在同一服务器上运行自动化脚本，您可以跳过 socat 并直接连接到 `127.0.0.1`。


### 4.3 开放防火墙端口

如果您使用 socat，请仅限制对受信任 IP 的访问：

```bash
# Allow only a specific IP (recommended)
sudo ufw allow from <YOUR_IP> to any port 40001 proto tcp
sudo ufw allow from <YOUR_IP> to any port 9223 proto tcp

# Or allow from any IP (NOT recommended for production)
# sudo ufw allow 40001/tcp
# sudo ufw allow 9223/tcp
```

### 4.4 推荐：使用 SSH 隧道

为了实现最安全的远程访问，请使用 SSH 隧道 — 无需更改防火墙或 socat。

由于 CDP 端口是**动态**（在启动浏览器时分配），因此工作流程为：

1. **首先为 API 端口建立隧道：**

```bash
# Run this on your local machine
ssh -L 40000:127.0.0.1:40000 user@<server-ip>
```
2. **通过隧道 API (`http://127.0.0.1:40000/api/env/start`) 启动浏览器**并读取返回的 `debugPort`。
3. **为 CDP 端口打开第二条隧道：**

```bash
# Replace <debugPort> with the actual port returned by the API
ssh -L <debugPort>:127.0.0.1:<debugPort> user@<server-ip>
```
4. 从本地 Playwright/Puppeteer 脚本**连接**到 `http://127.0.0.1:<debugPort>`，就像服务器位于本地一样。


> [!TIP]
如果您事先知道端口范围，则可以将两个隧道组合在一个命令中，例如：

```bash
ssh -L 40000:127.0.0.1:40000 -L 9222:127.0.0.1:9222 -L 9223:127.0.0.1:9223 user@<服务器IP>
```
但实际上，首先启动 API 隧道，然后根据需要添加每个浏览器的隧道会更容易。


## 第 5 步 — 快速自动化示例

下面是一个最小的 Python 示例，显示了浏览器的完整生命周期。有关具有并发性和错误处理功能的完整生产就绪脚本，请参阅 [GitHub 上的完整示例](https://github.com/MoreLoginBrowser/MoreLogin-API-Demos/blob/main/MoreLogin-Python/linux_server_test.py)。

### 5.1 安装Python依赖项

```bash
pip install requests playwright
```

> Playwright 在此仅用于其 CDP 客户端 (`connect_over_cdp`)。您**不需要**运行 `playwright install` — MoreLogin 提供自己的浏览器。


### 5.2 创建→启动→自动化→清理

此示例假设脚本与 MoreLogin **在同一服务器**上运行。远程场景请参见代码后的注释。

```python
import requests
from playwright.sync_api import sync_playwright

# ── Configuration ──────────────────────────────────────────
# Local:  script runs on the SAME server as MoreLogin
# Remote: script runs on a DIFFERENT machine — see notes below
API_BASE  = "http://127.0.0.1:40000"


# ① Create a browser profile
resp = requests.post(f"{API_BASE}/api/env/create/quick", json={
    "browserTypeId": 1,
    "operatorSystemId": 1,
    "quantity": 1
})
resp_data = resp.json()
assert resp_data["code"] == 0, f"Create failed: {resp_data}"
env_id = resp_data["data"]["envIds"][0]
print(f"✅ Created profile: {env_id}")


# ② Start the profile (headless)
resp = requests.post(f"{API_BASE}/api/env/start", json={
    "envId": env_id
})
resp_data = resp.json()
assert resp_data["code"] == 0, f"Start failed: {resp_data}"
debug_port = resp_data["data"]["debugPort"]   # Dynamic — different for each profile
print(f"✅ Started — debug port: {debug_port}")


# ③ Build the CDP URL
cdp_url = f"http://127.0.0.1:{debug_port}"


# ④ Connect via CDP and automate
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(cdp_url)
    page = browser.contexts[0].pages[0]
    page.goto("https://www.google.com")
    page.screenshot(path=f"screenshot_{env_id}.png")
    print(f"✅ Screenshot saved")
    # Use disconnect() — not close() — to detach without killing the browser.
    # The profile will be stopped cleanly via the API in step ⑤.
    browser.disconnect()


# ⑤ Stop the profile
requests.post(f"{API_BASE}/api/env/close", json={"envId": env_id})
print(f"✅ Profile stopped")


# ⑥ Delete the profile
requests.post(f"{API_BASE}/api/env/remove", json={"envIds": [env_id]})
print(f"✅ Profile deleted")
```

> [!NOTE]
**从远程计算机运行？** 两种方法：
**选项 A — SSH 隧道（推荐）：**
设置从本地计算机到服务器的 SSH 隧道（请参阅 [§ 4.4](#44-recommended-use-ssh-tunnel-instead)），然后保留 `API_BASE = "http://127.0.0.1:40000"` 和 `cdp_url = f"http://127.0.0.1:{debug_port}"` — SSH 使远程端口显示为本地。
**选项 B — 服务器上的 socat：**
在 **服务器** 上，为 API 端口和每个 CDP 端口启动 socat 转发：

```bash
# 在服务器上运行这些，而不是在本地计算机上
socat TCP-LISTEN:40001,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:40000 &
socat TCP-LISTEN:$((debug_port+1)),fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:$debug_port &
```
然后在脚本中设置 `API_BASE = "http://<server-ip>:40001"` 和 `cdp_url = f"http://<server-ip>:{debug_port + 1}"`。
⚠️ 使用防火墙规则限制访问 - 请参阅 [§ 4.3](#43-open-firewall-ports)。


> [!IMPORTANT]
`resp.json()["data"]["envIds"]` 结构与当前的 `/api/env/create/quick` 响应格式匹配。如果您遇到不同的形状（例如 `data: ["id1", ...]`），请检查您的版本的 [API 参考](/zh/api-reference/browser) - 响应格式可能因版本而异。


## 性能基准

使用[完整压力测试脚本](https://github.com/MoreLoginBrowser/MoreLogin-API-Demos/blob/main/MoreLogin-Python/linux_server_test.py)在 Ubuntu 24.04 服务器虚拟机（8 个 vCPU、8 GB RAM）上获得以下结果：

| 指标 | 数值 |
|  --- | --- |
| **总运行次数** | 100 |
| **并发** | 4（同时） |
| **成功率** | 100.0% |
| **总时间** | 604.06秒 |
| **每项任务的平均时间** | 6.04秒 |
| **吞吐量** | 0.17 任务/秒 |


> 这些数字作为基线。实际性能取决于服务器规格、网络条件和页面复杂性。


## 生产部署 (systemd)

对于生产服务器，将 MoreLogin 作为 **systemd 服务** 运行，以在启动时自动启动、在崩溃时重新启动以及集中日志记录。

### 创建服务文件

```bash
sudo tee /etc/systemd/system/morelogin.service > /dev/null <<'EOF'
[Unit]
Description=MoreLogin Browser (headless)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/morelogin
ExecStart=/usr/bin/xvfb-run -a /opt/morelogin/MoreLogin_x86_64_2.54.0.AppImage --no-sandbox
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF
```

> 调整 `WorkingDirectory` 和 `ExecStart` 路径以匹配您放置 AppImage 的位置。


> [!TIP]
对于生产，请考虑创建专用用户（例如 `morelogin`）而不是作为 `root` 运行，并相应地调整文件所有权和权限。如果 AppImage 当前需要 root 权限，您可以保留 `User=root`，但最佳实践是在非 root 帐户下隔离该进程。


### 启用并启动

```bash
sudo systemctl daemon-reload
sudo systemctl enable morelogin    # Auto-start on boot
sudo systemctl start morelogin     # Start now
```

### 管理服务

```bash
sudo systemctl status morelogin    # Check status
sudo journalctl -u morelogin -f    # Stream logs
sudo systemctl restart morelogin   # Restart
sudo systemctl stop morelogin      # Stop
```

> [!NOTE]
重新启动后，您必须再次调用[登录端点](#32-log-in-via-curl) - API 会话无法在进程重新启动后继续存在。对于自动恢复，请考虑添加 `ExecStartPost` 脚本或在服务启动后调用登录端点的运行状况检查 cron 作业。


## 故障排除

### MoreLogin 无法启动

```
AppImages require FUSE to run.
```

**修复：** 安装 FUSE 支持：

```bash
sudo apt install -y libfuse2t64
```

### 浏览器页面显示空白文本/缺失字符

**修复：** 安装目标语言的字体包（请参阅[步骤 1 - 安装字体](#install-fonts-optional)）。

### CDP 连接被外部机器拒绝

**原因：** CDP 调试端口默认绑定到 `127.0.0.1`。

**修复：** 设置 socat 转发（请参阅[步骤 4](#step-4--configure-network-forwarding-socat)）并确保防火墙规则允许转发的端口。

### `curl` 到本地 API 返回“连接被拒绝”

**原因：** MoreLogin 尚未完成启动，或进程崩溃。

**修复：**

1. 启动后等待 5-10 秒
2. 检查 `morelogin.log` 是否有错误
3. 验证进程正在运行：`ps aux | grep MoreLogin`


### API返回401“登录状态已过期”

```json
{"status": "error", "code": 401, "message": "Your login status has expired, please log in again"}
```

**原因：** 您没有通过API登录，或者MoreLogin进程被重启。

**修复：** 在任何其他 API 调用之前调用登录端点（请参阅[步骤 3](#step-3--log-in-to-morelogin-via-api-required)）。

## 下一步

| 目标 | 链接 |
|  --- | --- |
| 完整的浏览器 API 参考 | [浏览器 API](/zh/api-reference/browser) |
| 认证设置 | [身份验证指南](/zh/api-reference/getting-started/authentication) |
| Playwright / Selenium / Puppeteer 示例 | [自动化示例](/zh/api-reference/examples) |
| 完整的Linux压力测试脚本 | [GitHub — linux_server_test.py](https://github.com/MoreLoginBrowser/MoreLogin-API-Demos/blob/main/MoreLogin-Python/linux_server_test.py) |
| CLI 快速入门 | [CLI 指南](/zh/cli/quick-start) |