SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-13

Claude для системних адміністраторів: 6 завдань

Claude допоможе з журналами failed unit, systemd, nginx і Compose. Дізнайтеся, що перевіряти перед змінами та які 4 категорії даних не можна вставляти.

Claude для системних адміністраторів: спочатку порада, потім виконання

Claude для системних адміністраторів найкраще працює як засіб перевірки. Вставте фрагмент журналу, файл конфігурації, невідому вам команду або текст помилки й отримайте пояснення, яке можна перевірити до внесення будь-яких змін на сервері. Неправильна відповідь не завдасть шкоди, доки ви її не виконаєте, тому основа безпеки полягає в тому, щоб модель лише надавала поради, а не виконувала дії.

На орендованому Linux VPS (virtual private server) щотижня повторюються шість завдань. Для кожного з них нижче наведено робочий шаблон запиту, команду для перевірки відповіді та типову помилку, на яку слід очікувати. Жодне з цих завдань не потребує надання моделі доступу до вашого сервера.

На production-сервері важливий саме порядок дій: прочитайте пояснення, самостійно виконайте перевірку, а потім приймайте рішення. На scratch VM можна дозволити автономні дії. На сервері, який обслуговує клієнтів, перевагу слід надавати перевірці, оскільки модель не бачить стан системи, про який робить припущення.

Що ніколи не можна вставляти

Усе з prompt залишає ваш сервер. Чотири категорії мають залишатися на сервері:

  • Приватні ключі: ~/.ssh/id_ed25519, /etc/ssh/ssh_host_*_key і будь-який ключ TLS (transport layer security) у /etc/letsencrypt/live/.
  • Файли з обліковими даними: .env, ~/.aws/credentials, /root/.docker/config.json і паролі баз даних у будь-якому файлі або рядку журналу.
  • Дані облікових записів: /etc/shadow і /etc/gshadow. Для відповіді на запитання системного адміністратора хеш пароля не потрібен.
  • Будь-які дані ваших користувачів: адреси електронної пошти, рядки замовлень, журнали запитів із cookie сеансів або PII (personally identifiable information).

Відкриті ключі можна вставляти. Приватні ключі — ні. На перший погляд ці два файли схожі, тому перед копіюванням прочитайте перший рядок: файл, у першому рядку якого є BEGIN OPENSSH PRIVATE KEY, ніколи не вставляйте в prompt. Як не переплутати матеріали SSH-ключів варто опрацювати окремо, це займе десять хвилин.

Перед вставленням замаскуйте конфіденційні дані. Не покладайтеся на здатність помітити один токен у 200 рядках:

sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'

У Docker є окрема пастка. docker compose config підставляє значення .env у вивід, який друкує, тому цей вивід містить секрет, навіть якщо файл на диску ним не був. Використовуйте docker compose config -q: ця команда перевіряє конфігурацію і нічого не виводить. Ширші правила щодо даних, які агент може бачити, зокрема середовища виконання, описано в матеріалі Як не допускати потрапляння секретів до AI-агентів.

Завдання 1: чому цей сервіс завершився з помилкою?

Почніть із двох команд, у виведенні яких є відповідь:

systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-iso

Вставте обидві команди разом із контекстом, якого модель не може вгадати: дистрибутивом і його версією, останніми змінами, інформацією про те, чи працювало це раніше, і часом, коли виникла проблема. Спочатку попросіть пояснити механізм.

Ubuntu 24.04. myapp.service працював нормально, доки годину тому я не відредагував unit. Ось systemctl status і останні 100 рядків журналу. Який рядок є першою справжньою помилкою і що він означає? Поки що без виправлення.

Фраза «Поки що без виправлення» у цьому запиті має важливе значення. Журнали приховують першу помилку повідомленнями про спричинені нею повторні спроби, тому модель, яку попросили запропонувати виправлення, пояснить останній побачений рядок. Релевантний рядок зазвичай розташований приблизно на двадцять рядків вище за цей шум.

Результатом може бути пояснення на кшталт Main PID: 1841 (code=exited, status=203/EXEC). Код завершення 203/EXEC означає, що ядро не змогло виконати файл, указаний у ExecStart: шлях не існує або файл існує, але не має права на виконання. Рядок #! з інтерпретатором, який не встановлено, спричиняє такий самий код. Усе це можна перевірити за допомогою ls -l і head -1.

Типова помилка: вигадана причина. Якщо вставити замало даних, модель заповнить прогалину загальним припущенням, наприклад «порт уже використовується». Потрібно поставити зустрічне запитання: «Який рядок у наданих мною даних це підтверджує?» Причина, на яку ніхто не може вказати в тексті, є лише припущенням.

Завдання 2: підготуйте unit systemd або запис cron

Надайте всі дані, потрібні для unit-файла: точну команду, користувача, від імені якого вона запускається, робочий каталог, потребу очікувати на мережу та дію в разі завершення з ненульовим кодом. Перш ніж щось вмикати, перевірте отриманий результат.

sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pager

systemd-analyze verify аналізує файл так само, як systemd, тому виявляє помилки, які легко пропустити під час ручної перевірки. Помилка в назві директиви виводить /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. Відсутній бінарний файл виводить Command /usr/local/bin/myapp is not executable: No such file or directory. Під час daemon-reload обидві помилки залишаються непомітними. Тому unit може успішно завантажитися, але завершитися з помилкою одразу після запуску.

Є дві типові помилки під час підготовки. Перша — After=network.target. Це означає лише, що мережевий стек налаштований, але не гарантує, що IP-адресу вже призначено. Сервіс, який прив’язується до конкретної IP-адреси, під час завантаження завершується з помилкою bind: Cannot assign requested address. Виправлення — Wants=network-online.target разом із After=network-online.target. Друга — Type=simple для програми, яка переходить у фоновий режим: systemd вважає перший процес сервісом, батьківський процес одразу завершується, і unit позначається як неактивний, тоді як фактичний процес продовжує працювати без керування.

Для розкладу виконайте перевірку, а не просто читайте його:

systemd-analyze calendar 'Mon *-*-* 04:00:00'

Команда виводить нормалізовану форму та час наступного запуску виразу. Це усуває неоднозначність щодо його значення. Якщо ви обираєте між timer і crontab, у матеріалі про systemd services і timers на VPS описано компроміси між цими варіантами.

У cron є особливість, про яку жодна модель не попередить без окремого запиту. Cron запускає завдання з мінімальним оточенням, тому PATH приблизно дорівнює /usr/bin:/bin, а профіль shell ніколи не завантажується. Завдання, яке працює після вставлення команди в термінал, завершується з помилкою /bin/sh: 1: docker: not found під час запуску через cron, оскільки цей бінарний файл розташований у /usr/local/bin. У crontab використовуйте абсолютні шляхи.

Завдання 3: перевірте файл nginx або Compose перед запуском у production

Це завдання дає найбільшу користь. Вставте файл, опишіть, що він має робити, і попросіть пояснити його фактичну поведінку, рядок за рядком.

Цей vhost має обслуговувати example.com через HTTPS і проксувати /api до локального сервісу на порту 8080. Прочитай його та назви все, що не відповідає цьому опису.

Потім запустіть інструмент, який перевіряє синтаксис:

sudo nginx -t
docker compose config -q

nginx -t виводить nginx: configuration file /etc/nginx/nginx.conf test is successful або вказує файл і рядок, як у nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. docker compose config -q нічого не виводить, якщо файл має коректний синтаксис, і показує щось на кшталт yaml: line 7: did not find expected key, якщо порушено відступи.

Жоден із цих інструментів не перевіряє задум. Конфігурація, яка проходить nginx -t, усе одно може проксувати запити не на той порт або слухати 0.0.0.0, хоча вам потрібен 127.0.0.1. Саме в цій розбіжності модель може бути корисною, але тут вона також помиляється: якщо попросити виправити одну директиву, вона часто повертає весь файл у зміненому вигляді та непомітно видаляє дві ваші директиви. Попросіть показати змінені рядки й пояснити причину кожної зміни, а потім внесіть правки вручну.

Перевірте, що саме ви відкрили назовні:

sudo ss -tulpn

Без sudo ви бачите сокети, які прослуховуються, але не процеси, що ними володіють. Якщо цей вивід вас здивував, коротше пояснення призначення портів і прив’язування Linux до них.

Завдання 4: поясніть незнайому команду, перш ніж запускати її

Вставте команду та поставте щодо неї чотири запитання: що робить кожен прапорець, що вона записує, що видаляє і що станеться, якщо запустити її двічі. Останнє запитання допомагає виявити більше потенційної шкоди, ніж інші.

Розглянемо find /var/log -name '*.gz' -mtime +7 -delete. Правильна відповідь пояснює, що -mtime +7 рахує повні 24-годинні періоди та відкидає дробову частину. Тому команда знаходить файли віком щонайменше вісім днів, а не сім. Також слід зазначити, що find обчислює вираз зліва направо. Якщо перемістити -delete перед -name, команда видалить усе під початковим шляхом. Це попередження наведено на сторінці довідки find. Через цю помилку люди втрачали /var/log.

Або розглянемо rsync -a --delete /srv/app/ /backup/app/. Кінцева скісна риска в джерелі означає «вміст цього каталогу». Якщо прибрати її, результатом буде /backup/app/app/. Додайте --delete — і все, чого немає в джерелі, буде видалено з призначення. Для дзеркальної копії це правильно, але неправильний шлях до джерела перетворює операцію на аварійну.

Перевіряйте за допомогою інструмента, а не моделі:

rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7

Запустіть find без -delete — і отримаєте список замість втрати даних.

Типовий сценарій помилки: вигаданий прапорець. Модель добре працює з інструментами, документації до яких уже тридцять років, але значно частіше помиляється з CLI виробників і новими підкомандами. Вона може запропонувати прапорець, який виглядає цілком правдоподібно, але насправді не існує. --help допомагає перевірити це за одну секунду. Інша проблемна зона — лапки. Тому, якщо команда містить вираз $(...), прочитайте як розгортається підстановка команд перед запуском команди, а не покладайтеся на пояснення.

Завдання 5: перетворіть історію shell на runbook

Ви щойно витратили дві години на те, щоб усе запрацювало. Ці знання залишилися у scrollback і наступного місяця зникнуть.

history 200 > /tmp/session.txt

Прочитайте цей файл і видаліть кожен рядок, що містить пароль, токен або ідентифікатор клієнта, перш ніж передавати його куди-небудь. Історія shell — одне з найнадійніших місць для пошуку секрету на Linux-системі, оскільки кожен хоча б раз вводить секрет безпосередньо в командному рядку. Установіть HISTCONTROL=ignorespace у ~/.bashrc, і команда, введена з пробілом на початку, взагалі не записуватиметься в історію.

У запиті, який дає придатний runbook, просіть не лише описати кроки, а й додати перевірки:

Це shell-сеанс, під час якого на чистій системі Debian 13 було налаштовано робочий Postgres. Оформіть його як нумерований runbook. Один крок — одна команда. Після кожного кроку наведіть команду, яка підтверджує успішне виконання, і опишіть, як має виглядати коректний результат. Позначте кожен крок, який залежав від параметрів мого конкретного хоста.

Типова помилка: охайна історія. У вашому сеансі був крок, який ви двічі виконали неправильно, перш ніж виправити. Саме цей крок модель згладжує, оскільки без нього transcript виглядає чистіше. Порівняйте runbook з історією та поверніть виправлення. Модель також вигадує правдоподібні команди перевірки, тому виконайте кожну перевірку, яку вона записала, перш ніж зберігати файл. Якщо runbook охоплює перше завантаження системи, звірте його з першими десятьма хвилинами на новому VPS, щоб не записати гіршу версію вже розв’язаної проблеми.

Завдання 6: перетворіть повідомлення про помилку на виправлення

Вставте точний рядок, команду, яка його вивела, і єдину зміну, внесену безпосередньо перед появою помилки. Попросіть упорядкувати можливі причини та навести окрему команду для розрізнення кожної з них. Це змусить відповідь містити перевірювані дії.

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Упорядкуй імовірні причини та наведи по одній команді для кожної, яка підтвердить або виключить її.

У цьому випадку механізм однозначний: інший процес уже використовує порт 80, а sudo ss -tulpn | grep ':80 ' показує, який саме. Часто це другий master-процес nginx, що залишився після невдалого reload, або Apache, який було підключено як залежність і запущено власним пакетом.

Типова помилка: виправлення приховує причину. chmod 777, --privileged, вимкнення SELinux і запуск сервісу від імені root усувають повідомлення про помилку. Не приймайте виправлення, які розширюють дозволи, доки модель не пояснить, чому вузький дозвіл не спрацював. Саме це пояснення і є відповіддю. Обхідне рішення лише приховує помилку.

Що він стабільно робить неправильно

  • Він не бачить ваш сервер. Кожна відповідь залежить від того, що ви вставили, і він не повідомить, що наведений фрагмент замалий.
  • Він плутається у версіях. Назви пакетів і стандартні прапорці відрізняються в різних дистрибутивах і релізах, а модель усереднює дані про всі них.
  • Він переконливо помиляється. Вигаданий механізм виглядає так само, як правильний. Саме тому кожна наведена вище причина супроводжується командою для її перевірки.
  • Він втрачає контекст під час тривалих сеансів. Факти з початку двогодинної розмови перестають впливати на відповіді наприкінці.

Остання проблема більше пов’язана з робочим процесом, ніж із моделлю. Практичне рішення — керування контекстом у тривалому сеансі Claude Code: коротші сеанси, одне завдання в кожному.

Розміщення агента безпосередньо на сервері

Усе описане вище зводиться до копіювання та вставлення, тому модель не взаємодіє з вашим комп’ютером. Коли агент запускається безпосередньо на сервері, читає файли та виконує команди, характер ризику змінюється: неправильна команда може зупинити сервіс. Створіть для агента окремого непривілейованого користувача, а не запускайте його від імені root. Поки ви вивчаєте його поведінку, не запускайте агент на production-сервері. Спочатку створіть snapshot. У матеріалі Безпечний запуск Claude Code на VPS описано ізоляцію та модель дозволів. Матеріал Керування Claude Code у tmux вирішує іншу проблему: розірване SSH (secure shell)-з’єднання завершує роботу агента, який виконується у foreground, посеред виконання завдання. Створіть цей обліковий запис так само, як будь-який service account. Це докладно описано в матеріалі Користувачі з мінімальними привілеями на VPS.

FAQ

Чи може Claude безпосередньо читати журнали мого сервера?

Ні, не самостійно. Інтерфейс чату бачить лише текст, який ви вставляєте в нього. Claude Code, запущений на сервері як інструмент командного рядка, може читати файли та виконувати команди з дозволами користувача, який його запустив. Це суттєво більше рішення з погляду довіри. Для звичайного запиту до служби підтримки швидше й безпечніше вставити скорочений фрагмент журналу на 100 рядків, ніж надавати агенту доступ до shell.

Що ніколи не можна вставляти з сервера?

Приватні ключі, файли .env та інші сховища облікових даних, /etc/shadow, а також будь-які дані, що належать вашим користувачам. Перед вставленням фрагментів журналу в prompt видаліть із них токени. Є один неочевидний випадок: результат виконання docker compose config містить у підставленому вигляді значення .env, тому використовуйте docker compose config -q. Він перевіряє файл і нічого не виводить.

Чи безпечно дозволяти Claude виконувати команди на production VPS?

Ставтеся до нього як до нового адміністратора, який не знає контексту: читання допустиме, запис потребує перевірки. У production попросіть пояснити команду та виконайте її самостійно. Якщо ви все ж хочете, щоб агент виконував команди, надайте йому окремий непривілейований обліковий запис без необмеженого sudo і почніть зі staging-сервера, де помилка призведе до повторного розгортання, а не до простою.

Чому Claude пропонує прапорець, якого не існує?

Тому що він прогнозує правдоподібний текст, а правдоподібний прапорець виглядає так само, як справжній. Найчастіше це трапляється з CLI виробників і новішими підкомандами, документація для яких недостатньо представлена в даних моделі або вже змінилася. Арбітрами є --help і man. Будь-яку команду, яка видаляє або перезаписує дані, спочатку слід виконати в режимі dry run.

Як перевірити unit systemd перед його увімкненням?

Виконайте sudo systemd-analyze verify /etc/systemd/system/myapp.service. Команда аналізує файл власним парсером systemd, повідомляє про невідомі директиви із зазначенням номерів рядків і позначає бінарний файл ExecStart, якого немає або який не має дозволу на виконання. Потім виконайте daemon-reload, start і прочитайте systemctl status перед тим, як enable його, оскільки unit, який завантажується без помилок, усе одно може завершитися помилкою під час першого запуску.