Як запустити Claude API на Ubuntu VPS
Покроковий гайд з розробки Python-скрипта для аналізу логів на Ubuntu 24.04. Налаштування Claude API, стрімінг, обробка помилок та створення systemd unit.
Що ви створюєте
Консольний інструмент на новому Ubuntu 24.04 VPS. Ви передаєте йому повідомлення про помилку або фрагмент логів, а отримуєте діагноз простою англійською мовою: journalctl -u nginx -n 50 | explain. Проєкт складається приблизно з 60 рядків коду на Python. Він охоплює всі необхідні компоненти для реального застосунку з Claude API: правильне зберігання ключа, використання virtualenv, структури відповідей SDK, стрімінг, типи ланцюжка винятків (exception chain) та unit-файл systemd для автономної роботи.
Я обрав цей проєкт навмисно. Більшість туторіалів про "перший застосунок з API" пропонують створити чат-бота, який ви ніколи більше не відкриєте. Інструмент для аналізу логів приносить користь на сервері з першого дня. Він змушує розв'язувати дві реальні проблеми початківців: правильне читання об'єкта відповіді та контроль витрат. API тарифікується за токени, і єдиним обмеженням є встановлені вами ліміти. Тому контроль витрат є частиною проєкту, а не другорядним завданням — це та сама дисципліна, яка необхідна, коли ви перейдете до запуску Claude Code на цьому ж VPS у tmux.
Отримання API key через Console
Доступ до API керується через Anthropic Console на сайті platform.claude.com. Спершу зареєструйтеся, потім створіть ключ у розділі Settings → API Keys (посилання в документації веде безпосередньо на platform.claude.com/settings/keys). Ключ відображається лише один раз, починається з sk-ant-, і його неможливо отримати повторно. Скопіюйте його одразу або видаліть і створіть новий.
Щодо оплати: станом на липень 2026 року безкоштовного рівня використання для API не існує. Згідно з документацією Anthropic щодо ціноутворення, нові користувачі отримують невелику суму безкоштовних кредитів для тестування. Точна сума залежить від того, що вказано в Console під час реєстрації. Після вичерпання кредитів необхідно поповнити баланс акаунта, щоб запити виконувалися успішно. Це окрема послуга від підписки claude.ai: плани Pro або Max не включають кредити для API, а наявність API key не надає доступ до чат-додатка. Якщо ви обираєте між підпискою та API, розгляньте це окремо: який план Claude вам насправді потрібен.
Створюйте ключ з обмеженим доступом лише для одного проєкту або сервера. Якщо ключ буде скомпрометовано — а на довгій дистанції це неминуче — ви зможете відкликати його, не порушуючи роботу інших ваших систем.
Не зберігайте ключ у .bashrc
Використання рефлексивного переміщення export ANTHROPIC_API_KEY=sk-ant-... у ~/.bashrc є помилковим. Це створює три окремі проблеми:
- Кожен процес успадковує його. Змінна середовища, експортована у вашому shell при вході, передається всьому, що ви запускаєте: веб-додаткам, звітам про помилки, які додають змінні середовища до звітів, або сторінці
phpinfo(), яку хтось залишив увімкненою. Поверхня атаки ключа стає рівною всьому, що запускає цей користувач. - Введення ключа потрапляє в
~/.bash_history. Якщо ви один раз виконаєте команду export вручну, ваш ключ назавжди залишиться у текстовому файлі та потрапить у всі резервні копії вашої домашньої директорії. - Ключ недоступний для systemd. Сервіси не читають ваш
.bashrc, тому цей підхід не працює, коли ви перетворюєте скрипт на unit — зазвичай це призводить до помилки 401 о 6 годині ранку.
Правильний підхід на сервері — це окремий файл середовища з правами 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Використовуйте tee через printf замість редактора, якщо хочете уникнути появи ключа у swap-файлах редактора; у будь-якому разі перевірте за допомогою ls -l /etc/claude-explain.env, що файл читається як -rw------- і належить root. Інтерактивні shell отримують ключ під час кожного запуску через обгортку (див. нижче), а systemd отримує його через EnvironmentFile= — root читає файл перед зниженням привілеїв, тому користувачу сервісу не потрібен доступ на читання. Ключ ніколи не з'являється в коді, у git, у виводі ps або в історії shell.
Встановлення SDK у venv
Ubuntu 24.04 постачається з Python 3.12 та примусовим застосуванням PEP 668. Через це пряме встановлення pip install anthropic у системний інтерпретатор призводить до помилки error: externally-managed-environment. Ця помилка є очікуваною поведінкою ОС — використовуйте 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)Два моменти в цих дванадцяти рядках визначають основну логіку API. По-перше, anthropic.Anthropic() без аргументів зчитує ключ із середовища — ніколи не передавайте його як рядкову константу. По-друге, response.content — це список блоків контенту, а не рядок. Якщо вивести його напряму, ви отримаєте типовий результат для новачків:
[TextBlock(citations=None, text='A systemd unit file is...', type='text')]Це не помилка, а представлення об'єкта (repr). Відповіді можуть містити кілька типів блоків (text, tool calls, thinking), тому необхідно ітерувати список та перевіряти block.type == "text" перед зверненням до .text. Використовуйте цей цикл відразу, щоб уникнути помилок на кшталт «виводиться сміття».
Використовуйте точний ID моделі claude-opus-4-8. ID поточного покоління не містять дати — не додавайте суфікс із датою за звичкою (або за старими статтями); це призведе до помилки 404, про яку йдеться нижче.
Повний опис інструменту
Ось повна програма — вхідні дані через stdin, потоковий вивід діагностики, обробка помилок:
#!/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, або файл середовища має належати групі, до якої входить ваш користувач-адміністратор. Оберіть один із цих варіантів замість встановлення прав доступу 644.)
Переваги потокового виводу. client.messages.stream виводить токени в міру їх отримання, а не чекає завершення всієї генерації. Це дозволяє уникнути тайм-аутів HTTP при великих обсягах виводу. SDK відхиляє занадто великі значення max_tokens при не-потокових викликах саме з цієї причини. Якщо вам потрібен готовий об'єкт, викликайте stream.get_final_message() всередині блоку with.
Порядок обробки винятків. SDK генерує типизовані винятки, починаючи з найбільш специфічних: RateLimitError відповідає помилці 429 і містить заголовок retry-after із вказівкою часу очікування; APIStatusError охоплює інші відповіді, відмінні від 2xx (перевірте e.status_code >= 500 на наявність проблем на стороні сервера); APIConnectionError означає, що запит взагалі не отримав відповіді. Перед створенням циклу повторних спроб врахуйте: SDK вже самостійно повторює запити для помилок 429 та 5xx, за замовчуванням двічі з експоненціальною затримкою (max_retries на стороні клієнта). До моменту виконання вашого except всі повторні спроби вже будуть вичерпані. Тому для CLI-інструментів правильним рішенням є виведення помилки та завершення роботи, а не очікування та повторні запити.
Контроль витрат
Цей розділ виділено окремо, оскільки API не має вбудованого щомісячного ліміту, окрім налаштованих вами параметрів, а будь-яка помилка тут призводить до прихованого зростання витрат.
max_tokens — це ваш ліміт витрат на один виклик. Вихідні токени (output tokens) коштують дорожче — на Opus 4.8 ціна виходу в п'ять разів вища за ціну входу. 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 року: Opus 4.8 (claude-opus-4-8) коштує $5 за мільйон вхідних токенів і $25 за мільйон вихідних; Haiku 4.5 (claude-haiku-4-5) коштує $1/$5 з контекстом 200K; Sonnet 5 (claude-sonnet-5) коштує $3/$15 (діє акційна ціна $2/$10 до 31 серпня 2026 року). Приклад: фрагмент логу на 2,000 токенів з відповіддю на 500 токенів коштує приблизно $0.0225 на Opus та $0.0045 на Haiku. Починайте з Opus, поки оцінюєте якість відповідей, потім спробуйте ті самі промпти на Haiku — для обробки великих обсягів простих перетворень результат часто не відрізняється, а ціна в п'ять разів нижча. Перевіряйте актуальні дані на сторінці з цінами перед тим, як жорстко прописувати ці цифри в бюджеті.
Використовуйте Batches для завдань, які не потребують миттєвої відповіді. Batches API обробляє запити асинхронно за 50% від стандартних цін, і більшість пакетів обробляються протягом години. Щоденні звіти, заповнення пропущених даних, масова класифікація — усе, що не потребує очікування людини, слід відправляти туди.
Кешування промптів для повторюваного контексту. Якщо кожен виклик повторно надсилає один і той самий великий системний промпт або інструкцію, позначте їх як кешовані:
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.25x від ціни входу, читання з кешу — близько 0.1x при TTL 5 хвилин. Отже, другий виклик протягом цього вікна вже коштує стільки ж, скільки перший. Є два нюанси. Кешований префікс має відповідати мінімальному порогу для конкретної моделі — кілька тисяч токенів для Opus — інакше короткий системний промпт не буде кешуватися. І якщо cache_read_input_tokens залишається нульовим при однакових викликах, це означає, що у вашому префіксі щоразу змінюється якась частина (зазвичай це мітка часу).
Пам'ятайте, що саме вважається вхідними даними. Системні промпти, визначення інструментів та — у багатоходових діалогах — вся історія, яку ви перенадсилаєте на кожному кроці, розраховуються як вхідні токени. Чат-цикл без обрізання історії призводить до квадратичного зростання витрат. Потрібно розуміти повний механізм обліку, перш ніж створювати будь-які діалогові системи: як насправді складаються витрати на токени Claude.
Запуск через systemd
Результат використання environment-file: таймер, який щоранку створює звіт про помилки за вчорашній день.
# /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.targetsudo 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 зчитує файл з правами root та mode-600 перед переходом до непривілейованого користувача explain. Таким чином процес отримує змінну, тоді як користувач не має доступу до файлу з ключем. Група systemd-journal надає доступ до логів. Перевірте налаштування за допомогою ручного systemctl start та перегляньте journalctl -u log-digest.service — не чекайте 06:15, щоб виявити помилку в синтаксисі. Якщо цей патерн стане складнішим за shell pipeline, такий самий підхід із використанням env-файлів можна застосувати у n8n workflows на базі Claude на цьому ж сервері.
Режими помилок та відповідні рядки
401 при робочому ключі. Помилка виглядає так:
anthropic.AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}, 'request_id': 'req_011CSHoEeqs5C35K2UUqR7Fy'}Якщо ключ працює в shell, але сервіс повертає 401, сервіс не отримав ключ. Пам'ятайте, що systemd не зчитує .bashrc; перевірте, чи EnvironmentFile= вказує на правильний шлях. Інші причини: лапки у env-файлі (ANTHROPIC_API_KEY="sk-ant-..." — systemd видаляє лапки, але . file вашого shell-wrapper зберігає їх у значенні, якщо лапки були поставлені некоректно), пробіли в кінці рядка або ключ, який ви анулювали в 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-8, claude-haiku-4-5, claude-sonnet-5. Копіюйте їх з документації моделей, а не з пам'яті або старих туторіалів.
429 rate_limit_error. Рядок типу помилки — rate_limit_error, а у відповіді міститься заголовок retry-after із кількістю секунд очікування. SDK вже зробив дві спроби повторного запиту з затримкою (backoff) до того, як ви побачили виняток. Постійні 429 означають, що ваша поточна швидкість запитів перевищує ліміт вашого тарифу — використовуйте пакетну обробку (batching) або розподіляйте навантаження, не збільшуйте частоту повторних спроб.
Виводиться об'єкт, а не текст. Вивід виглядає як [TextBlock(citations=None, text='...', type='text')]. Ви вивели response.content замість того, щоб ітерувати блоки та зчитувати .text з тих блоків, де є block.type == "text". Усі наведені вище приклади SDK роблять це правильно; скопіюйте цикл.
error: externally-managed-environment. Ви запустили pip install проти системного Python в Ubuntu 24.04. Використовуйте venv — ніколи не використовуйте --break-system-packages на сервері, де це критично.
Обрізані відповіді. response.stop_reason == "max_tokens" означає, що модель досягла ліміту виводу (output cap) під час генерації. Це передбачена поведінка; збільште ліміт.
Коли ваш перший додаток запрацює, створення AI-агента з Claude перетворить ці ж виклики API на агента, що використовує інструменти (tools).
FAQ
Яка вартість використання Claude API для тестування?
Для такого інструменту вона дуже низька. Станом на липня 2026 року, Opus 4.8 коштує $5 за мільйон вхідних токенів і $25 за мільйон вихідних. Типова діагностика логів (кілька тисяч вхідних токенів і кілька сотень вихідних) коштуватиме близько двох центів. Використання Haiku 4.5 ($1/$5) обійдеться менш ніж у пів цента. Місяць щоденних звітів коштує менше, ніж кава. Ризик становить не ціна за один виклик, а неконтрольовані цикли та неконтрольований max_tokens, тому в цьому посібнику ці параметри налаштовуються явно.
Чи є безкоштовний рівень для Claude API?
Станом на липень 2026 року постійного безкоштовного рівня немає. Згідно з документацією Anthropic, нові користувачі отримують невелику кількість безкоштовних кредитів для тестування API — це одноразова пробна версія, точна суму якої вказано в Console під час реєстрації. Після цього необхідно поповнювати баланс. Якщо ваша мета — нульова маржинальна вартість за запит, а не максимальна якість, альтернативою є self-host an open-weight model with Ollama, де оплатою є використання RAM замість токенів.
Як забезпечити безпеку API key на сервері?
Ніколи не зберігайте ключ у коді, у git, не експортуйте його через .bashrc і не вводьте в shell, де він залишиться в історії. Зберігайте ключ у файлі під керуванням root з правами 600. Завантажуйте його для кожного окремого процесу: використовуйте скрипт-обгортку для інтерактивної роботи та EnvironmentFile= для systemd. Використовуйте окремий ключ для кожного сервера або проєкту, щоб анулювання викраденого ключа було легким процесом, а не повною заміною системи. Якщо ключ потрапив на paste-сайт або у git commit, негайно анулюйте його в Console; видалення коміту не приховує факт витоку.
З якої моделі Claude варто почати?
Починайте з claude-opus-4-8, поки оцінюєте, чи достатньо якісними є результати для розробки. Вам потрібно перевірити ідею на максимальній якості, а при невеликих обсягах різниця в ціні становить лічені центи. Коли промпт буде готовий, запустіть реальні дані на claude-haiku-4-5; для сумаризації, класифікації та сортування логів ця модель часто працює так само добре, але за п'яту частину ціни. Переходьте на Haiku або Sonnet на основі результатів вимірювань, а не за замовчуванням.