Вчера многие обратили внимание на конструкцию в nginx:
Что это блядь за «чёрточка» вместо сервер_нейма?
ㅤ
Если техническим языком — это подстановочное имя хоста.
Пусть на сервере прописано так:
Если в браузере откроем
А как получить 444, тот самый с «чёрточкой»?
Просто! Например, зайти на сервер по его IP адресу. Nginx не сможет сопоставить доменные имена, которые прописаны в конфиге и отдаст статус 444.
То есть «чёрточка» это что-то типа заглушки. Nginx не воспринимает его как специальный символ, это обычное имя хоста, которое можно использовать для обработки запросов, не соответствующих другим явно указанным доменам.
Обычно эту «чёрточку» прописывают в файле defaults, чтобы тем, кто попал на сервер по IP адресу увидел, то что ты захочешь, а не рандомный сайт который у тебя висит на сервере.
Короче если запрос приходит с именем хоста, которое не совпадает ни с одним из явно прописанных
А в сочетании с
Если «чёрточка» не используется, то вместо неё можно просто прописать
Вот так вот и живём, изучай!
tags: #nginx #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgate
server_name _;
Что это блядь за «чёрточка» вместо сервер_нейма?
ㅤ
Если техническим языком — это подстановочное имя хоста.
Пусть на сервере прописано так:
server {
listen 80;
server_name _;
return 444;
}
server {
listen 80;
server_name bashdays.ru;
return 200;
}
server {
listen 80;
server_name linuxfactory.ru;
return 200;
}Если в браузере откроем
bashdays.ru или linuxfactory.ru, то получим статус 200.А как получить 444, тот самый с «чёрточкой»?
Просто! Например, зайти на сервер по его IP адресу. Nginx не сможет сопоставить доменные имена, которые прописаны в конфиге и отдаст статус 444.
То есть «чёрточка» это что-то типа заглушки. Nginx не воспринимает его как специальный символ, это обычное имя хоста, которое можно использовать для обработки запросов, не соответствующих другим явно указанным доменам.
Обычно эту «чёрточку» прописывают в файле defaults, чтобы тем, кто попал на сервер по IP адресу увидел, то что ты захочешь, а не рандомный сайт который у тебя висит на сервере.
Короче если запрос приходит с именем хоста, которое не совпадает ни с одним из явно прописанных
server_name, то он будет обрабатываться этим серверным блоком.А в сочетании с
return 444 (No Response) используется для закрытия нежелательных запросов или для обработки некорректных запросов.Если «чёрточка» не используется, то вместо неё можно просто прописать
default_server в директиве listen, и блок будет работать аналогично.server {
listen 80 default_server;
return 444;
}Символ _ не имеет специального значения в самом Nginx. Это просто удобное соглашение, принятое сообществом.
Вот так вот и живём, изучай!
tags: #nginx #devops #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 80
Сегодня будем запирать врата ада.
ㅤ
Ситуация: Есть физический сервер, на нём торчит само собой Linux, к нему подключен монитор и кнопки. Короче можно физически подойти к этой машине и ввести логин/пароль.
Ну или при желании понажимать
Надеюсь ты понял о чем я тебе говорю. Ну дак вот!
Задача: Нужно запретить физический вход по логину/паролю, но оставить вход по ssh с ключами.
Как настраивать все эти ключи можешь почитать в серии постов по тэгу: #linuxfactory
Давай теперь отключим физический доступ к tty.
Заходим на сервер и смотрим юниты
В ответ получаем список активных tty
Теперь запускаем команды:
Всё! Песда! Терминал становится черным, интерактивность потеряна.
Пробуем понажимать
Перезагружаем сервер и НИЧЕГО! Черная дыра! Пробуем подключиться к серверу по ssh — ХА! Работает сучка!
Теперь даже имея физический доступ к серверу, ты нихуя с ним сделать не сможешь. Максимум загрузиться в Recovery mode и починить:
Вот такие приколюхи! Как и где это применять решай сам. Развлекайся.
tags: #linux #devops
—
🔔 @bashdays➡️ @gitgate
ㅤ
Ситуация: Есть физический сервер, на нём торчит само собой Linux, к нему подключен монитор и кнопки. Короче можно физически подойти к этой машине и ввести логин/пароль.
Ну или при желании понажимать
ALT+F1, F2, F3 (чтобы переключать tty).Надеюсь ты понял о чем я тебе говорю. Ну дак вот!
Задача: Нужно запретить физический вход по логину/паролю, но оставить вход по ssh с ключами.
Как настраивать все эти ключи можешь почитать в серии постов по тэгу: #linuxfactory
Давай теперь отключим физический доступ к tty.
Заходим на сервер и смотрим юниты
systemctl list-units | grep getty
В ответ получаем список активных tty
getty@tty1.service
getty@tty2.service
getty@tty3.service
getty@tty4.service
getty (сокращение от get tty) — это программа в Linux и Unix-подобных системах, которая отвечает за управление терминалами и логин-процессом для пользователей, подключающихся к системе через консоль.
Теперь запускаем команды:
systemctl disable getty@tty{1..10}.service
systemctl stop getty@tty{1..10}.serviceВсё! Песда! Терминал становится черным, интерактивность потеряна.
Пробуем понажимать
ALT+F1, F2, F3 — хуй там плавал!Перезагружаем сервер и НИЧЕГО! Черная дыра! Пробуем подключиться к серверу по ssh — ХА! Работает сучка!
При отключении getty для терминалов tty1–tty10, это не повлияет на SSH-доступ, так как SSH-сервер работает независимо от getty.
Теперь даже имея физический доступ к серверу, ты нихуя с ним сделать не сможешь. Максимум загрузиться в Recovery mode и починить:
sudo mount /dev/sdXn /mnt
sudo chroot /mnt
sudo systemctl enable getty@tty{1..10}.service
sudo systemctl start getty@tty{1..10}.service
Вот такие приколюхи! Как и где это применять решай сам. Развлекайся.
Про Magic SysRq в Linux писал тут.
Чем терминал отличается от консоли писал тут
tags: #linux #devops
—
Please open Telegram to view this post
VIEW IN TELEGRAM
10 97
Использовать ssh ключи очень удобно, при условии если у тебя в наличии 2-5-10 серверов
А как жить в ситуации когда у тебя 100500 серверов и еще 100500 пользователей?
ㅤ
Этож нужно за всем этим следить, обновлять и отзывать неактуальны (проёбанные) ключи. Всё скатывается в ужасную рутину.
Да, можно поднять какой-нибудь бастион и через него всем этим рулить, либо упороться с ансиблом и т.п.
Но чтобы не морочиться со всей этой хуйней, у тебя всё это есть и установлено из коробки. Вариант не совсем простой, легко запутаться, но если разобраться то качнешь свой скилл.
Центр сертификации (CA).
Работает он так:
1. Ты настраиваешь CA которому доверяют все твои 100500 серверов.
2. Сертификат подписывает ключи пользователей с указанием сроков действия и ограничений.
3. Если сотрудник покидает команду, ты просто отзываешь сертификат, а не удаляешь ключи с каждого сервера.
Давай замутим:
Берем какуюнить линукс машину и делаем из него CA.
По итогу получаем 2 ключа,
Дальше чтобы сервера могли доверять сертификатам, подписанным нашим CA, добавляем публичный ключ CA (
Покажу в рамках одного сервера:
Теперь заходим на этот самый сервер куда ты скопировал публичную часть ключа.
Открываем конфиг
И пишем в него:
Не забываем хуйнуть:
Теперь сервер будет доверять сертификатам подписанным CA.
Ну а чтобы пользователь мог подключаться по сертификату, подписываем его публичный ключ с помощью CA.
Для этого копируем на CA машину свой локальный публичный ключ. Тот что у тебя на машине лежит и который ты прописывал ранее в
Подписываем публичный ключ и превращаем его в сертификат.
В ответ получаем нечто такое:
И в папке
➡️ Важно. При подписании ключа, указывай валидного юзера под которым будешь подключаться, иначе нарвешься на ошибку:
Забираем себе на локальную машину подписанный ключ и пробуем подключиться:
Вуаля, я залетаю на сервер с подписанным ssh ключом, а на удаленном сервере вижу в логах:
И да, на удаленном сервере можно снести файл
Ну а теперь давай отзовем сертификат с ключа
На сервере к которому ты настраивал подключение:
В файле
Добавляем серт в этот файл с отзывами:
Всё, теперь если попробуем подключиться к серверу, нас пошлют нахуй.
Выглядит все это конечно пиздец крипово, но при правильной автоматизации этого процесса у тебя получится достаточно гибкий инструмент.
Завтра про Vault Hashicorp расскажу, в нем все проще делается
tags: #linux #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgate
А как жить в ситуации когда у тебя 100500 серверов и еще 100500 пользователей?
ㅤ
Этож нужно за всем этим следить, обновлять и отзывать неактуальны (проёбанные) ключи. Всё скатывается в ужасную рутину.
Да, можно поднять какой-нибудь бастион и через него всем этим рулить, либо упороться с ансиблом и т.п.
Но чтобы не морочиться со всей этой хуйней, у тебя всё это есть и установлено из коробки. Вариант не совсем простой, легко запутаться, но если разобраться то качнешь свой скилл.
Центр сертификации (CA).
Работает он так:
1. Ты настраиваешь CA которому доверяют все твои 100500 серверов.
2. Сертификат подписывает ключи пользователей с указанием сроков действия и ограничений.
3. Если сотрудник покидает команду, ты просто отзываешь сертификат, а не удаляешь ключи с каждого сервера.
Давай замутим:
Берем какуюнить линукс машину и делаем из него CA.
ssh-keygen -t rsa -b 4096 -f ~/.ssh/ssh_ca -C "SSH Certificate Authority"
Описывать за что отвечают параметры не буду, всё это уже разжевали, читай посты по тегу #linuxfactory
По итогу получаем 2 ключа,
ssh_ca (приватный) и ssh_ca.pub (публичный).Дальше чтобы сервера могли доверять сертификатам, подписанным нашим CA, добавляем публичный ключ CA (
ssh_ca.pub) на все 100500 серверов.Тут уже сам автоматику организуй, либо баш скриптом, либо ансибл ролью либо еще как-то. Попробуй ради интереса изобрести своё решение.
Покажу в рамках одного сервера:
scp ~/.ssh/ssh_ca.pub user@bashdays:/etc/ssh/
Теперь заходим на этот самый сервер куда ты скопировал публичную часть ключа.
Открываем конфиг
/etc/ssh/sshd_configИ пишем в него:
TrustedUserCAKeys /etc/ssh/ssh_ca.pub
Не забываем хуйнуть:
sudo systemctl restart ssh
Теперь сервер будет доверять сертификатам подписанным CA.
Ну а чтобы пользователь мог подключаться по сертификату, подписываем его публичный ключ с помощью CA.
Для этого копируем на CA машину свой локальный публичный ключ. Тот что у тебя на машине лежит и который ты прописывал ранее в
authorized_keys на удаленных серверах.Подписываем публичный ключ и превращаем его в сертификат.
ssh-keygen -s ~/.ssh/ssh_ca -I "user_cert" -n user -V +1w /tmp/user_key.pub
В ответ получаем нечто такое:
Signed user key /tmp/user_key-cert.pub: id "user_cert" serial 0 for username valid from 2025-02-16T12:02:00 to 2025-02-23T12:02:59
И в папке
/tmp появляется файл user_key-cert.puberror: Certificate invalid: name is not a listed principal
Забираем себе на локальную машину подписанный ключ и пробуем подключиться:
ssh -i ~/.ssh/id_rsa -o CertificateFile=~/.ssh/user_key-cert.pub root@bashdays.com
Вуаля, я залетаю на сервер с подписанным ssh ключом, а на удаленном сервере вижу в логах:
2025-02-16 sshd[958704]: Accepted publickey for root from 11.11.11.11 port 35528 ssh2: RSA-CERT SHA256:Q4SKZ5cRycm79w0SyvRhAQR8 ID user_cert (serial 0) CA RSA SHA256:PtNBUw/+4/gGz4rc/ybu/uNHngcI
Если что-то не получается или не даёт зайти, пиздуешь на сервер к которому подключается и смотришь логи var/logs/auth.log. В этом файле тебе очень информативно подскажут что погуглить.
И да, на удаленном сервере можно снести файл
~/.ssh/authorized_keys от тебе больше не пригодится. Потому что сервак начинает доверять всем ключам, которые подписаны через CA.Ну а теперь давай отзовем сертификат с ключа
На сервере к которому ты настраивал подключение:
touch /etc/ssh/revoked_certs
В файле
/etc/ssh/sshd_config добавляем:RevokedKeys /etc/ssh/revoked_certs
Добавляем серт в этот файл с отзывами:
ssh-keygen -k -f /etc/ssh/revoked_certs -z 1 user_key-cert.pub
Всё, теперь если попробуем подключиться к серверу, нас пошлют нахуй.
Выглядит все это конечно пиздец крипово, но при правильной автоматизации этого процесса у тебя получится достаточно гибкий инструмент.
Завтра про Vault Hashicorp расскажу, в нем все проще делается
tags: #linux #devops #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
2 118
Здрасти, сегодня продолжаем издеваться над ssh.
Давай прикрутим 2FA.
ㅤ
Идем на сервер к которому хотим подключmся по ssh и ставим пакеты:
Запускаем конфигуратор:
Я запускаю под рутом, но если тебе нужно настроить 2FA для другого юзера, для начала переключись на этого пользователя и только потом запускай конфигуратор.
После запуска конфигуратора, получишьпо ебалу:
Тут поди сам разберешься чо нажимать. В ответ тебе выплюнут QR код, ссылку и секретный ключ.
Можно еще всякие ключики использовать:
Если интересно:
Всю эту инфу куданить себе скопируй чтоб не проебаться.
Дальше сканируем этот QR код, либо берем секретный ключ который он тебе выплюнул и вставляем в vaultwarden в TOTP или на телефоне в апку добавляем.
Тот самый секретный ключ:
В общем нужно получить шестизначный код, вернуться в терминал (где ты запускал конфигуратор) и вставить его. Логика аналогична подключению 2FA в любых сервисах.
После этого оно выплюнет тебе рекавери коды, ну и спросит:
На всё соглашаешься, но если хочешь, можешь прочитать и тонко затюнить под свои задачи.
В файл
Теперь открываем файл
И добавляем в него строчку:
По необходимости комментим common-auth если ничего не работает. Есть вариант не комментить, но тогда нужно правильно настроить common-auth, но у нас сегодня не про это.
Закомментировав этот модуль ты отключаешь стандартные механизмы аутентификации и даешь зеленый свет на использование pam_google_authenticator.
Тут аккуратнее, можешь себе в ногу выстрелить. Сначала все проверяем и только потом закрываем терминал с активной сессий.
Дальше добавляем в конфиг:
Вот и всё, настройка 2FA завершена.
Рестартим:
И пробуем подключиться по ssh к этому серверу:
Ха! А что вводить? Это и есть 2FA, сюда вводим одноразовый код который выплюнул тебе vaultwarden либо аппка на телефоне.
Всё! Залетаем спокойно на сервер. Без кода и ключа хуй ты теперь чо сделаешь.
Как использовать резервные коды?
Да также при запросе в Verification code. НО из файла
Также можешь включать 2FA для конкретных пользователей, в конфиге
Настроек там жопой кушай, я тебе лишь концепт показал как эту хуйню можно быстренько настроить.
Главное не спеши и делай всё вдумчиво, чтобы не проебать доступ к серверу. Ну а если все проебал, да и хуй с ним, ебани кофейка и мультики посмотри.
tags: #linux #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgate
Давай прикрутим 2FA.
ㅤ
Идем на сервер к которому хотим подключmся по ssh и ставим пакеты:
sudo apt update
sudo apt install libpam-google-authenticator
Запускаем конфигуратор:
google-authenticator
Я запускаю под рутом, но если тебе нужно настроить 2FA для другого юзера, для начала переключись на этого пользователя и только потом запускай конфигуратор.
После запуска конфигуратора, получишь
Do you want authentication tokens to be time-based (y/n)
Тут поди сам разберешься чо нажимать. В ответ тебе выплюнут QR код, ссылку и секретный ключ.
Можно еще всякие ключики использовать:
google-authenticator -t -f -d -w 3 -e 5 -r 3 -R 60
Если интересно:
google-authenticator --helpВсю эту инфу куданить себе скопируй чтоб не проебаться.
Дальше сканируем этот QR код, либо берем секретный ключ который он тебе выплюнул и вставляем в vaultwarden в TOTP или на телефоне в апку добавляем.
Тот самый секретный ключ:
Your new secret key is: MAIY4KDCXKWHPDCI
В общем нужно получить шестизначный код, вернуться в терминал (где ты запускал конфигуратор) и вставить его. Логика аналогична подключению 2FA в любых сервисах.
После этого оно выплюнет тебе рекавери коды, ну и спросит:
Do you want me to update your "/root/.google_authenticator" file?
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks
и другие
На всё соглашаешься, но если хочешь, можешь прочитать и тонко затюнить под свои задачи.
В файл
/root/.google_authenticator сохранится секретный ключ и коды восстановления. Этот файл не трогаем, без него тоже нихуя не заработает.Теперь открываем файл
/etc/pam.d/sshdИ добавляем в него строчку:
# @include common-auth
auth required pam_google_authenticator.so
По необходимости комментим common-auth если ничего не работает. Есть вариант не комментить, но тогда нужно правильно настроить common-auth, но у нас сегодня не про это.
Закомментировав этот модуль ты отключаешь стандартные механизмы аутентификации и даешь зеленый свет на использование pam_google_authenticator.
Тут аккуратнее, можешь себе в ногу выстрелить. Сначала все проверяем и только потом закрываем терминал с активной сессий.
Дальше добавляем в конфиг:
/etc/ssh/sshd_configUsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
PubkeyAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
Вот и всё, настройка 2FA завершена.
Рестартим:
sudo systemctl restart ssh
И пробуем подключиться по ssh к этому серверу:
ssh root@bashdays.ru
(root@bashdays.ru) Verification code:
Ха! А что вводить? Это и есть 2FA, сюда вводим одноразовый код который выплюнул тебе vaultwarden либо аппка на телефоне.
Всё! Залетаем спокойно на сервер. Без кода и ключа хуй ты теперь чо сделаешь.
Как использовать резервные коды?
Да также при запросе в Verification code. НО из файла
/root/.google_authenticator они будут отлетать. Тут тоже аккуратнее.Также можешь включать 2FA для конкретных пользователей, в конфиге
/etc/ssh/sshd_configMatch User <имя юзера>
AuthenticationMethods publickey,keyboard-interactive
Настроек там жопой кушай, я тебе лишь концепт показал как эту хуйню можно быстренько настроить.
А как работать с 2FA и QR кодами из консоли, можешь почитать тут.
Главное не спеши и делай всё вдумчиво, чтобы не проебать доступ к серверу. Ну а если все проебал, да и хуй с ним, ебани кофейка и мультики посмотри.
tags: #linux #devops #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Что делать если я проебал приватный ssh ключ?
Самое главное не ссать!
Если ты рядовой разработчик/qa/cto/шлюха, напиши своему девопс инженеру чтобы прописал новый публичный ключик.
Это нужно сделать обязательно через таску никаких блядь личек. Чтобы потом можно было прикрыть свою жопу и всё свалить на безответственных сотрудников, которые штаны просиживают и блокируют работу команды.
Пусть знают с кем связались — бабуины прямоходящие! 🙈
Тебя конечно же проклянут, но спустя какое-то время ключик пропишут. Доступ к серверам восстановлен. Профит чо!
Это прям идеальный исход событий.
Но если ты и есть девопс инженер да еще и один единственный в команде, то у тебя бааальшие проблемы!
Пеню, все решаемо, напомню — не ссать!
Варианты решения:
➡️ Вариант №1
Если ты осел и у тебя все еще включен доступ по паролю, то зайди на сервер по паролю. Но в 99999999% ты пароль не записал, либо просто его не знаешь/проебал.
Но опять же решаемо, если у тебя есть доступ в панель управления серверами, ты можешь в пару кликов через веб-морду провайдера задать новый пароль.
У Селектела и AEZA такая возможность есть.
Но с этим паролем ты сможешь войти только через KVM, то есть опять же через веб морду. Потому что если ты в ssh конфиге (на сервере) отключил вход по паролю, то через
Через KVM сразу можешь отредачить ssh конфиг и включить доступ по паролю, потом комфортно подключиться к серверу так
Это самый трушный вариант, но работает не всегда + иногда требуется перезагрузка сервера, а это не допустимо.
➡️ Вариант №2
Если у тебя есть какие-то другие доступы к серверу, например у тебя там поднят IPMI, VNC.
Тут все просто, заходим, прописываем новые ключики, меняем конфиги, восстанавливаем доступы.
➡️ Вариант №3
Вспомни, возможно у тебя есть другой юзер который прописан в sudoers, не обязательно это может быть твой второй юзер. Возможно ты выдавал доступы разработчикам и т.п. Обратись к ним, если ты не мудак они зайдут на сервер и починят тебя. Но если ты мудак — поехали дальше.
➡️ Вариант №4
У многих две рабочих машины, у меня например основной писюк где я видосы для девопсины клепаю и параллельно решаю вопросы по ssh. Соответственно на писюке у меня есть приватный ключ.
Но также у меня есть и ноут (нет, не в тот что кот насрал), на ноуте я обычно работаю в сортире и созваниваюсь в постельке. На ноуте у меня тоже есть этот приватный ключик.
А еще у меня есть внешний диск, когда с ноута на ноут переезжал то бекапы делал, там тоже этот приватный ключик наверняка лежит.
Суть такая — найти бекап этого ключа, всяко он у тебя где-то продублирован. Выйди на солнышко/снег/дождик, покури, подумай. бекапы порой делаются не осознанно.
➡️ Вариант №5
Рекавери режим. Нужен физический доступ к серверу, загружаешься, монтируешь диск, меняешь конфиги, прописываешь новые ключи.
Физический доступ к сервакам обычно редкость, но опять же в Селектеле я такое делал много раз через веб-морду, там прям есть пунктик — Rescue Mode. Про аезу не скажу (аеза нас читает, пусть прокомментирует), пока не приходилось с этим сталкиваться.
Минус — придется перезагружать сервер. Будет даун тайм и тебя за это очень быстро выебут (если это какойнить прод).
➡️ Вариант №6
У тебя есть какойнить Ansible который хуячит под крылом AWX, у ансибла нативный рут, либо юзер который может сделать become и выполнить таски от рута. Это прям облегчает задачу. Не нужно перезагружать сервак, прогнал плейбук и был таков.
🙃 Если хочешь проникнуться Ансиблом/Гитлабом/Докером — велком в наш пантеон.
➡️ Вариант №7
➡️ А это твой вариант, напиши про него в комменты.
Я бы мог еще продолжать, но у телеги лимиты на количество символов. Так что пошли в комменты, попиздим и найдем серебряную пульку.
Спасибо за внимание и хороших предстоящих выходных!
tags: #рабочиебудни #linux
—
🔔 @bashdays➡️ @gitgate
Самое главное не ссать!
Если ты рядовой разработчик/qa/cto/шлюха, напиши своему девопс инженеру чтобы прописал новый публичный ключик.
Это нужно сделать обязательно через таску никаких блядь личек. Чтобы потом можно было прикрыть свою жопу и всё свалить на безответственных сотрудников, которые штаны просиживают и блокируют работу команды.
Пусть знают с кем связались — бабуины прямоходящие! 🙈
Человек как меч, либо делает свою работу либо тупой.
Тебя конечно же проклянут, но спустя какое-то время ключик пропишут. Доступ к серверам восстановлен. Профит чо!
Это прям идеальный исход событий.
Но если ты и есть девопс инженер да еще и один единственный в команде, то у тебя бааальшие проблемы!
Пеню, все решаемо, напомню — не ссать!
Варианты решения:
Если ты осел и у тебя все еще включен доступ по паролю, то зайди на сервер по паролю. Но в 99999999% ты пароль не записал, либо просто его не знаешь/проебал.
Но опять же решаемо, если у тебя есть доступ в панель управления серверами, ты можешь в пару кликов через веб-морду провайдера задать новый пароль.
У Селектела и AEZA такая возможность есть.
Но с этим паролем ты сможешь войти только через KVM, то есть опять же через веб морду. Потому что если ты в ssh конфиге (на сервере) отключил вход по паролю, то через
ssh root@server у тебя нихуя не выйдет.Через KVM сразу можешь отредачить ssh конфиг и включить доступ по паролю, потом комфортно подключиться к серверу так
ssh root@server и добавить свои новые ключики.Это самый трушный вариант, но работает не всегда + иногда требуется перезагрузка сервера, а это не допустимо.
Про ssh ключи, конфиги и прочее читай по тегу #linuxfactory
Если у тебя есть какие-то другие доступы к серверу, например у тебя там поднят IPMI, VNC.
Тут все просто, заходим, прописываем новые ключики, меняем конфиги, восстанавливаем доступы.
Вспомни, возможно у тебя есть другой юзер который прописан в sudoers, не обязательно это может быть твой второй юзер. Возможно ты выдавал доступы разработчикам и т.п. Обратись к ним, если ты не мудак они зайдут на сервер и починят тебя. Но если ты мудак — поехали дальше.
У многих две рабочих машины, у меня например основной писюк где я видосы для девопсины клепаю и параллельно решаю вопросы по ssh. Соответственно на писюке у меня есть приватный ключ.
Но также у меня есть и ноут (нет, не в тот что кот насрал), на ноуте я обычно работаю в сортире и созваниваюсь в постельке. На ноуте у меня тоже есть этот приватный ключик.
А еще у меня есть внешний диск, когда с ноута на ноут переезжал то бекапы делал, там тоже этот приватный ключик наверняка лежит.
Суть такая — найти бекап этого ключа, всяко он у тебя где-то продублирован. Выйди на солнышко/снег/дождик, покури, подумай. бекапы порой делаются не осознанно.
Рекавери режим. Нужен физический доступ к серверу, загружаешься, монтируешь диск, меняешь конфиги, прописываешь новые ключи.
Физический доступ к сервакам обычно редкость, но опять же в Селектеле я такое делал много раз через веб-морду, там прям есть пунктик — Rescue Mode. Про аезу не скажу (аеза нас читает, пусть прокомментирует), пока не приходилось с этим сталкиваться.
Минус — придется перезагружать сервер. Будет даун тайм и тебя за это очень быстро выебут (если это какойнить прод).
У тебя есть какойнить Ansible который хуячит под крылом AWX, у ансибла нативный рут, либо юзер который может сделать become и выполнить таски от рута. Это прям облегчает задачу. Не нужно перезагружать сервак, прогнал плейбук и был таков.
Как говорится — Хуем в ладошку и вперёд в путь дорожку!
Я бы мог еще продолжать, но у телеги лимиты на количество символов. Так что пошли в комменты, попиздим и найдем серебряную пульку.
Спасибо за внимание и хороших предстоящих выходных!
tags: #рабочиебудни #linux
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Такс, как и обещал притаранил тебе рабочий пайплайн для авто деплоя
ㅤ
Чтобы всё это заработало, в проекте тебе нужно создать структуру:
Файл можешь обозвать как угодно.
Давай пробежимся:
Триггер
Следом запускается джоба
Дальше используем адаптированный контейнер с убунтой 22.04 специально адаптированный под тестирование GitHub Actions через
Почему GitHub Actions? Потому что
Пиздеть не буду, не переносил, но если у тебя есть опыт, то было бы интересно увидеть его в комментариях.
Потом идут шаги
После сборки идет секция с деплоем, я использую этот экшен. Основан он на
Забиваем нужные ключи и переменные, которые требуются для работы этого экшена. Переменные определяешь в настройках проекта в
SSH_PRIVATE_KEY = Приватный ssh ключ с которым раннер пойдет на твой сервер и подключиться по ssh к нему. Соответственно публичная часть ключа должна быть прописана у пользователя на сервере в файле
ARGS = Аргументы для
SOURCE = Какой каталог со статикой отправляем. В
REMOTE_HOST & REMOTE_USER = Айпишник или домен продакшена на который деплоим + имя пользователя под которым подключаемся к серверу.
TARGET = В какую папку на проде скинуть содержимое папки
Параметров в экшене гораздо больше, у меня приведен необходимый минимум. Про все ключи и свистоперделки этого экшена можешь почитать тут.
Вот и всё. Теперь при пуше в
В моем случае выкатываются новые посты в
Короче хорошего тебе вечера, теперь уже до завтра!
tags: #devops #cicd
—
🔔 @bashdays➡️ @gitgate
mkdocs через gitea.ㅤ
Чтобы всё это заработало, в проекте тебе нужно создать структуру:
.gitea/workflows/deploy.yml
Файл можешь обозвать как угодно.
name: Build and Deploy Bashdays Blog
on:
push:
branches:
- main
jobs:
build:
runs-on: super-runner
container:
image: catthehacker/ubuntu:act-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install dependencies and build
run: |
pip install -r requirements.txt
mkdocs build
- name: Deploy to Server
uses: https://gitea.com/aquelle1/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-rlgoDzvc -i --delete"
SOURCE: "site/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
TARGET: ${{ secrets.REMOTE_TARGET }}
Давай пробежимся:
Триггер
on: push: запускается если что-то запушено в ветку main. Почему в main а не в master? Читай тут.
Следом запускается джоба
build на раннере super-runner, не забываем зарегать себе раннер, без него нихуя не получится.Что такое раннеры и как с ними работать, можешь загуглить, там по сути ничего сложного. Поэтому этот этап пропущу. Чуть позже отдельным постом запилю про это.
Дальше используем адаптированный контейнер с убунтой 22.04 специально адаптированный под тестирование GitHub Actions через
act.Почему GitHub Actions? Потому что
gitea унаследовало синтаксис и пайплайны в теории могут переносится между системами.Пиздеть не буду, не переносил, но если у тебя есть опыт, то было бы интересно увидеть его в комментариях.
Потом идут шаги
speps, клонируется репозиторий с проектом в контейнер, устанавливаются необходимые зависимости через «пипку», ну и билдится финальная статика.После сборки идет секция с деплоем, я использую этот экшен. Основан он на
rsync поверх ssh.Забиваем нужные ключи и переменные, которые требуются для работы этого экшена. Переменные определяешь в настройках проекта в
gitea в секции secrets.SSH_PRIVATE_KEY = Приватный ssh ключ с которым раннер пойдет на твой сервер и подключиться по ssh к нему. Соответственно публичная часть ключа должна быть прописана у пользователя на сервере в файле
~/.ssh/authorized_keys.Как работать с ssh ключами, читай по тегу #linuxfactory
ARGS = Аргументы для
rsync, рекурсивное копирование, сохранение прав доступа, удаление файлов которые не в локальной версии.SOURCE = Какой каталог со статикой отправляем. В
Mkdocs статика генерится по умолчанию в папку site.REMOTE_HOST & REMOTE_USER = Айпишник или домен продакшена на который деплоим + имя пользователя под которым подключаемся к серверу.
TARGET = В какую папку на проде скинуть содержимое папки
site.Параметров в экшене гораздо больше, у меня приведен необходимый минимум. Про все ключи и свистоперделки этого экшена можешь почитать тут.
Вот и всё. Теперь при пуше в
main ветку, автоматически запустится пайплайн и на прод выкатятся изменения.В моем случае выкатываются новые посты в
markdown. Этот процесс хочу автоматизировать и продублировать все посты из этого канала в блог, сделать наконец нормальную навигацию и поиск. А то чёрт ногу сломит уже, хуй чё найдешь. Но это пока только мечты, мечты...Короче хорошего тебе вечера, теперь уже до завтра!
tags: #devops #cicd
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Как из РФ создать новую учётку в Gitlab
У ребят в Linux Factory довольно часто возникает вопрос — а как зарегистрировать новую учетку в Gitlab?
ㅤ
Онож там и карту просит и смс и еще хуй пойми чего.
Вариантов есть много, но работают они 50 на 50. У кого-то работает одно, у кого-то другое, но нет золотой середины.
Сейчас я покажу 100% рабочий вариант.
Регистрируешься в Putsbox. Это сервис для временных почтовых ящиков. Проверен лично мной годами, никогда не косячит.
Тут важно зарегистрироваться, а не просто создать новый ящик.
Это важно, потому что Gitlab рано или поздно снова запросит подтвердить твою личность и отправит код на почту. А если ты не порегаешься в putsbox, то ящика того самого не будет.
Короче регаешься в putsbox, входишь в учетку и создаешь почтовый ящик.
Дальше скачиваешь себе TOR Browser и регаешься в Gitlab на ящик который создал в ранее. Проходишь капчу, челенджи с количеством камней и т.п. Да, будет подтормаживать, но за пару минут управишься.
После регистрации на ящик в putsbox приходит код с подтверждением, подтверждаешь. Закрываешь TOR Browser.
Идешь в свой браузер и без проблем залетаешь в Gitlab под новой учёткой.
Без карт, смс и прочей хуиты. Если в будущем оно попросит тебя снова подтвердить личность, идешь в старый ящик putxbox и подтверждаешь.
На самом деле всё просто. Единственный момент — TOR Browser, возможно сразу он у тебя не запустится, нужно будет поиграть с мостами либо заранее подключить VPN. Короче тут сам разберешься, это уже дело третье.
Такие дела, тыкай, изучай.
🛠 #linuxfactory #gitlab #services
—
✅ @bashdays / @linuxfactory / @blog
У ребят в Linux Factory довольно часто возникает вопрос — а как зарегистрировать новую учетку в Gitlab?
ㅤ
Онож там и карту просит и смс и еще хуй пойми чего.
Вариантов есть много, но работают они 50 на 50. У кого-то работает одно, у кого-то другое, но нет золотой середины.
Сейчас я покажу 100% рабочий вариант.
Регистрируешься в Putsbox. Это сервис для временных почтовых ящиков. Проверен лично мной годами, никогда не косячит.
Про этот сервис я как-то давненько рассказывал здесь.
Тут важно зарегистрироваться, а не просто создать новый ящик.
Это важно, потому что Gitlab рано или поздно снова запросит подтвердить твою личность и отправит код на почту. А если ты не порегаешься в putsbox, то ящика того самого не будет.
Короче регаешься в putsbox, входишь в учетку и создаешь почтовый ящик.
Дальше скачиваешь себе TOR Browser и регаешься в Gitlab на ящик который создал в ранее. Проходишь капчу, челенджи с количеством камней и т.п. Да, будет подтормаживать, но за пару минут управишься.
После регистрации на ящик в putsbox приходит код с подтверждением, подтверждаешь. Закрываешь TOR Browser.
Идешь в свой браузер и без проблем залетаешь в Gitlab под новой учёткой.
Без карт, смс и прочей хуиты. Если в будущем оно попросит тебя снова подтвердить личность, идешь в старый ящик putxbox и подтверждаешь.
А если запуск пайплайнов требуют верификации, то читаем этот пост.
На самом деле всё просто. Единственный момент — TOR Browser, возможно сразу он у тебя не запустится, нужно будет поиграть с мостами либо заранее подключить VPN. Короче тут сам разберешься, это уже дело третье.
Если такая ебатория не по тебе, можешь локально Gitlab воткнуть. В этом посте я по шагам показал как это сделать. И не нужно думать что эта тварь сильно прожорливая, под лабу хватит минимального конфига по железу.
Такие дела, тыкай, изучай.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 47
Очередные грабли. При клонировании Linux машин, клонированные машины получают по DHCP тот же IP адрес, что и донор. Возникает конфликт интересов.
ㅤ
Проблема распространенная, лечится довольно просто.
1. Меняем MAC адреса на клонах
2. Меняем machine-id на клонах
В первом случае всё просто, делается через морду VBox, либо через консольные команды:
Новый MAC адрес можешь сгенерить такой командой:
Во втором случае это файл
Удаляем и генерим новый
Перезапускаем виртуальную машину. DHCP выдаёт этой машине новый IP адрес, который не будет конфликтовать с донором.
Вот и вся наука. Пользуйся.
🛠 #linux #linuxfactory
—
✅ @bashdays / @linuxfactory / @blog
ㅤ
Проблема распространенная, лечится довольно просто.
1. Меняем MAC адреса на клонах
2. Меняем machine-id на клонах
В первом случае всё просто, делается через морду VBox, либо через консольные команды:
ip link
sudo ip link set dev eth0 down
sudo ip link set dev eth0 address 00:11:22:33:44:55
sudo ip link set dev eth0 up
Новый MAC адрес можешь сгенерить такой командой:
printf '02:%02x:%02x:%02x:%02x:%02x\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))
Во втором случае это файл
/etc/machine-id, в нем хранится уникальный идентификатор машины.ed76c4f179044828b51028aadf9f4981
Удаляем и генерим новый
machine-id:sudo rm /etc/machine-id sudo systemd-machine-id-setup
Перезапускаем виртуальную машину. DHCP выдаёт этой машине новый IP адрес, который не будет конфликтовать с донором.
Вот и вся наука. Пользуйся.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Распространенный случай в пайплайнах, как ребята пишут в LF:
То есть на каждую команду, создается отдельная SSH сессий. В большинстве случаев у тебя всё будет работать, но порой можно наступить на грабли.
ㅤ
На сервере может быть установлены лимиты в
И по итогу пайплайн будет вечно делать хуйню, внезапно падать и т.п.
Что делать?
Передать команды в рамках одной сессии.
Например, так:
Либо пропихать так:
Но предпочтительнее первый вариант, он консистентный и более читаемый.
Учись сразу делать нормально и учитывать такие моменты.
Ну и с праздником тебя и твоих ребятишек!
🛠 #devops #linuxfactory #cicd
—
✅ @bashdays / @linuxfactory / @blog
deploy:
stage: deploy
script:
- ssh ${USER}@${HOST} "docker pull"
- ssh ${USER}@${HOST} "docker down"
- ssh ${USER}@${HOST} "docker up -d"
- ssh ${USER}@${HOST} "....."
🔥 Как и обещал. С сегодняшнего дня в Linux Factory действуют летние скидки. Кто ждал, велком.
То есть на каждую команду, создается отдельная SSH сессий. В большинстве случаев у тебя всё будет работать, но порой можно наступить на грабли.
ㅤ
На сервере может быть установлены лимиты в
ssh_config — MaxSessions, а плюсом еще работает Fail2ban или нечто подобное.И по итогу пайплайн будет вечно делать хуйню, внезапно падать и т.п.
Что делать?
Передать команды в рамках одной сессии.
Например, так:
script:
- |
ssh ${USER}@${HOST} << EOF
docker pull ...
docker down ...
docker up -d ...
...
EOF
В YAML, конструкция | перед блоком многострочного текста указывает, как обрабатывать переносы строк. | означает: сохраняй все переносы строк, как они написаны.
Либо пропихать так:
script:
- ssh ${USER}@${HOST} "docker pull ...; docker down ...; ..."
Но предпочтительнее первый вариант, он консистентный и более читаемый.
Учись сразу делать нормально и учитывать такие моменты.
Ну и с праздником тебя и твоих ребятишек!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
7 82
Довольно частый вопрос с LF — Как жить с gitlab раннерами?
Да просто там всё. Если у тебя основная инфра в кубе, то в кубе и крутим.
ㅤ
Ну а если ламповые сервера, без всей этой кубовой хуйни, то вариантов не много.
Заводим себе отдельный сервер/сервера, чисто под раннеры. Заводим с учетом на то, что на этих серверах будут собираться докер образы. Со временем место будет забиваться.
Здесь важно раздуплить себе какой-нибудь гарбаж коллектор, либо башник в крону накидать.
Подняли сервер, нарегали нужных раннеров. В идеале это процесс автоматизировать, ансибл-хуянсибл ну или чё там у тебя есть.
Раннеры можно зарегать на один токен:
Сервер 1
Сервер 2
В морде гитлаба появятся 2 отдельных раннера, а далее гитлаб будет балансировать между ними. Также можешь указать одинаковые теги. Тут у нас все сводится в сторону масштабируемости.
Раннер 1
Раннер 2
В
Задание пойдет на тот раннер, который раньше освободится. Если оба свободны — гитлаб рандомно сделает выбор, приоритетности нет.
Если важна приоритетность, можно поиграть в юните с параметром
А как деплоить?
Тоже всё просто,
Как-то так:
Подключаемся под юзером из переменной
Важно!
Если у тебя 100500 раннеров — ты с ними заебешься, поэтому на моменте регистрации, сделай себе табличку, пропиши в них теги раннеров и на каких серверах они у тебя живут. Опять же это можно сделать через ансибл-роль, либо скриптом генерить. Тут уже сам наколдуешь.
Основное рассказал, если что-то еще вспомню, накидаю. Если у тебя есть мысли, пиши в комментарии, будем обсуждать.
🛠 #devops #linuxfactory #cicd
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Да просто там всё. Если у тебя основная инфра в кубе, то в кубе и крутим.
ㅤ
Ну а если ламповые сервера, без всей этой кубовой хуйни, то вариантов не много.
Заводим себе отдельный сервер/сервера, чисто под раннеры. Заводим с учетом на то, что на этих серверах будут собираться докер образы. Со временем место будет забиваться.
Здесь важно раздуплить себе какой-нибудь гарбаж коллектор, либо башник в крону накидать.
Часто раннеры пихают прям на продакшен сервера, где крутятся все бизнес процессы. В этом случае продакшен превращается в помойку, нагрузка постоянно скачет при сборках/деплое и т.п.
Это хуёвая практика, на продакшене такого быть не должно. Лишь поэтому мы и поднимаем отдельный сервер под раннеры.
Подняли сервер, нарегали нужных раннеров. В идеале это процесс автоматизировать, ансибл-хуянсибл ну или чё там у тебя есть.
Раннеры можно зарегать на один токен:
Сервер 1
gitlab-runner register \
--url https://gitlab.com/ \
--registration-token ABCDEFG123456 \
--executor docker \
--description "runner-1"
Сервер 2
gitlab-runner register \
--url https://gitlab.com/ \
--registration-token ABCDEFG123456 \
--executor docker \
--description "runner-2"
В морде гитлаба появятся 2 отдельных раннера, а далее гитлаб будет балансировать между ними. Также можешь указать одинаковые теги. Тут у нас все сводится в сторону масштабируемости.
Раннер 1
--description "runner-fast"
--tag-list "docker"
Раннер 2
--description "runner-slow"
--tag-list "docker"
В
.gitlab-ci.yml у нас так:build:
script: echo "Building"
tags:
- docker
Задание пойдет на тот раннер, который раньше освободится. Если оба свободны — гитлаб рандомно сделает выбор, приоритетности нет.
Если важна приоритетность, можно поиграть в юните с параметром
GITLAB_RUNNER_PRIORITY.Короче если хочешь распределять нагрузку по раннерам с одинаковыми тегами, и раннера работают на разных машинах, просто регистрируй всех с одинаковыми тегами — гитлаб сам уже всё разрулит.
А как деплоить?
Тоже всё просто,
ssh/rsync в помощь, раннер подключается к нужному серверу, например по ssh и выполняет все необходимые команды. Затаскивает новый докер образ, стопорит старый, запускает новый.Как-то так:
deploy:
stage: deploy
script:
- |
ssh $SSH_USER@$SSH_HOST << EOF
docker pull $IMAGE_NAME
docker stop my_app || true
docker rm my_app || true
docker run -d -p 5000:5000 --name my_app $IMAGE_NAME
EOF
Подключаемся под юзером из переменной
$SSH_USER к хосту из переменной $SSH_HOST. Ну и запускаем команды.Важно!
Если у тебя 100500 раннеров — ты с ними заебешься, поэтому на моменте регистрации, сделай себе табличку, пропиши в них теги раннеров и на каких серверах они у тебя живут. Опять же это можно сделать через ансибл-роль, либо скриптом генерить. Тут уже сам наколдуешь.
Основное рассказал, если что-то еще вспомню, накидаю. Если у тебя есть мысли, пиши в комментарии, будем обсуждать.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
4 55
GIT для девопс-инженера
Многих git пугает разнообразием команд, но 99% его функционала тебе никогда не пригодится. Это как MS Word или Excel, где ты используешь ну от силы 0000.1% всего задуманного в нём.
ㅤ
Да, разработчикам посложнее, надо разруливать мердж-конфликты, делать какие-то ебаные черепики и ребейзы. Но для программистов на yml, достаточно основной базы.
Теорию по git опустим, ты и сам знаешь для чего оно всё нужно — для удобства.
К сути. Как я сказал выше, тебе достаточно базы:
К этому можно еще добавить
Как все работает в реальности
У тебя есть корпоративная учетка в гитлабе/гитхабе, там уже сто пудово созданы репы. Копируешь мышкой строку для клона, вставляешь себе в терминале.
ВСЁ! Репа у тебя на руках.
Создаешь новую ветку от мастера:
И уже в нее говнокодишь. Когда говна достаточно, комитишь, делаешь пулл-реквест (мердж-реквест). После того как тимлид заапрувит твой реквест, правки вольются в мастер. А ветку
Пункт с реквестами опять-же маловероятен, если компания не большая и ты там царь и бог девопса. Сразу хуяришь в мастер и никого не слушаешь. Отпадает необходимость создавать ветки и т.п. Ведь ты же всегда все делаешь идеально.
Я порой прям в гитлабе правлю через внутренний редактор, ебал я локально себе что-то клонировать. Быстрее через морду зайти и пайп подправить.
На этом можно и заканчивать, все элементарно. Не бойся гита, это хуйня не страшная. Если что-то пошло по пизде, удали, склонируй мастер и начни с чистого листа.
А как настроить ключи и т.п. я писал много постов, поищи по тегу #linuxfactory
А тут разбирали почему порой главная ветка называется
🛠 #git #devops
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Многих git пугает разнообразием команд, но 99% его функционала тебе никогда не пригодится. Это как MS Word или Excel, где ты используешь ну от силы 0000.1% всего задуманного в нём.
ㅤ
Да, разработчикам посложнее, надо разруливать мердж-конфликты, делать какие-то ебаные черепики и ребейзы. Но для программистов на yml, достаточно основной базы.
Стянул-закомитил-запушил. Не пушится? Похуй — push force!
Теорию по git опустим, ты и сам знаешь для чего оно всё нужно — для удобства.
Я к примеру в гите храню базу obsidian и совсем недавно это спасло все мои заметки. Я установил плагин для синка с seafile и оно мне нахуй всё стерло. У меня сука глаз выпал, овер 3к заметок проебало за секунду.
Но в гите у меня все это осталось, склонировал, восстановил. Бекап который однажды пригодился. Удобно.
К сути. Как я сказал выше, тебе достаточно базы:
git pull
git commit -m "ебал я вашу буравую, несите книжку трудовую"
git push
К этому можно еще добавить
clone, checkout и init, но этим ты будешь пользоваться очень редко.Как все работает в реальности
У тебя есть корпоративная учетка в гитлабе/гитхабе, там уже сто пудово созданы репы. Копируешь мышкой строку для клона, вставляешь себе в терминале.
git clone git@git.bashdays.ru:shubin/obsidian.git
ВСЁ! Репа у тебя на руках.
Создаешь новую ветку от мастера:
git checkout -b 010825
И уже в нее говнокодишь. Когда говна достаточно, комитишь, делаешь пулл-реквест (мердж-реквест). После того как тимлид заапрувит твой реквест, правки вольются в мастер. А ветку
010825 можно закрывать.Пункт с реквестами опять-же маловероятен, если компания не большая и ты там царь и бог девопса. Сразу хуяришь в мастер и никого не слушаешь. Отпадает необходимость создавать ветки и т.п. Ведь ты же всегда все делаешь идеально.
Я порой прям в гитлабе правлю через внутренний редактор, ебал я локально себе что-то клонировать. Быстрее через морду зайти и пайп подправить.
На этом можно и заканчивать, все элементарно. Не бойся гита, это хуйня не страшная. Если что-то пошло по пизде, удали, склонируй мастер и начни с чистого листа.
А как настроить ключи и т.п. я писал много постов, поищи по тегу #linuxfactory
А тут разбирали почему порой главная ветка называется
main а не master.—
Please open Telegram to view this post
VIEW IN TELEGRAM