# Linuxサーバーの導入

MoreLogin をヘッドレス Ubuntu サーバーにデプロイし、ローカル 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 バックグラウンドでさらにログインを開始する

`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 にログインする (必須)

> [!CAUTION]
**他のローカル API エンドポイントを呼び出す前にログインする必要があります。** ヘッドレス サーバーには手動でログインするための GUI がないため、API 経由で認証する必要があります。この手順を行わないと、すべての API 呼び出しは次の値を返します。

```json
{"status": "error", "code": 401, "message": "ログインステータスの有効期限が切れています。再度ログインしてください"}
```


### 3.1 API 認証情報を取得する

MoreLogin デスクトップ クライアント (ログインしている任意のマシン上) を開き、**設定 → API と MCP** に移動します。 **Open API** セクションから **APP ID** と **API Key** をコピーします。

![MoreLogin API 設定 — オープン API セクションから APP ID と API キーをコピー](/assets/image.cfac9a4c31ae47e8434739e42cab4601ee08d737bba4fccba40f2f3bc78e9648.e4db3d38.png)

### 3.2curl経由でログインする

資格情報を使用してログイン エンドポイントを呼び出します。

```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 の読み取り、スクリプトの挿入、スクリーンショットのキャプチャ)。

**推奨事項:**
- リモート アクセスには socat の代わりに **SSH トンネル**を使用します: `ssh -L 40000:127.0.0.1:40000 user@server`
- socat を使用する必要がある場合は、ファイアウォール ルールを使用してアクセスを **特定の IP のみ**に制限してください
- **VPN** またはクラウド プロバイダーのセキュリティ グループを使用して、受信トラフィックを制限します
- IP 制限なしで、公開サーバー上でポート `40001` / CDP ポートを `0.0.0.0` に決して開かないでください**



### 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]
運用環境では、返された `debugPort` を使用して、各 `/api/env/start` 呼び出しの後に 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 ポートの 2 番目のトンネルを開きます:**

```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]
ポート範囲が事前にわかっている場合は、1 つのコマンドで両方のトンネルを組み合わせることができます。例:

```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]
**リモート マシンから実行しますか?** 2 つのアプローチ:
**オプション 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 リファレンス](/ja/api-reference/browser) でお使いのバージョンを確認してください。応答形式はリリースによって異なる場合があります。


## パフォーマンスベンチマーク

次の結果は、[フル ストレス テスト スクリプト](https://github.com/MoreLoginBrowser/MoreLogin-API-Demos/blob/main/MoreLogin-Python/linux_server_test.py) を使用して Ubuntu 24.04 サーバー VM (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
```

> AppImage を配置した場所と一致するように `WorkingDirectory` パスと `ExecStart` パスを調整します。


> [!TIP]
運用環境では、`root` として実行する代わりに専用ユーザー (`morelogin` など) を作成し、それに応じてファイルの所有権と権限を調整することを検討してください。現在 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) を参照)、ファイアウォール ルールで転送ポートが許可されていることを確認します。

### ローカル API への `curl` は「接続が拒否されました」を返します

**原因:** 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](/ja/api-reference/browser) |
| 認証設定 | [認証ガイド](/ja/api-reference/getting-started/authentication) |
| 劇作家 / Selenium / 人形遣いの例 | [自動化の例](/ja/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 ガイド](/ja/cli/quick-start) |