SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-01

Claude APIをUbuntu VPSで始める方法

Ubuntu 24.04 VPSでClaude API keyを安全に設定し、Pythonでログ説明ツールを作ります。streaming、型付きエラー処理、systemd、実際のコスト制御まで解説します。

構築するもの

新しい Ubuntu 24.04 VPS 上で動作するコマンドラインツールを構築します。エラーメッセージまたはログの一部をパイプで渡すと、平易な英語による診断結果が返ります: journalctl -u nginx -n 50 | explain。Python のコードはおそらく約60行です。実際の Claude API アプリケーションに必要な要素をすべて扱います。適切に保存した key、virtualenv、SDK の response shapes、streaming、typed exception chain、さらに手動操作なしで実行する systemd unit です。

このプロジェクトを選んだのには理由があります。多くの「初めての API アプリケーション」チュートリアルでは、二度と開かない chatbot を作ります。ログ説明ツールは初日からサーバー上で役立ちます。また、初心者が実際によく間違える2つの点にも取り組めます。response object を正しく読み取ることと、支出を制御することです。API は token 単位で課金され、上限は自分で設定したものだけです。そのため、ここではコスト制御を後付けではなく設計要件として扱います。これは、同じ VPS 上で tmux を使って Claude Code を実行する段階に進んだときにも重要な考え方です。

ConsoleからAPI keyを取得する

API accessはplatform.claude.comのAnthropic Consoleで管理します。サインアップ後、Settings → API Keysでkeyを作成します(ドキュメントからplatform.claude.com/settings/keysへ直接移動できます)。keyは1回だけ表示され、sk-ant-で始まります。後から再取得できないため、すぐにcopyするか、削除して再発行してください。

料金については、2026年7月時点でAPIに継続的なfree tierはありません。Anthropicの料金ドキュメントによると、新規ユーザーにはテスト用の少額のfree creditsが付与されます。正確な金額はサインアップ時にConsoleに表示される値です。creditsを使い切ると、requestが成功する前にaccountへ入金する必要があります。これはclaude.aiのsubscriptionとは別です。ProまたはMax planにAPI creditは含まれません。また、API keyでchat appを利用することもできません。subscriptionとAPIのどちらを選ぶかは別の論点です。実際に必要なClaude planを確認する

keyは1つのprojectまたはserverに限定して作成してください。keyが漏えいした場合、十分に長い期間があれば、いずれ漏えいします。他の所有リソースに影響を与えずにrevokeできるようにしてください。

鍵を .bashrc に保存しない

よくある対応は export ANTHROPIC_API_KEY=sk-ant-...~/.bashrc に追加することです。これは避けてください。問題は3つあります。

  • すべてのプロセスが継承します。 ログインシェルでエクスポートした環境変数は、起動するすべてのプロセスに伝播します。Webアプリ、環境変数をバグレポートに出力してしまうクラッシュレポーター、誰かが有効にしたままの phpinfo() ページも対象です。鍵の露出範囲が「このユーザーが実行するすべてのもの」になります。
  • 入力内容が ~/.bash_history に保存されます。 export を手動で一度実行すると、鍵が平文ファイルに永続的に残り、ホームディレクトリのすべてのバックアップにも同期されます。
  • systemd が必要とするときに存在しません。 サービスは .bashrc を読み込まないため、スクリプトを unit に移行したときにこの方法は機能しません。通常は、午前6時に原因不明の 401 として発生します。

サーバーでは、必要なプロセスだけが読み込む、専用の環境ファイルを 600 の権限で用意する方法が適切です。

sudo mkdir -p /opt/explain
sudo install -m 600 -o root -g root /dev/null /etc/claude-explain.env
printf 'ANTHROPIC_API_KEY=sk-ant-YOUR-KEY-HERE\n' | sudo tee /etc/claude-explain.env >/dev/null

エディターのスワップファイルに鍵を残したくない場合は、エディターではなく printf から tee を使用してください。どちらの方法でも、ls -l /etc/claude-explain.env-rw------- を読み取り、root が所有していることを確認します。対話型シェルにはラッパー(下記)を使用して呼び出しごとに鍵を渡し、systemd には EnvironmentFile= を使用します。root が権限を下げる前にファイルを読み込むため、サービスユーザーにそのファイルの読み取り権限は必要ありません。鍵がコード、git、ps の出力、シェル履歴に現れることはありません。

venv に SDK をインストールする

Ubuntu 24.04 には PEP 668 の適用された Python 3.12 が含まれています。そのため、システムインタープリターに対して bare pip install anthropic を実行すると、error: externally-managed-environment で失敗します。このエラーは OS が意図どおりに動作していることを示します。virtualenv を使用してください。

sudo apt update && sudo apt install -y python3-venv
sudo python3 -m venv /opt/explain/venv
sudo /opt/explain/venv/bin/pip install anthropic

サーバーではアクティベーション操作は必要ありません。/opt/explain/venv/bin/python を直接呼び出すと、常に venv のパッケージが使用されます。

最初の呼び出しとレスポンスの正しい読み取り

import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1000,
    messages=[{"role": "user", "content": "Explain what a systemd unit file is in three sentences."}],
)

for block in response.content:
    if block.type == "text":
        print(block.text)

この12行には、APIの基本的な考え方の大部分が含まれています。まず、引数なしのanthropic.Anthropic()は環境変数からキーを読み取ります。キーを文字列リテラルとして渡してはいけません。次に、response.contentは文字列ではなく、コンテンツブロックのリストです。これを直接出力すると、初めて使う場合によくある次の出力になります。

[TextBlock(citations=None, text='A systemd unit file is...', type='text')]

これはバグではありません。オブジェクトのreprです。レスポンスには、複数のブロックタイプ(テキスト、ツール呼び出し、思考)が含まれる場合があります。そのため、block.type == "text"を確認してから.textを扱うように反復処理します。このループを初日から組み込めば、「文字化けした内容が出力される」という問題の混乱を防げます。

モデルIDには、正確にclaude-opus-4-8を使用します。現行世代のIDには日付が含まれません。日付のサフィックスを追加するよう促す古い習慣や古いブログ記事に従わないでください。追加すると404が発生します。詳細は以下で説明します。

実際のツール: explain

以下が完全なプログラムです。標準入力を受け取り、診断結果をストリーム出力し、エラーを処理します。

#!/usr/bin/env python3
"""explain: pipe an error or log excerpt in, get a diagnosis out."""
import sys
import anthropic

MODEL = "claude-opus-4-8"

def main() -> int:
    text = sys.stdin.read().strip()
    if not text:
        print("usage: journalctl -u nginx -n 50 | explain", file=sys.stderr)
        return 1

    client = anthropic.Anthropic()
    try:
        with client.messages.stream(
            model=MODEL,
            max_tokens=1500,
            system=(
                "You are a senior Linux sysadmin. The user pipes you server "
                "logs or error output. Name the most likely cause outright, "
                "then give the commands to confirm and fix it. Be terse."
            ),
            messages=[{"role": "user", "content": text}],
        ) as stream:
            for chunk in stream.text_stream:
                print(chunk, end="", flush=True)
        print()
    except anthropic.RateLimitError as e:
        retry_after = e.response.headers.get("retry-after", "60")
        print(f"rate limited; retry in {retry_after}s", file=sys.stderr)
        return 2
    except anthropic.APIStatusError as e:
        print(f"API error {e.status_code}: {e.message}", file=sys.stderr)
        return 2
    except anthropic.APIConnectionError:
        print("network error reaching the API", file=sys.stderr)
        return 2
    return 0

if __name__ == "__main__":
    sys.exit(main())

/opt/explain/explain.py として保存し、対話的に使用するために鍵を読み込むラッパーを追加します。

sudo tee /usr/local/bin/explain >/dev/null <<'EOF'
#!/bin/sh
set -a; . /etc/claude-explain.env; set +a
exec /opt/explain/venv/bin/python /opt/explain/explain.py "$@"
EOF
sudo chmod 755 /usr/local/bin/explain

(ラッパーは sudo 経由で実行する必要があります。または、env ファイルのグループを管理者ユーザーが所属するものにする必要があります。ファイルの権限を 644 に緩めるのではなく、どちらかを意図的に選択してください。)

ストリーミングを使う理由。 client.messages.stream は生成全体が完了するまで待機せず、到着したトークンを出力します。また、長い出力での HTTP タイムアウトを回避できます。SDK はこの理由から、非ストリーミング呼び出しで非常に大きな max_tokens 値を実際に拒否します。後で組み立てたオブジェクトが必要な場合は、with ブロック内で stream.get_final_message() を呼び出します。

例外の順序がこの順である理由。 SDK は型付き例外を、より具体的なものから先に発生させます。RateLimitError は 429 で、待機時間を示す retry-after ヘッダーを含みます。APIStatusError はその他の non-2xx レスポンスを処理します(サーバー側の問題については e.status_code >= 500 を確認してください)。APIConnectionError は、応答をまったく受信できなかったことを示します。リトライループを実装する前に確認してください。SDK は 429 と 5xx エラーを自動的に再試行します。デフォルトでは指数バックオフを使用して 2 回再試行します(クライアントでは max_retries)。except が実行される時点では再試行を使い切っています。そのため CLI では、待機して繰り返し要求するのではなく、エラーを報告して終了するのが適切です。

コスト管理

APIには、設定した上限を超える月間上限が組み込まれていません。この点のミスは気付かないまま積み重なるため、独立したセクションで扱います。

max_tokens は、1回の呼び出しに対する支出上限です。 Opus 4.8では、出力トークンの単価は入力の5倍です。max_tokens は、モデルが生成できる出力トークン数のハード上限です。暴走したプロンプトでも、許可した量を超える出力コストは発生しません。作業に合わせて設定してください。ログ診断なら1,500で十分です。分類タスクなら100で足ります。stop_reason: "max_tokens" で応答が文の途中で止まる場合は、上限が低すぎます。無条件に大きな値へ変更せず、必要性を確認してから引き上げてください。

送信前にトークン数を数えてください。 入力にも料金がかかり、ログは大きくなりがちです。APIには無料で使えるカウント用エンドポイントがあります。ただし、メッセージ作成とは別のレート制限が適用されます。

count = client.messages.count_tokens(
    model="claude-opus-4-8",
    messages=[{"role": "user", "content": big_log_text}],
)
print(count.input_tokens)

これを使って、誤って2 GBのログをツールへ渡すことを防いでください。この用途に tiktoken は使わないでください。これは OpenAI のトークナイザーであり、一般的なテキストでは Claude のトークン数をおよそ15–20%少なく見積もり、コードではさらに大きく過小評価します。

利用目的に応じてモデルを選び、特定のモデルに固執しないでください。 2026年7月時点で、Opus 4.8 (claude-opus-4-8) は入力100万トークンあたり$5、出力100万トークンあたり$25です。Haiku 4.5 (claude-haiku-4-5) は$1/$5で、コンテキスト長は200Kです。Sonnet 5 (claude-sonnet-5) はその中間の$3/$15で、2026年8月31日までは導入価格として$2/$10が適用されます。具体的には、2,000トークンのログ抜粋に500トークンの回答を付けた場合、Opusでは約$0.0225、Haikuでは約$0.0045です。出力品質を評価している間はOpusから始め、その後、同じプロンプトをHaikuでも試してください。大量処理や単純な変換では、価格が5分の1でも違いが分からないことがよくあります。予算にこれらの数値を組み込む前に、料金ページで最新の数値を確認してください。

待機できる処理にはBatchesを使用してください。 Batches APIはリクエストを非同期で処理し、標準料金の50%で利用できます。ほとんどのバッチは1時間以内に完了します。夜間のダイジェスト、バックフィル、一括分類など、人が待機する必要のない処理はここで実行してください。

繰り返し送信するコンテキストにはプロンプトキャッシュを使用してください。 すべての呼び出しで同じ大きなシステムプロンプトやランブックを再送する場合は、キャッシュ可能として指定します。

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1000,
    system=[{
        "type": "text",
        "text": RUNBOOK_TEXT,  # the same 30K tokens on every call
        "cache_control": {"type": "ephemeral"},
    }],
    messages=[{"role": "user", "content": question}],
)
print(response.usage.cache_read_input_tokens)  # non-zero from the second call on

キャッシュへの書き込みは入力料金の約1.25倍、キャッシュからの読み取りは約0.1倍です。TTLは5分なので、この期間内の2回目の呼び出しですでに初回分を回収できます。注意点が2つあります。キャッシュするプレフィックスは、モデルごとの最小トークン数を超える必要があります。Opusでは数千トークン程度で、短いシステムプロンプトはキャッシュされないままになることがあります。また、同一の呼び出しで cache_read_input_tokens が0のままなら、リクエストごとにプレフィックスのどこかが変化しています。通常はタイムスタンプが原因です。

入力として計上される対象を確認してください。 システムプロンプト、ツール定義、マルチターンの会話で各ターンに再送する履歴全体は、すべて入力トークンとして課金されます。履歴を削除しないチャットループでは、コストが二次的に増加します。会話型の機能を構築する前に、料金の全体像を理解しておく価値があります: Claudeのトークン使用量と課金の実際の内訳

systemd で実行する

環境ファイルを適切に管理するメリットは、毎朝、前日のエラーを要約するタイマーを実行できることです。

# /etc/systemd/system/log-digest.service
[Unit]
Description=Daily error-log digest via the Claude API

[Service]
Type=oneshot
User=explain
Group=systemd-journal
EnvironmentFile=/etc/claude-explain.env
ExecStart=/bin/sh -c 'journalctl -p err --since yesterday | /opt/explain/venv/bin/python /opt/explain/explain.py >> /var/log/log-digest.txt'
# /etc/systemd/system/log-digest.timer
[Unit]
Description=Run the log digest every morning

[Timer]
OnCalendar=06:15
Persistent=true

[Install]
WantedBy=timers.target
sudo useradd -r -s /usr/sbin/nologin explain
sudo touch /var/log/log-digest.txt && sudo chown explain /var/log/log-digest.txt
sudo systemctl daemon-reload
sudo systemctl enable --now log-digest.timer
sudo systemctl start log-digest.service   # test it once, right now

EnvironmentFile= によって得られる利点に注目してください。systemd は、権限のない explain ユーザーに切り替える に、root が所有する mode-600 のファイルを読み取ります。そのため、プロセスは変数を取得できますが、ユーザーはキーファイルを読み取れません。systemd-journal グループによってログへのアクセスが許可されます。手動で systemctl start を実行して journalctl -u log-digest.service を読み取り、06:15 まで待って入力ミスに気付くことのないようにしてください。この方法が単純なシェルパイプラインでは対応できなくなっても、同じキーを環境ファイルに保存する方法を、そのまま同じマシン上の Claude を使用する n8n ワークフロー に適用できます。

失敗例と表示される文字列

動作するキーで401が返る場合。 例外には次のように表示されます。

anthropic.AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}, 'request_id': 'req_011CSHoEeqs5C35K2UUqR7Fy'}

シェルではキーが機能するのにサービスが401を返す場合、サービスがキーを受け取っていません。systemdは.bashrcを読み取らないため、EnvironmentFile=が正しいパスを指していることを確認してください。その他の原因には、環境ファイルに引用符を貼り付けたこと(ANTHROPIC_API_KEY="sk-ant-..."。systemdは引用符を値から除外しますが、引用符の付け方によっては、シェルラッパーの. fileが引用符を値に残します)、末尾の空白、先週Consoleで失効させたキーがあります。

モデル名の誤記による404。 最もよくある例は、現在のモデルIDに日付の接尾辞を付けることです。

anthropic.NotFoundError: Error code: 404 - {'type': 'error', 'error': {'type': 'not_found_error', 'message': 'model: claude-opus-4-8-20260115'}, 'request_id': 'req_011CSJqymAvNw4bT3qmDdMbA'}

現行世代のIDは、claude-opus-4-8claude-haiku-4-5claude-sonnet-5のように、記載どおり正確である必要があります。モデルのドキュメントからコピーしてください。記憶や古いチュートリアルに頼らないでください。

429 rate_limit_error。 エラー種別の文字列はrate_limit_errorです。レスポンスには、待機する秒数を示すretry-afterヘッダーが含まれます。例外が表示されるまでに、SDKはバックオフを使用してすでに2回再試行しています。そのため、429が継続する場合は、持続的なレートが実際に利用ティアの上限を超えています。処理をバッチ化するか分散してください。再試行ループの間隔を短くしないでください。

テキストではなくオブジェクトが出力される場合。 出力は[TextBlock(citations=None, text='...', type='text')]のようになります。ブロックを反復処理せず、block.type == "text"であるブロックから.textを読み取る代わりに、response.contentを出力しています。上のSDKの例では正しく処理しています。同じループをコピーしてください。

error: externally-managed-environment Ubuntu 24.04のシステムPythonに対してpip installを実行しました。venvを使用してください。管理対象のサーバーでは--break-system-packagesを絶対に使用しないでください。

回答が途中で切れる場合。 response.stop_reason == "max_tokens"は、モデルが出力上限に達したため、回答の途中で停止したことを意味します。想定された動作です。必要に応じて上限を引き上げてください。

最初のアプリが動作したら、ClaudeでAIエージェントを構築することで、同じAPI呼び出しをツールを使用するエージェントに発展させられます。

FAQ

Claude APIを試すにはいくらかかりますか?

このようなツールとしては、実際にはごくわずかです。2026年7月時点で、Opus 4.8は入力100万トークンあたり$5、出力100万トークンあたり$25です。そのため、入力が数千トークン、出力が数百トークン程度の一般的なログ診断なら、約2セントです。Haiku 4.5($1/$5)なら0.5セント未満です。毎日のダイジェストを1か月実行しても、コーヒー1杯未満の費用です。リスクは1回あたりの料金ではありません。上限のないループと上限のないmax_tokensです。そのため、このガイドでは両方を明示的に設定します。

Claude APIに無料プランはありますか?

2026年7月時点で、継続的な無料プランはありません。Anthropicの料金ドキュメントによると、新規ユーザーにはAPIを試すための少額の無料クレジットが、1回限りのトライアルとして提供されます。正確な金額は、登録時にConsoleに表示されます。その後はアカウントに入金します。最先端の品質ではなく、リクエストごとの限界費用をゼロにすることが目的なら、代替策はOllamaでオープンウェイトモデルをセルフホストすることです。トークンの代わりにRAMを使用します。

サーバー上でAPI keyを安全に保つにはどうすればよいですか?

コードに保存しないでください。gitにも保存しないでください。.bashrcからexportしないでください。履歴に残るshellにも入力しないでください。rootが所有するファイルに600の権限で保存し、プロセスごとに読み込んでください。対話的に使用する場合はwrapper scriptを使い、systemdではEnvironmentFile=を使用します。漏えいしたkeyを失効させる作業を最小限にするため、サーバーまたはプロジェクトごとに1つのkeyを割り当ててください。keyがpaste siteやgit commitに一度でも含まれた場合は、直ちにConsoleで失効させてください。commitを削除しても、漏えいしたkeyは無効になりません。

最初に使用するClaude modelはどれですか?

出力を基に構築できる品質かどうかを評価している間は、claude-opus-4-8から始めてください。アイデアを最高品質で評価する必要があり、趣味の規模で使用する場合は料金差が数セントだからです。promptが決まったら、実際の入力をclaude-haiku-4-5で再実行してください。要約、分類、ログのトリアージでは、5分の1の価格で同等の性能になることがよくあります。HaikuまたはSonnetへの移行は、デフォルトではなく測定結果に基づいて判断してください。