~/.ssh/config.d/

Продовжую тему про SSH. Сьогодні розкажу відносно просту дрібничку про те, як краще організувати великий .ssh/config зі значною кількістю хостів.

Може, хтось з однієї тільки назви посту вже все зрозумів :) Ну а я далі напишу, як я дійшов до життя такого. У мене багато конфігурації SSH, і переважно це параметри доступу до різних хостів.

Приклади конфігурація

Що у нас взагалі діється в тій конфігурації?

Уявімо, що у хоста host1 IP-адреса 10.20.30.40 в нашій локальній мережі, і що sshd на ньому слухає порт 2250. У нас там є обліковий запис користувача user1. Як нам туди потрапити?

ssh -l user1 -p 2250 10.20.30.40

Ні, так живі люди не пишуть, зручніше так:

ssh user1@10.20.30.40:2250

Але ще зручніше, якщо у конфігураційному файлі .ssh/config написати приблизно отакий блок:

Host host1 host1.example.com 10.20.30.40
  HostName 10.20.30.40
  Port 2250
  User user1
  HostKeyAlias host1

Написати коротку команду ssh host1 мені простіше, ніж щоразу вказувати логін, порт і всю іншу фігню. Ну і запам’ятати треба лише ім’я хоста (або будь-яке з варіантів імен).

Якщо я з такою конфігурацією виконаю ssh host1 (або ssh host1.example.com, або ssh 10.20.30.40, ці три варіанти рівнозначні), то SSH з’єднається саме з хостом 10.20.30.40 на порту 2250, використає для з’єднання ім’я користувача user1, а ще (незалежно від того, з яким саме з аліасів запустили SSH) для цього хоста в ~/.ssh/known_hosts буде використовуватися рядок з іменем host1.

  • Якщо SSH працює на стандартному порту 22, то рядок Port нам не потрібен.
  • Якщо логін користувача на віддаленому хості співпадає з локальним, то рядок User теж не потрібен. Але якщо ця конфігурація використовується одночасно на різних хостах, і на цих хостах у вас різні логіни, то тут уже можливі варіанти. Безпечніше явно вказати логін.
  • Рядок HostName завжди присутній. Це адреса, з якою фактично відбувається з’єднання. Якщо є можливість обирати, то я тут частіше використовую IP-адресу, а не доменне ім’я. В локальній мережі це завжи IP. Якщо DNS впаде, і коли треба буде піти по SSH на DNS-сервер щось полагодити, то краще йти по IP.
  • Рядок HostKeyAlias теж завжди присутній, це щоб для одного хоста було лише одне входження в ~/.ssh/known_hosts.

Бувають більш складні і цікаві рядки конфігурації, може port forwarding, або proxy jump.

Та головне, що з часом з’являється все більше конфігурації для різних хостів. А коли хостів стає хоча б десяток (не кажучи вже про сотню), виникає певна незручність у редагуванні.

Що я пропоную

Давайте просто розділимо конфігурацію на окремі шматочки.

Створіть каталог ~/.ssh/config.d/ (або зробіть сімлінк кудись у ваш репозитарій з конфігурацією).

Покладіть в цей каталог різні файли конфігурації для різних хостів. Наприклад, вищенаведений фрагмент конфігурації можна покласти в файл ~/.ssh/config.d/host1. Якщо на один хост є кілька фрагментів конфігурації (наприклад, варіанти доступу різним шляхом), то їх логічно об’єднати.

Тепер у файлі .ssh/config достатньо одного рядка:

Include config.d/*

І все. Це зручно, спробуйте.

Приклад з Vagrant

Ось одна з переваг такого підхода: можна автоматично створювати незалежні фрагменти конфігурації, не зачіпаючі все інше. (Або так само автоматично їх видаляти).

Наприклад, якщо ви користуєтеся Vagrant, то для кожної віртуалки легко згенерувати відповідний фрагмент конфігурації:

vagrant ssh-config --host vm01 > ~/.ssh/config.d/vm01

На відміну від команди vagrant ssh, ця конфігурація працюватиме також і з scp, rsync і так далі.

Мікро-некро-тред у Твітері (2018).