Claude для системних адміністраторів: 6 завдань
Шість типових завдань для Claude: аналіз журналів failed unit, підготовка systemd unit, перевірка nginx і Compose, а також дані, які не можна вставляти.
Claude для системних адміністраторів: спочатку поради, потім виконання
Claude для системних адміністраторів найкраще працює як інструмент перевірки. Вставте фрагмент журналу, файл конфігурації, незнайому команду або текст помилки — і отримаєте пояснення, яке можна перевірити до внесення будь-яких змін на сервері. Неправильна відповідь не завдасть шкоди, доки ви її не виконаєте. Тому основна модель безпеки полягає в тому, щоб використовувати модель для надання порад, а не для безпосереднього виконання.
На орендованому Linux VPS (virtual private server) щотижня виникають шість типових завдань. Нижче для кожного наведено робочий шаблон запиту, команду для перевірки відповіді та очікуваний сценарій збою. Для жодного з них моделі не потрібен доступ до вашого сервера. Ви можете вставити дані з вкладки браузера або вікна на власному робочому столі, оскільки Claude нативно працює в Linux як desktop app і CLI.
На production-сервері важливий порядок дій: прочитайте пояснення, самостійно виконайте перевірку, а потім приймайте рішення. На тестовій 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. Для відповіді на жодне запитання системного адміністратора не потрібен хеш пароля. - Будь-які дані ваших користувачів: адреси електронної пошти, рядки замовлень, журнали запитів із session cookies або 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 рядків журналу. Який рядок є першою справжньою помилкою і що він означає? Поки що без виправлення.
Фраза «Поки що без виправлення» у цьому запиті має практичне значення. Журнал приховує першу помилку повідомленнями про повторні спроби, які вона спричинила. Тому модель, яку попросили одразу запропонувати виправлення, пояснить останній побачений рядок. Важливий рядок зазвичай розташований приблизно на 20 рядків вище від цього шуму.
Результатом може бути рядок на кшталт Main PID: 1841 (code=exited, status=203/EXEC). Код завершення 203/EXEC означає, що kernel не зміг виконати файл, указаний у ExecStart: шлях не існує або файл існує, але не має права на виконання. Такий самий код повертає рядок #!, якщо в ньому вказано interpreter, якого не встановлено. Усе це можна перевірити за допомогою 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-pagersystemd-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 може коректно завантажитися, але одразу завершитися з помилкою під час запуску.
Є 2 типові помилки під час підготовки конфігурації. Перша — After=network.target. Це означає лише те, що мережевий стек налаштований, але IP-адреса ще може бути відсутня. Сервіс, який прив’язується до конкретної IP-адреси, під час завантаження завершується з помилкою bind: Cannot assign requested address. Виправлення — Wants=network-online.target разом із After=network-online.target. Друга — Type=simple для програми, яка переходить у режим daemon. systemd вважає перший процес сервісом, батьківський процес одразу завершується, а unit позначається як зупинений, тоді як справжній процес продовжує працювати без керування. Саме таку помилку модель найімовірніше запропонує, оскільки з команди неможливо визначити, чи створює бінарний файл дочірній процес. Тому перед прийняттям такого варіанта варто знати що саме гарантує systemd кожне значення Type=.
Для розкладу перевірте запис, а не просто прочитайте його:
systemd-analyze calendar 'Mon *-*-* 04:00:00'Команда виведе нормалізовану форму та наступний час виконання виразу. Це усуває суперечки щодо його значення. Якщо ви обираєте між timer і crontab, у матеріалі сервіси й timer systemd на VPS описано компроміси між цими варіантами.
У cron є особливість, про яку модель не попередить без відповідного запиту. cron запускає завдання з мінімальним набором змінних середовища. Тому PATH приблизно дорівнює /usr/bin:/bin, а профіль shell ніколи не читається. Завдання, яке працює після вставлення команди в термінал, завершується в cron з помилкою /bin/sh: 1: docker: not found, оскільки цей бінарний файл розташований у /usr/local/bin. У crontab використовуйте абсолютні шляхи. Якщо вимога unit-файлу явно вказувати користувача, середовище та залежності здається зайвою формальністю порівняно з одним рядком crontab, у матеріалі описано проблеми, для розв’язання яких створили systemd.
Завдання 3: перевірте файл nginx або Compose перед введенням в експлуатацію
Це завдання дає найбільшу користь. Вставте файл, опишіть його призначення та попросіть пояснити кожен рядок і фактичну поведінку конфігурації.
Цей vhost має обслуговуватиexample.comчерез HTTPS і проксувати/apiдо локального сервісу на порту 8080. Проаналізуй конфігурацію та назви все, що не відповідає цьому опису.
Потім запустіть інструмент, який перевіряє граматику:
sudo nginx -t
docker compose config -qnginx -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 допомагає перевірити це за одну секунду. Ще одним слабким місцем є quoting, тому, коли команда містить вираз $(...), прочитайте як розгортається підстановка команд до запуску команди, а не покладайтеся на пояснення.
Завдання 5: перетворіть історію shell на runbook
Ви щойно витратили дві години на те, щоб налаштувати щось до робочого стану. Тепер ці знання зберігаються у scrollback, а наступного місяця їх уже не буде.
history 200 > /tmp/session.txtПрочитайте цей файл і видаліть кожен рядок із паролем, токеном або ідентифікатором клієнта, перш ніж передавати файл кудись. Історія shell — одне з найнадійніших місць для пошуку секрету на Linux-системі, оскільки кожен хоча б раз вводить секрет безпосередньо в командному рядку. Додайте HISTCONTROL=ignorespace у свій ~/.bashrc, і команда, введена з пробілом на початку, взагалі не записуватиметься в історію.
У запиті, який дає придатний runbook, потрібно просити не лише послідовність дій, а й перевірки:
Це shell-сеанс, під час якого на чистій системі Debian 13 було налаштовано робочий Postgres. Оформіть його як нумерований runbook. Один command на крок. Після кожного кроку наведіть command, який підтверджує успішне виконання, і опишіть, як має виглядати коректний результат. Позначте кожен крок, який залежав від параметрів мого конкретного хоста.
Типова помилка — охайна історія. У вашому сеансі був крок, який ви двічі виконали неправильно, перш ніж виправити його. Саме цей крок модель прибере, оскільки без нього 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, який залишився після невдалого перезавантаження конфігурації, або Apache, підключений як залежність і запущений власним пакетом.
Сценарій збою: виправлення, яке приховує причину. chmod 777, --privileged, вимкнення SELinux і запуск сервісу від імені root усувають помилку лише зовні. Відхиляйте будь-яке виправлення, яке розширює дозволи, доки модель не пояснить, чому вузький дозвіл не спрацював. Саме це пояснення є фактичною відповіддю. Обхідне рішення лише приглушує помилку.
Що воно стабільно робить неправильно
- Воно не бачить ваш сервер. Кожна відповідь залежить від того, що ви вставили, і модель не повідомить, що уривок був надто коротким.
- Воно плутається у версіях. Назви пакетів і прапорці за замовчуванням змінюються між дистрибутивами та релізами, а модель узагальнює інформацію про всі них.
- Воно переконливо помиляється. Вигаданий механізм звучить так само, як правильний. Саме тому для кожної наведеної вище причини є команда, яка її перевіряє.
- Воно втрачає контекст під час довгих сеансів. Факти з початку двогодинної розмови перестають впливати на відповіді наприкінці.
Остання проблема більше пов’язана з робочим процесом, ніж із самою моделлю. Практичне рішення — керування контекстом у довгому сеансі Claude Code: коротші сеанси, по одному завданню в кожному.
Розміщення агента безпосередньо на сервері
Усе описане вище можна виконати копіюванням і вставленням, тому модель не взаємодіє з вашим комп’ютером. Коли агент запускається на сервері, читає файли та виконує команди, характер ризику змінюється: неправильна команда може зупинити сервіс. Створіть для нього окремого непривілейованого користувача, а не використовуйте root. Поки ви вивчаєте його поведінку, не запускайте агента на production-сервері. Спочатку створіть snapshot. У матеріалі Безпечний запуск Claude Code на VPS описано sandboxing і модель дозволів. Матеріал Керування Claude Code у tmux вирішує іншу проблему: у разі розриву SSH-сеансу агент, запущений у 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 від постачальників і новішими subcommand, для яких документація, доступна моделі, неповна або вже змінилася. --help і man є остаточним джерелом перевірки. Будь-яку команду, яка видаляє або перезаписує дані, спочатку слід виконати в режимі dry run.
Як перевірити unit systemd перед увімкненням?
Виконайте sudo systemd-analyze verify /etc/systemd/system/myapp.service. Ця команда аналізує файл за допомогою власного парсера systemd, повідомляє про невідомі директиви із зазначенням номерів рядків і вказує на відсутній або не виконуваний бінарний файл ExecStart. Потім виконайте daemon-reload, start і прочитайте systemctl status, перш ніж виконувати enable для цього unit. Unit, який коректно завантажується, все одно може завершитися помилкою під час першого запуску.