SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor

Як керувати кількома Linux-серверами: робочі інструменти

SSH config, tmux, Ansible, Uptime Kuma, Zabbix і Webmin порівняно за кількістю серверів: що замінюють, налаштування за хвилини та головна пастка.

Що ви створюєте

Не один інструмент, а невеликий стек, підібраний за фактичною кількістю серверів. Це єдиний важливий параметр, який ігнорує кожен огляд «інструментів для керування Linux-серверами». Класична помилка — взяти рішення для 200 серверів, коли у вас чотири VPS, а потім витратити місяць на обслуговування інструмента замість серверів. Друга класична помилка — мати вісімнадцять серверів і досі підключатися до кожного через SSH вручну, застосовуючи «одну й ту саму» зміну вісімнадцятьма дещо різними способами.

Тому цей посібник організовано за розміром парку серверів: від 2 до 5 серверів, від 5 до 20 і понад 20, а також за наскрізним рівнем, потрібним за будь-якого розміру парку й майже завжди не описаним: інвентаризація, належне керування ключами, єдиний спосіб доступу та резервні копії, відновлення яких ви справді перевіряли. Для кожного інструмента наведено три речі: що він замінює, скільки хвилин займає налаштування і яка особливість насправді може спричинити проблеми. Я керую VPS-хостом уже п’ятнадцять років. Нижче наведено те, що витримує аварію о 2-й годині ночі, а не те, що добре виглядає в демонстрації.

Передумови та чесні застереження

На кожному сервері вже має працювати SSH із ключами (якщо ви досі вводите паролі, спочатку виправте це: це займає десять хвилин, а все нижче передбачає використання ключів), потрібен користувач із правами sudo, який не є root, і сервери мають працювати на актуальному ПЗ. Команди нижче розраховані на Ubuntu 24.04, але нічого не є специфічним для Ubuntu, крім apt.

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

Від 2 до 5 серверів: ~/.ssh/config — найбільш недооцінений інструмент, який у вас уже є

Що він замінює: текстовий файл зі списком IP-адрес, археологію в історії shell (ssh 203.0, потім Ctrl-R і надія на краще) та нескінченне введення -p 2222 -i ~/.ssh/other_key. Витрати на налаштування: 15 хвилин один раз. Проблема: застарілі сокети мультиплексування, про які йдеться нижче.

За такого масштабу додаткове програмне забезпечення не потрібне. Потрібно лише правильно налаштувати клієнт, який у вас уже є. ~/.ssh/config перетворює кожен сервер на однослівне ім’я та зберігає правила маршрутизації, щоб вам більше не доводилося про них думати:

Host *
    ServerAliveInterval 30
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h-%p
    ControlPersist 10m

Host bastion
    HostName 10.0.0.10
    User matt

Host web1
    HostName 10.8.0.11
    User matt
    ProxyJump bastion

Host db1
    HostName 10.8.0.12
    User matt
    Port 2222
    ProxyJump bastion

Роботу виконують три параметри. ProxyJump за один перехід маршрутизує з’єднання через bastion, тому ssh db1 з кав’ярні прозоро тунелює через bastion без agent forwarding і без заклинань на кшталт ProxyCommand. Приватним серверам при цьому взагалі не потрібні публічні SSH-порти (докладніше про це в наскрізному розділі). ControlMaster auto разом із ControlPersist мультиплексує з’єднання через один TCP-сеанс. Тому другий і всі наступні ssh, scp або rsync до того самого хоста підключаються миттєво, без повторного узгодження параметрів. Коли з’являється Ansible, різниця стає особливо помітною. Оскільки scp, rsync і Ansible читають той самий файл, кожне визначене тут ім’я працює всюди.

Проблема полягає в тому, що головне з’єднання може залишитися активним після втрати корисності, а два режими відмови мають різний вигляд. Коли сервер перезавантажується або зникає Wi-Fi, головний процес зберігає мертвий TCP-сеанс і ще не встигає це виявити. Наступний ssh web1 тоді непомітно зависає на сокеті, який уже нікуди не веде. Окремо sshd обмежує кількість сеансів для одного з’єднання значенням 10 (MaxSessions у sshd_config), тому одинадцятий мультиплексований сеанс до одного хоста виводить:

mux_client_request_session: session request failed: Session open refused by peer

В обох випадках виправлення однакове: ssh -O exit web1 завершує головний процес, а наступне з’єднання запускає новий. Іноді ви також можете побачити ControlSocket /home/matt/.ssh/cm-matt@10.8.0.11-22 already exists, disabling multiplexing. Це не небезпечно: два сеанси запустилися одночасно, і з’єднання все одно працює, але без мультиплексування.

На цьому рівні корисні ще два інструменти. tmux на кожному сервері замінює nohup, захищає від втрати роботи після розриву Wi-Fi та усуває ситуацію «я не можу закрити ноутбук, бо виконується міграція». Витрати на налаштування: sudo apt install -y tmux, дві хвилини, а також звичка використовувати tmux new -s work і tmux attach -t work. Проблема виникає через вкладені сеанси: tmux усередині tmux перехоплює клавішу префікса. Тому запускайте його або на сервері, або на ноутбуці, але не в обох місцях. Якщо ви запускаєте довготривалі сеанси агентів, це вдвічі важливіше. Це той самий підхід, що й у випадку запуску Claude Code у tmux на VPS, коли сеанс має пережити SSH-з’єднання.

Спільний файл alias замінює повторне введення дванадцяти улюблених однорядкових команд на кожному сервері. Зберігайте .bash_aliases у git-репозиторії та завантажуйте його на кожен сервер. Проблема полягає в тому, що файл одразу починає відрізнятися, якщо редагувати його безпосередньо на одному сервері, а не в репозиторії. Це також перше пояснення, навіщо потрібен наступний рівень.

Від 5 до 20 серверів: конфігурація як код, інакше перемагає дрейф

Після приблизно п’яти серверів підхід «я просто зроблю це на кожному сервері» перестає бути методом і стає самообманом. Усі інструменти цього рівня борються з одним ворогом: дрейфом конфігурації.

Ansible замінює shell-цикл за списком імен хостів, wiki-сторінку з назвою «налаштування нового сервера», яка вже на три кроки застаріла, і занепокоєння через невідомість, чи справді web3 отримав виправлення. Вартість налаштування: 30 хвилин до першого робочого playbook, sudo apt install -y ansible на вашому ноутбуці або management box (apt встановлює старішу версію Ansible, але для всього описаного тут цього достатньо; у tutorial використовується маршрут через pipx для отримання актуальних версій), без агентів на серверах, усе працює через конфігурацію SSH, яку ви вже створили. Це найбільше окреме покращення на цій сторінці. Повний опис наведено в tutorial про перший playbook в Ansible; ось структура inventory, яка забезпечує його роботу:

[web]
web1 ansible_host=10.8.0.11
web2 ansible_host=10.8.0.12

[db]
db1 ansible_host=10.8.0.21 ansible_port=2222

[all:vars]
ansible_user=matt
ansible_ssh_common_args='-o ProxyJump=bastion'

Оскільки Ansible запускає бінарний файл OpenSSH, ~/.ssh/config, який ви записали в попередньому розділі, уже застосовується. Inventory із простими іменами, наприклад web1, працював би взагалі без vars. Наведені вище vars натомість роблять inventory самодостатнім. Це особливо корисно в день, коли ви запускаєте його з машини, яка не є вашим ноутбуком.

Перевірте це командою ansible all -i inventory.ini -m ping. Правильний результат виводить "ping": "pong" для кожного хоста зеленим кольором. Перша помилка, з якою ви зіткнетеся, виглядає так:

web1 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: matt@10.8.0.11: Permission denied (publickey).",
    "unreachable": true
}

Це не проблема Ansible: звичайний ssh matt@10.8.0.11 завершується так само. Завжди спочатку виправляйте SSH. Ansible працює не краще, ніж базовий шар під ним. Є ще одне застереження: Ansible потребує Python на вашій машині та, для майже кожного модуля, зокрема ping, також на сервері. Тому справді мінімальний образ може відповісти /usr/bin/python3: not found. Один apt install python3 — і ця проблема більше вас не турбуватиме. Для цілого fleet із мінімальних образів модуль raw, один із небагатьох, якому не потрібен Python на віддаленій машині, може виконати це встановлення замість вас.

unattended-upgrades замінює вас як особу, яка застосовує security patches до N серверів. Stock Ubuntu Server 24.04 постачається з ним попередньо встановленим і зазвичай уже ввімкненим для security updates, тому тут потрібно перевірити, а не встановлювати:

cat /etc/apt/apt.conf.d/20auto-upgrades

Обидва рядки мають завершуватися на "1". Деякі мінімальні та cloud images постачаються з вимкненим сервісом, а sudo dpkg-reconfigure -plow unattended-upgrades перезаписує цей файл, якщо у вашому випадку це так. Вартість налаштування: дві хвилини на перевірку кожного сервера або одна Ansible task для всіх серверів. Застереження: за замовчуванням цей інструмент ніколи не перезавантажує сервер, тому security updates для ядра залишаються застосованими лише частково, доки ви цього не зробите. У окремому посібнику з unattended-upgrades описано автоматичні перезавантаження, вибір оновлень для встановлення та читання його журналів.

Централізований моніторинг замінює отримання інформації від клієнта — найдорожчу систему моніторингу з усіх можливих. Є два інструменти, по одному рядку про те, коли їх використовувати: Uptime Kuma відповідає на запитання «чи працює сервіс?», виконує HTTP-, TCP- і ping-перевірки та надсилає сповіщення будь-куди; його налаштування в Docker займає десять хвилин. Zabbix відповідає на запитання «чи не починає сервіс відмовляти?», відстежує тенденції використання диска, пам’яті та CPU через агент на кожному хості, а його налаштування чесно займає післяобідній час. Почніть із Kuma. Додавайте Zabbix, коли ситуація «сервіс працює, але деградує» почне коштувати вам грошей. Застереження для обох інструментів стосується розміщення. Воно настільки важливе, що йому присвячено розділ про помилки нижче.

Вебпанель — лише за потреби. Webmin замінює запам’ятовування того, де Ubuntu зберігає налаштування. Для команди з різним рівнем навичок або сервера, до якого ви звертаєтеся двічі на рік, він справді корисний. Налаштування займає десять хвилин. Застереження: це вебзастосунок із правами, еквівалентними root, який прослуховує порт 10000, а інтернет постійно сканує цей порт. Якщо ви використовуєте його, прив’яжіть його до localhost або адреси VPN, але ніколи не прив’язуйте до 0.0.0.0 на публічному інтерфейсі. Якщо ви звертаєтеся до панелі, бо SSH здається повільним, спочатку перечитайте попередній розділ: ~/.ssh/config разом з Ansible після налаштування працюють швидше за будь-яку панель.

20+ серверів: де цей посібник чесно завершується

Після двадцяти серверів ви вже керуєте флотом, і набір інструментів змінюється: Terraform або OpenTofu, щоб самі сервери можна було відтворювати; cloud-init або golden images, щоб сервер був одноразовим, а не таким, який потрібно відновлювати; pull-based конфігурація або CI pipelines, що запускають Ansible, оскільки push із ноутбука перестає масштабуватися; а також повноцінне керування секретами. Сам Ansible не перестає працювати на двадцяти серверах: багато команд використовують його для сотень вузлів. Але супутні практики потрібно посилювати, і це вже тема для іншої статті, ніж ті, що публікує цей сайт. Якщо ви працюєте в такому масштабі, наведений нижче розділ усе одно для вас, оскільки inventory, ключі та дисципліна доступу — це саме те, що fleet tooling передбачає як уже наявне.

Шар, про який ніхто не записує

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

Файл інвентаризації, навіть текстовий. Щойно у вас з’являється три сервери, запишіть: ім’я, IP-адресу, провайдера, що на сервері працює і навіщо він потрібен. servers.md у git-репозиторії достатньо; наведений вище інвентар Ansible кращий, оскільки це виконувана документація. Він замінює запитання о другій ночі: «Зачекайте, що таке 10.0.0.40?». Витрати на налаштування: десять хвилин. Важливий нюанс: це працює лише тоді, коли створення сервера й додавання рядка відбуваються одночасно, а не як дві окремі дії.

Гігієна ключів: ротація зараз, SSH CA — коли це стане проблемою. Визначте, де зберігаються ваші ключі (cat ~/.ssh/*.pub на вашій стороні, ~/.ssh/authorized_keys на стороні кожного сервера), видаліть ключі з колишніх ноутбуків і колишніх колег та замініть усі ключі, для яких ви вже не можете сказати, де вони побували. SSH certificate authority і короткоживучі підписані сертифікати замість статичних ключів — зрілий підхід. Але чесна порада така: якщо серверів менше десяти, дисципліноване керування authorized_keys через Ansible дає 90% переваг за 10% складності.

Один спосіб доступу, а не двадцять. Кожен публічний SSH-порт збільшує площу атаки в N разів. Масштабований підхід: один bastion host або, ще краще, WireGuard VPN на VPS під вашим контролем, а SSH на всіх інших серверах має бути прив’язаний лише до їхніх приватних адрес. Рядки ProxyJump у наведеній вище конфігурації вже передбачають таку схему. Для всього, що має залишатися публічним, за замовчуванням налаштуйте fail2ban. Витрати на налаштування: одна година. Важливий нюанс: перевірте, що резервний спосіб доступу — консоль провайдера — працює, перш ніж закривати порт 22 всюди, а не після цього.

Резервні копії потрібно перевіряти відновленням. Неперевірена резервна копія — це лише припущення. Незалежно від механізму — snapshot провайдера, restic, rsync на другий сервер — насправді важливим є запис у календарі, за яким ви відновлюєте один сервер на чистому VPS і перевіряєте, що він завантажується та обслуговує запити. У кожній історії про проблеми з резервними копіями, яку я чув за п’ятнадцять років хостингу, була фраза: «У нас були резервні копії».

Помилки

Причини збоїв у масштабі кількох серверів пов’язані не з інструментами, а зі звичками. Майже все зводиться до чотирьох проблем.

Сервери-сніжинки. Кожен сервер налаштований вручну, трохи відрізняється від інших, і ніхто не може відтворити його конфігурацію. Це з’ясовується під час відмови диска. Рішення нецікаве: кожна зміна має проходити через Ansible або щонайменше додаватися до розділу цього сервера в документі інвентаризації. Сервер, який ви не змогли б відновити за нотатками сьогодні вдень, є технічним боргом із терміном погашення, який ви не можете обрати.

«Тимчасові» отвори у firewall. ufw allow 5432 для налагодження, а через вісімнадцять місяців Postgres досі доступний з інтернету. Перевірте правила за допомогою sudo ufw status numbered на кожному сервері або однією командою — ansible all -i inventory.ini -a "ufw status numbered" --become. Видаліть усе, для чого не можете назвати актуальну причину. Якщо правило справді тимчасове, відповідна команда ufw delete має бути виконана в тому самому вікні tmux до його закриття.

Моніторинг, розміщений на сервері, за яким він стежить. Якщо Uptime Kuma працює на сервері, який моніторить, сповіщення «все недоступне» також буде недоступним. У такому разі ви створили меншу й менш ефективну версію найнеефективнішого дата-центру у світі. Моніторинг має бути в іншому домені відмови: класичний варіант — недорогий VPS в іншого провайдера. Щонайменше використовуйте зовнішню перевірку на безкоштовному тарифі, яка стежить за системою моніторингу.

SSH під root усюди. Один спільний ключ root для всього парку серверів означає, що один викрадений ноутбук дає доступ до всіх систем. Крім того, в журналі аудиту не буде видно, хто що зробив. Створіть окремих користувачів для кожної людини, налаштуйте sudo і PermitRootLogin no у /etc/ssh/sshd_config на кожному хості. Це знову лише три рядки в задачі Ansible замість цілого вечора ручного введення команд.

Коли парк серверів перевищує кілька машин, ваш перший playbook Ansible автоматизує повторювані операції.

FAQ

Який найкращий безкоштовний інструмент для керування кількома Linux-серверами?

Для 2–5 серверів добре написаний ~/.ssh/config разом із tmux ефективніший за будь-який інструмент, який можна встановити. Приблизно від п’яти серверів стандартним вибором є Ansible: він не потребує агентів, безкоштовний, працює через наявний SSH і перетворює налаштування серверів на файли в git. Додайте Uptime Kuma для сповіщень про доступність сервісів. Усі інструменти, названі в цьому посібнику, є вільним програмним забезпеченням.

Чи можна керувати кількома Linux-серверами без Ansible?

Так. Якщо серверів менше приблизно п’яти, достатньо правильно налаштованого SSH, спільного файлу alias і дисципліни. Багато адміністраторів працюють так роками. Коли серверів стає більше, альтернативою Ansible є не «нічого», а ненадокументовані відмінності: 18 серверів, кожен із трохи іншими ручними налаштуваннями. Якщо Ansible здається надто складним, почніть з одного playbook, який керує лише authorized_keys і unattended-upgrades. Цього вже достатньо, щоб виправдати час на навчання.

Як одночасно виконати ту саму команду на кількох Linux-серверах?

ansible all -i inventory.ini -a "uptime" — оптимальний варіант. Для нього потрібен лише inventory-файл, а playbook не потрібен. Для інтерактивної роботи поруч у кількох сесіях tmux може передавати натискання клавіш до кожної панелі за допомогою setw synchronize-panes on. Але сприймайте це лише як демонстраційний прийом: передавання інтерактивних команд на production-сервери може перетворити одну помилку набору на збій, помножений на кількість серверів.

Чи потрібна для керування Linux-серверами панель керування на зразок Webmin?

Ні. Усе, що робить панель, SSH і Ansible виконують більш відтворювано. Webmin виправданий, коли ті самі сервери адмініструють люди з різним рівнем підготовки або коли ви звертаєтеся до сервера настільки рідко, що повторний пошук шляхів до конфігурації займає багато часу. Якщо ви використовуєте Webmin, ставтеся до нього як до вебзастосунку з еквівалентними правами root: прив’яжіть його до localhost або адреси VPN, а не до публічного інтерфейсу.

Скільки Linux-серверів одна людина може реально адмініструвати?

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