Paano gumamit ng Claude API sa Ubuntu VPS
Matutong mag-setup ng Python log-explainer sa Ubuntu 24.04. Kasama ang streaming, typed error handling, at tamang cost control gamit ang Claude API key.
Ang iyong bubuuin
Isang command-line tool sa isang bagong Ubuntu 24.04 VPS. I-pipe ang error message o bahagi ng log dito para makakuha ng diagnosis sa plain-English: journalctl -u nginx -n 50 | explain. Binubuo ito ng humigit-kumulang animnapung linya ng Python. Sinusubok nito ang lahat ng kailangan ng isang tunay na Claude API application — tamang pag-store ng key, virtualenv, response shapes ng SDK, streaming, typed exception chain, at systemd unit para tumakbo ito nang awtomatiko.
Pinili ko ang proyektong ito nang may intensyon. Karamihan sa mga "first API app" tutorial ay nagtuturo ng paggawa ng chatbot na hindi mo na muling bubuksan. Ang isang log explainer ay kapaki-pakinabang agad sa server mula sa unang araw. Pinipilit din nito ang user na matutunan ang dalawang bagay na madalas pagkakamalian ng mga beginner: ang tamang pagbasa sa response object, at ang pagkontrol sa gastos. Ang API ay nagbi-bill per token at walang limitasyon maliban sa mga itatakda mo, kaya ang cost control ay isang mahalagang design input dito. Ito ang parehong disiplina na kailangan kapag gagamit ka na ng Claude Code sa VPS na ito gamit ang tmux.
Kumuha ng API key mula sa Console
Ang API access ay pinamamahalaan sa Anthropic Console sa platform.claude.com — mag-sign up, pagkatapos ay gumawa ng key sa ilalim ng Settings → API Keys (ang link sa docs ay direktang papunta sa platform.claude.com/settings/keys). Isang beses lang ipapakita ang key, nagsisimula ito sa sk-ant-, at hindi na muling makukuha — i-copy agad ito o i-delete at mag-reissue.
Tungkol sa bayad: simula July 2026, wala nang ongoing free tier para sa API. Ayon sa pricing docs ng Anthropic, ang mga bagong user ay makakatanggap ng maliit na halaga ng free credits para sa testing; ang eksaktong halaga ay kung ano ang ipapakita sa iyo ng Console sa signup, at kapag naubos na ito, kailangan nang lagyan ng pondo ang account para maging successful ang mga request. Hiwalay ito sa claude.ai subscription — ang Pro o Max plan ay hindi kasama ang API credit, at ang API key ay hindi nagbibigay ng access sa chat app. Kung pinagpipilian mo ang subscription laban sa API, ang trade-off na iyon ay hiwalay na paksa: kung anong Claude plan ang kailangan mo talaga.
Gumawa ng key na naka-scope lamang sa isang project o server. Kapag na-leak ang isang key — at sa mahabang panahon ay siguradong mangyayari ito — kailangan mo itong i-revoke nang hindi nasisira ang iba mo pang mga system.
Huwag ilagay ang key sa .bashrc
Ang reflexive move ay export ANTHROPIC_API_KEY=sk-ant-... sa ~/.bashrc. Huwag itong gawin. May tatlong hiwalay na problema:
- Inherited ito ng bawat process. Ang environment variable na i-e-export sa iyong login shell ay kakalat sa lahat ng sisimulan mo — ang web app, ang crash reporter na naglalagay ng environment sa bug report, at ang
phpinfo()page na naiwang naka-enable. Ang exposure surface ng key ay magiging "lahat ng pinapatakbo ng user na ito." - Mapupunta ito sa
~/.bash_historykapag tinype mo. Kapag manual mong ni-run ang export, ang key ay mananatili sa isang plaintext file habambuhay, at magsi-sync sa bawat backup ng iyong home directory. - Wala ito kapag kailangan na ng systemd. Hindi binabasa ng mga services ang iyong
.bashrc, kaya mabibigo ang pattern na ito kapag ginamit mo na ang script bilang unit — karaniwang nagreresulta ito sa misteryosong 401 error tuwing alas-6 ng umaga.
Ang tamang pattern sa isang server ay ang paggamit ng dedicated environment file na may 600 permissions, na i-lo-load lamang ng process na nangangailangan nito:
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/nullGamitin ang tee mula sa isang printf sa halip na editor kung gusto mong maiwasan ang paglagay ng key sa editor swap files; sa anumang paraan, i-verify gamit ang ls -l /etc/claude-explain.env na binabasa nito ang -rw------- at owned ng root. Ang mga interactive shell ay makukuha ang key per-invocation sa pamamagitan ng isang wrapper (nasa ibaba), at ang systemd ay makukuha ito sa pamamagitan ng EnvironmentFile= — binabasa ng root ang file bago i-drop ang privileges, kaya hindi na kailangan ng service user ang read access dito. Ang key ay hindi kailanman lalabas sa code, sa git, sa ps output, o sa shell history.
I-install ang SDK sa isang venv
Ang Ubuntu 24.04 ay may Python 3.12 na may PEP 668 enforcement, kaya ang direktang pip install anthropic sa system interpreter ay magreresulta sa error: externally-managed-environment. Ang error na ito ay normal na behavior ng OS — gumamit ng virtualenv:
sudo apt update && sudo apt install -y python3-venv
sudo python3 -m venv /opt/explain/venv
sudo /opt/explain/venv/bin/pip install anthropicHindi kailangan ang activation sa isang server: ang direktang pagtawag sa /opt/explain/venv/bin/python ay laging gagamit ng mga package mula sa venv.
Unang call, at ang tamang pagbasa sa response
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)Dalawang bagay sa labindalawang linyang iyon ang bumubuo sa mental model ng API. Una, ang paggamit ng anthropic.Anthropic() nang walang arguments ay nagbabasa ng key mula sa environment — huwag itong ipasa bilang string literal. Pangalawa, ang response.content ay isang list of content blocks, hindi isang string. Kapag i-print mo ito nang direkta, makukuha mo ang karaniwang output para sa mga nagsisimula pa lang:
[TextBlock(citations=None, text='A systemd unit file is...', type='text')]Hindi ito bug; ito ang repr ng object. Ang mga response ay maaaring maglaman ng iba't ibang block types (text, tool calls, thinking), kaya dapat mong i-iterate at i-check ang block.type == "text" bago i-access ang .text. Siguraduhing naka-implement na ang loop na ito sa simula pa lang para maiwasan ang kalituhan sa "it prints garbage".
Gamitin ang eksaktong model ID na claude-opus-4-8. Ang mga current-generation IDs ay walang petsa — huwag sundin ang nakasanayan (o ang mga lumang blog post) na nagpapakuha sa iyo na magdagdag ng date suffix; magreresulta ito sa 404, na tatalakayin sa ibaba.
Ang mismong tool: paliwanag
Narito ang buong program — stdin ang input, streamed ang diagnosis output, at handled ang mga error:
#!/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())I-save ito bilang /opt/explain/explain.py, pagkatapos ay magdagdag ng wrapper na naglo-load ng key para sa interactive use:
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(Kailangang patakbuhin ang wrapper gamit ang sudo o dapat kabilang ang admin user mo sa group ng env file — pumili ng isa sa halip na gawing 644 ang file permissions.)
Bakit streaming. Nagpi-print ang client.messages.stream ng mga token habang dumarating ang mga ito sa halip na maghintay sa buong generation. Iniiwasan din nito ang HTTP timeouts sa mahahabang output — tinatanggihan ng SDK ang napakalalaking max_tokens values sa non-streaming calls dahil sa rason na ito. Kung kailangan mo ang assembled object pagkatapos, tawagin ang stream.get_final_message() sa loob ng with block.
Bakit ganyan ang pagkakasunod-sunod ng exception. Naglalabas ang SDK ng mga typed exception, mula sa pinaka-specific: ang RateLimitError ay isang 429 at may dalang retry-after header na nagsasabi kung gaano katagal dapat maghintay; sakop ng APIStatusError ang iba pang non-2xx responses (tingnan ang e.status_code >= 500 para sa server-side trouble); ang APIConnectionError ay nangangahulugang walang natanggap na response ang request. At bago ka gumawa ng retry loop: ang SDK ay awtomatiko nang nagre-retry ng 429s at 5xx errors, nang dalawang beses by default gamit ang exponential backoff (max_retries sa client). Pagdating sa oras na tumakbo ang except mo, tapos na ang mga retry — kaya ang tamang gawin sa isang CLI ay i-report at mag-exit, hindi ang mag-sleep at mag-hammer.
Cost control
Kailangan ito ng sariling section dahil walang built-in monthly cap ang API maliban sa iyong configuration, at ang bawat pagkakamali dito ay maaaring magresulta sa malaking gastos.
Ang max_tokens ang iyong per-call spend ceiling. Ang output tokens ang mas mahal — sa Opus 4.8, limang beses ang presyo nito kumpara sa input — at ang max_tokens ay ang hard cap sa dami ng tokens na maaaring i-produce ng model. Hindi maaaring lumampas ang gastos ng isang runaway prompt sa limitasyon ng output na iyong itinakda. I-set ang size ayon sa trabaho: sapat na ang 1,500 para sa log diagnosis; ang classification task ay nangangailangan ng 100. Kung huminto ang responses sa gitna ng pangungusap dahil sa stop_reason: "max_tokens", masyadong maliit ang iyong setting — itaas ito nang may pagsusuri sa halip na i-default sa napakalaking value.
Magbilang bago mag-send. May gastos din ang input, at ang mga logs ay malalaki. May counting endpoint ang API na libreng gamitin (mayroon itong sariling rate limits na hiwalay sa message creation):
count = client.messages.count_tokens(
model="claude-opus-4-8",
messages=[{"role": "user", "content": big_log_text}],
)
print(count.input_tokens)Gamitin ito para maiwasan ang aksidenteng pagpasa ng 2 GB na log sa tool. Huwag gamitin ang tiktoken para dito — tokenizer ito ng OpenAI, at mas mababa ang bilang nito sa Claude tokens nang humigit-kumulang 15–20% sa tipikal na text, at mas malaki pa sa code.
Piliin ang model base sa task, hindi sa loyalty. As of July 2026, ang Opus 4.8 (claude-opus-4-8) ay $5 bawat isang milyon na input tokens at $25 bawat isang milyon na output; ang Haiku 4.5 (claude-haiku-4-5) ay $1/$5 na may 200K context; ang Sonnet 5 (claude-sonnet-5) ay nasa pagitan sa $3/$15, na may introductory pricing na $2/$10 hanggang August 31, 2026. Sa konkretong halimbawa: ang isang 2,000-token log excerpt na may 500-token na sagot ay nagkakahalaga ng humigit-kumulang $0.0225 sa Opus at $0.0045 sa Haiku. Magsimula sa Opus habang sinusuri ang kalidad ng output, pagkatapos ay subukan ang parehong prompts sa Haiku — para sa high-volume at simpleng transformations, madalas ay hindi sila nagkakaiba sa fifth ng presyo. I-verify ang kasalukuyang presyo sa pricing page bago i-hard-code ang mga ito sa iyong budget.
Gamitin ang Batches para sa mga bagay na pwedeng maghintay. Ang Batches API ay nagpoproseso ng mga request nang asynchronous sa 50% ng standard prices, at karamihan sa mga batch ay natatapos sa loob ng isang oras. Nightly digests, backfills, bulk classification — anumang walang taong naghihintay ay dapat ilagay doon.
Prompt caching para sa paulit-ulit na context. Kung ang bawat call ay nagpapadala muli ng parehong malaking system prompt o runbook, i-marka ito bilang cacheable:
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 onAng cache writes ay nagkakahalaga ng humigit-kumulang 1.25x ng input price, ang cache reads ay humigit-kumulang 0.1x, sa isang 5-minute TTL — kaya ang ikalawang call sa loob ng window na ito ay bayad na sa unang call. May dalawang dapat bantayan. Ang cached prefix ay dapat lumampas sa per-model minimum — ilang libong tokens sa Opus — kaya ang isang maikling system prompt ay maaaring hindi mag-cache nang tahimik. At kung ang cache_read_input_tokens ay nananatiling zero sa mga magkaparehong call, may nagbabago sa iyong prefix sa bawat request (karaniwang sanhi ang timestamp).
Tandaan kung ano ang itinuturing na input. Ang mga system prompts, tool definitions, at — sa multi-turn conversations — ang buong history na muling ipinapadala mo sa bawat turn ay lahat itinuturing na input tokens. Ang isang chat loop na hindi kailanman nagtatanggal ng history ay mabilis na tataas ang gastos (quadratically). Mahalagang maunawaan ang buong accounting bago bumuo ng anumang conversational system: kung paano talaga nag-a-add up ang Claude token usage at billing.
Patakbuhin ito sa ilalim ng systemd
Ang benepisyo ng paggamit ng environment-file: isang timer na nagbubuod ng mga error kahapon tuwing umaga.
# /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 nowPansinin ang pakinabang ng EnvironmentFile=: binabasa ng systemd ang file na root-owned at may mode-600 bago mag-switch sa unprivileged na explain user. Dahil dito, makuha ng process ang variable habang hindi mababasa ng user ang key file. Ang systemd-journal group ang nagbibigay ng access sa log. I-test gamit ang manual na systemctl start at basahin ang journalctl -u log-digest.service — huwag nang maghintay hanggang 06:15 para malaman kung may typo. Kapag ang pattern na ito ay lumampas na sa shell pipeline, ang parehong key-in-env-file approach ay magagamit din sa Claude-powered n8n workflows sa parehong machine.
Failure modes, with the strings you will see
401 sa working key. Ang exception ay:
anthropic.AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}, 'request_id': 'req_011CSHoEeqs5C35K2UUqR7Fy'}Kung gumagana ang key sa shell mo pero 401 ang service, hindi ito natanggap ng service — tandaan na hindi binabasa ng systemd ang .bashrc; siguraduhin na ang EnvironmentFile= ay nakaturo sa tamang path. Iba pang sanhi: may quotes na na-paste sa env file (ANTHROPIC_API_KEY="sk-ant-..." — tinatanggal ng systemd ang quotes, pero ang . file ng iyong shell wrapper ay pinapanatili ang mga ito sa value kung mali ang pagkakagawa ng quotes), may trailing whitespace, o ang key ay na-revoke na sa Console noong nakaraang linggo.
404 dahil sa typo sa model. Ang pinakakaraniwang sanhi nito ay ang paglalagay ng date-suffix sa isang current model ID:
anthropic.NotFoundError: Error code: 404 - {'type': 'error', 'error': {'type': 'not_found_error', 'message': 'model: claude-opus-4-8-20260115'}, 'request_id': 'req_011CSJqymAvNw4bT3qmDdMbA'}Ang mga current-generation IDs ay eksakto sa kung paano sila isinulat — claude-opus-4-8, claude-haiku-4-5, claude-sonnet-5. I-copy ang mga ito mula sa documentation ng models; huwag manghula o kumuha sa lumang tutorial.
429 rate_limit_error. Ang error type string ay rate_limit_error at ang response ay may retry-after header na naglalaman ng bilang ng segundo na dapat maghintay. Ang SDK ay dalawang beses nang nag-retry nang may backoff bago lumabas ang exception, kaya ang tuloy-tuloy na 429 ay nangangahulugang lumampas na ang iyong sustained rate sa iyong tier — i-batch ang trabaho o i-spread ang execution, huwag paigtingin ang retry loop.
Object ang na-print, hindi ang text. Ang output ay mukhang [TextBlock(citations=None, text='...', type='text')]. Ang na-print mo ay response.content sa halip na i-iterate ang mga blocks at basahin ang .text mula sa mga blocks kung saan block.type == "text". Tama ang pagkakagawa ng lahat ng SDK example sa itaas; i-copy ang loop.
error: externally-managed-environment. Nag-run ka ng pip install gamit ang system Python ng Ubuntu 24.04. Gamitin ang venv — huwag gumamit ng --break-system-packages sa isang server na mahalaga sa iyo.
Truncated answers. Ang response.stop_reason == "max_tokens" ay nangangahulugang naabot ng model ang iyong output cap habang nag-iisip. Normal ito sa disenyo; taasan ang cap nang sadyang.
Kapag gumagana na ang iyong unang app, ang building an AI agent with Claude ay gagawing agent ang mga API call na iyon gamit ang mga tools.
FAQ
Magkano ang gastos sa pagsubok ng Claude API?
Napakababa lang para sa ganitong tool. As of July 2026, ang Opus 4.8 ay nagkakahalaga ng $5 per million input tokens at $25 per million output. Ang isang tipikal na log diagnosis — may ilang libong tokens sa input at ilang daan sa output — ay nasa dalawang sentimo lang. Sa Haiku 4.5 ($1/$5), mas mababa pa ito sa kalahating sentimo. Ang isang buwan ng daily digests ay mas mura pa sa kape. Ang panganib ay hindi ang presyo bawat call; ito ay ang unbounded loops at unbounded max_tokens, kaya kailangang i-set nang malinaw ang mga ito sa guide na ito.
Mayroon bang free tier para sa Claude API?
Walang ongoing free tier as of July 2026. Ayon sa pricing documentation ng Anthropic, ang mga bagong user ay makakatanggap ng maliit na halaga ng free credits para i-test ang API — isang one-time trial, kung saan ang eksaktong halaga ay makikita sa Console sa signup — pagkatapos ay kailangan nang i-fund ang account. Kung ang layunin mo ay zero marginal cost bawat request sa halip na frontier quality, ang alternatibo ay ang i-self-host ang isang open-weight model gamit ang Ollama at magbayad gamit ang RAM sa halip na tokens.
Paano pananatilihing ligtas ang aking API key sa isang server?
Huwag ilalagay sa code, huwag sa git, huwag i-export mula sa .bashrc, at huwag i-type sa isang shell kung saan itatala ito sa history. Ilagay ito sa isang root-owned file na may 600 permissions. I-load ito per-process — gumamit ng wrapper script para sa interactive use, at EnvironmentFile= para sa systemd. Limitahan ang isang key bawat server o project para ang pag-revoke ng leaked na key ay parang surgery lang at hindi amputation. Kung ang key ay napunta sa isang paste site o git commit, i-revoke agad ito sa Console; ang pag-delete sa commit ay hindi nakakapag-alis ng leak.
Anong Claude model ang dapat kong simulan?
Simulan sa claude-opus-4-8 habang sinusuri kung sapat na ang kalidad ng mga output para pagbatayan — kailangan mong masuri ang ideya sa full quality, at sa hobby volume ay sentimo lang ang difference sa gastos. Kapag stable na ang prompt, i-rerun ang iyong mga real inputs sa claude-haiku-4-5; para sa summarization, classification, at log triage, madalas ay kasinghusay nito ngunit nasa fifth lang ng presyo. Lumipat sa Haiku o Sonnet base sa measurement, hindi dahil ito ang default.