Приветcвую вас, комрады!
🔤 🔤 🔥 🔤 🔤 🔤 🔤 🔤 🔤 🔤
Есть довольно редкоземельная но полезная утилитка, обзывается она - Crane
ㅤ
Примеры использования:
Копирование образа между реестрами (без необходимости их пулить себе).
Бывало у вас такое, что нужно перенести образ из одного реестра в другой?
С crane это делается на раз-два:
Эта команда скопирует образ
Просмотр содержимого образа:
Иногда хочется заглянуть внутрь образа и посмотреть, что там внутри.
С crane это проще простого:
Здесь мы экспортируем файловую систему образа executor и просматриваем список файлов с помощью команды tar.
Извлечение конкретного файла из образа:
Нужно достать нужный файл из образа? Легко!
Эта команда извлечет файл passwd из директории etc образа executor и выведет его содержимое.
Сравнение конфигураций двух версий образа:
Хотите узнать, чем отличаются конфигурации двух версий одного образа? Пожалуйста:
Здесь мы сравниваем конфигурации версий
Получение размера образа:
Интересно, сколько весит ваш образ? Вот как это узнать:
Эта команда выводит суммарный размер конфигурации и всех слоев образа.
Изменение меток и аннотаций образа:
Вы можете добавлять или изменять метки и аннотации в существующем образе без необходимости его повторной сборки:
Эта команда добавит или обновит аннотацию и метку в указанном образе.
Также можно доложить tarbar (архивы .tar .tar.gz .tgz), добавить тэг (удобнее чем в дефолтном докер клиенте), задать другой entrypoint и т.д.
И это ещё не всё)
Но это чем я пользую практически регулярно. + это 1 бинарь (на любимой многими GOшечке) что позволяет спокойно его использовать и в системах автосборки и упростить взаимодействие с контейнерам.
tags: #utilites #devops
—
🔔 @bashdays➡️ @gitgate
Есть довольно редкоземельная но полезная утилитка, обзывается она - Crane
ㅤ
Примеры использования:
Копирование образа между реестрами (без необходимости их пулить себе).
Бывало у вас такое, что нужно перенести образ из одного реестра в другой?
С crane это делается на раз-два:
crane cp gcr.io/shlyapa-project/executor:v1.7.0-debug myharbor.ru/shlyapa-executor:v1.7.0-debug
Эта команда скопирует образ
executor:v1.7.0-debug
из реестра gcr.io
в ваш собственный реджистри myharbor.ru.
Просмотр содержимого образа:
Иногда хочется заглянуть внутрь образа и посмотреть, что там внутри.
С crane это проще простого:
crane export executor - | tar -tvf - | less
Здесь мы экспортируем файловую систему образа executor и просматриваем список файлов с помощью команды tar.
Извлечение конкретного файла из образа:
Нужно достать нужный файл из образа? Легко!
crane export executor - | tar -Oxf - etc/passwd
Эта команда извлечет файл passwd из директории etc образа executor и выведет его содержимое.
Сравнение конфигураций двух версий образа:
Хотите узнать, чем отличаются конфигурации двух версий одного образа? Пожалуйста:
diff <(crane config front:1.32 | jq) <(crane config front:1.33 | jq)
Здесь мы сравниваем конфигурации версий
1.32
и 1.33
образа front с помощью утилиты diff.Получение размера образа:
Интересно, сколько весит ваш образ? Вот как это узнать:
crane manifest gcr.io/buildpacks/builder:v1 | jq '.config.size + ([.layers[].size] | add)'
Эта команда выводит суммарный размер конфигурации и всех слоев образа.
Изменение меток и аннотаций образа:
Вы можете добавлять или изменять метки и аннотации в существующем образе без необходимости его повторной сборки:
crane mutate myharbor.ru/shlyapa-project/bear_ass_image:tag --annotation "org.opencontainers.image.description=New description" --label "version=2.0"
Эта команда добавит или обновит аннотацию и метку в указанном образе.
Также можно доложить tarbar (архивы .tar .tar.gz .tgz), добавить тэг (удобнее чем в дефолтном докер клиенте), задать другой entrypoint и т.д.
И это ещё не всё)
Но это чем я пользую практически регулярно. + это 1 бинарь (на любимой многими GOшечке) что позволяет спокойно его использовать и в системах автосборки и упростить взаимодействие с контейнерам.
tags: #utilites #devops
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 45
Еще немного про отладку ssh ключей, но уже в контексте интеграции со всякими гитлабами/гитхабами.
ㅤ
Чтобы работать с приватными репами ты добавляешь в настройки гитлаба/гитхаба свою публичную часть ключа.
Хорошо если такой ключ один, запутаться особо негде.
Но что если добавлено 20-100 ключей?
Ты проверяешь, видишь в табличке «Заголовок» — gitlab-runner-1 и вроде всё хорошо, ключ прописан и в раннере его приватная часть есть. Чо за хуйня?
Тут нам и пригодится команда:
Выполняем ее для ключа с которым подключаемся (работает и для приватной и публичной части одинаково).
И по итогу видим фингерпринт, отпечаток:
Сравниваем этот отпечаток с тем что прописан в гитлабе/гитхабе и видим что он НЕ совпадает.
Фиксим и радуемся. Как фиксить? Прописать актуальную публичную часть ключа в гитлаб/гитхаб. Дело закрыто.
tags: #git #devops #ssh #linuxfactory
—
🔔 @bashdays➡️ @gitgate
ㅤ
Чтобы работать с приватными репами ты добавляешь в настройки гитлаба/гитхаба свою публичную часть ключа.
Хорошо если такой ключ один, запутаться особо негде.
Но что если добавлено 20-100 ключей?
Порой возникает ситуация, когда какой-нибудь раннер отказывается клонировать репу и начинает орать на доступы.
Ты проверяешь, видишь в табличке «Заголовок» — gitlab-runner-1 и вроде всё хорошо, ключ прописан и в раннере его приватная часть есть. Чо за хуйня?
Тут нам и пригодится команда:
ssh-keygen -l -E md5 -f ~/.ssh/id_rsa
Выполняем ее для ключа с которым подключаемся (работает и для приватной и публичной части одинаково).
И по итогу видим фингерпринт, отпечаток:
2048 MD5:03:62:23:ca:ce:1b:8c:ad:60:1f:66:16:05:43:d8:a7 shuba@server (RSA)
Сравниваем этот отпечаток с тем что прописан в гитлабе/гитхабе и видим что он НЕ совпадает.
А это значит что твой раннер использует не тот приватный ключ для подключения.
Фиксим и радуемся. Как фиксить? Прописать актуальную публичную часть ключа в гитлаб/гитхаб. Дело закрыто.
tags: #git #devops #ssh #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Еще один частый вопрос с LF — а нужно ли менять дефолтный ssh (22) порт на какой-то другой?
ㅤ
Нет! Ну а нахуя? Сократить в логах количество записей про неудачные попытки подломить твой девственный сервак?
В логи ты ходишь — практически никогда! Тем более там logrotate работает и место диске сильно не забьется.
Предположим ты поменял 22 на 2222. Количество записей в логах «сократилось» и теперь ты ебешься с указанием порта.
Охуеть как удобно! Ты скажешь - дак можно же в
Справедливо. Но зачем жертвовать своим удобством?
У тебя на серверах уже отключен вход по паролю, только ключи, рут тоже запрещен.
Пусть эти писька-боты долбятся и дальше в жопы. Накрайняк воткни fail2ban и устрой им веселую жизу.
Да и боты сейчас умные, если они видят закрытый 22 порт, они сделают
Как не прячься, все равно тебя найдут и насрут в логи.
Получается все манипуляции с портом это бесполезные телодвижения в ущерб удобства.
Соблюдай базовые правила безопасности и всё с твоими серверами будет хорошо.
За всю свою практику я встретил только одну компанию, где меняли 22 порт на какой-то другой, но никакой смысловой нагрузки в этом не было. Так и так эту компанию подломили и спиздили базу данных.
Да, еще был компания, где 22 порт открывался через port knocking. То есть нужно было предварительно стукнуться на 3 определенных порта и если последовательность была соблюдена, то открывался 22 порт.
Ну тоже такое себе решение в ущерб удобства. Любят люди из пушки по воробьям стрелять.
Это как в жизни — мойте руки перед едой. Если соблюдаешь этот базовый принцип, то повышаешь шансы, что твой организм не хакнет кишечная палочка.
Такие дела, изучай!
tags: #devops #ssh #linuxfactory #security
—
🔔 @bashdays➡️ @gitgate
ㅤ
Нет! Ну а нахуя? Сократить в логах количество записей про неудачные попытки подломить твой девственный сервак?
В логи ты ходишь — практически никогда! Тем более там logrotate работает и место диске сильно не забьется.
Предположим ты поменял 22 на 2222. Количество записей в логах «сократилось» и теперь ты ебешься с указанием порта.
ssh -p2222 user@server
Охуеть как удобно! Ты скажешь - дак можно же в
~/.ssh/config
все это прописать и всё вернуть на свои места.Host bashdays.ru
HostName bashdays.ru
User user
IdentityFile ~/.ssh/shuba
Port 2222
Справедливо. Но зачем жертвовать своим удобством?
У тебя на серверах уже отключен вход по паролю, только ключи, рут тоже запрещен.
Пусть эти писька-боты долбятся и дальше в жопы. Накрайняк воткни fail2ban и устрой им веселую жизу.
Да и боты сейчас умные, если они видят закрытый 22 порт, они сделают
nmap -Pn
, по итогу получат твой 2222 и продолжат долбиться.Как не прячься, все равно тебя найдут и насрут в логи.
Получается все манипуляции с портом это бесполезные телодвижения в ущерб удобства.
Соблюдай базовые правила безопасности и всё с твоими серверами будет хорошо.
- отключи вход по паролю
- перейди на ssh ключи
- запрети вход для рута
За всю свою практику я встретил только одну компанию, где меняли 22 порт на какой-то другой, но никакой смысловой нагрузки в этом не было. Так и так эту компанию подломили и спиздили базу данных.
Да, еще был компания, где 22 порт открывался через port knocking. То есть нужно было предварительно стукнуться на 3 определенных порта и если последовательность была соблюдена, то открывался 22 порт.
Ну тоже такое себе решение в ущерб удобства. Любят люди из пушки по воробьям стрелять.
Это как в жизни — мойте руки перед едой. Если соблюдаешь этот базовый принцип, то повышаешь шансы, что твой организм не хакнет кишечная палочка.
Такие дела, изучай!
tags: #devops #ssh #linuxfactory #security
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 87
Здрасти мои хорошие!
Рассмотрим ситуацию — злодеи устроили нагрузочное тестирование и натравили на твой ламповый стартап какой-нибудь «яндекс-танк».
ㅤ
😲 Подключить DDosGuard или Кратор!
Эт я пеню, ценник на такие услуги — моё почтение, да и по функционалу там очень даже всё урезано. А cloudflare по регламенту компании запрещен. Замкнутый круг.
Ну так что делать то?
Да блядь nginx затюнить и отбить всю эту хуйню-муйню. Понятно дело оно особо при дидосах не спасет, но со сканерами и «танками» заебись справится.
В nginx есть параметр
Поехали настраивать.
Создаем файл
Для рейта есть такая табличка:
тестируем так:
И смотрим нет ли ошибок 503 Слишком дохуя запросов и корректно ли отрабатывает лимит.
🅰️ 🅰️
Сука! А как рассчитать эту 20m памяти? Щаа…
Пардон, хуйню сморозил, давай на котиках:
То есть, зона
А откуда взялось 128?
Как я написал выше nginx хранит каждого уникального клиента (ключ
Есть такая табличка:
Да, еще можно настроить
Например:
Клиенту разрешается до 400 мгновенных запросов, а затем он попадает в ограничение 200r/s.
Теперь по мапингам и гео хуйне.
В первом блоке про гео:
1. Все пользователи получат
2. Те, кто с
Во втором блоке про мапинг:
1. Если
2. Если
Короче делаем что-то вроде белого списка и кто в него не входит — идёт нахуй! Надеюсь понятно объяснил.
Теперь чтобы вся эта поебота заработала, нужно прописать в нужный локейшен:
Ну а чтобы отдавать нужный статус при достижении лимита, делаем:
Возвращаем 429 Слишком дохуя запросов, вместо стандартного 503.
Бездумно это настраивать не советую, могут пострадать обычные пользователи, а вот если всё вдумчиво сделать — спасешь свой стартап от злых писек.
➡️ Ну и сыпь в комменты свои варианты!
tags: #nginx #devops #security
—
🔔 @bashdays➡️ @gitgate
Рассмотрим ситуацию — злодеи устроили нагрузочное тестирование и натравили на твой ламповый стартап какой-нибудь «яндекс-танк».
ㅤ
Эт я пеню, ценник на такие услуги — моё почтение, да и по функционалу там очень даже всё урезано. А cloudflare по регламенту компании запрещен. Замкнутый круг.
Ну так что делать то?
Да блядь nginx затюнить и отбить всю эту хуйню-муйню. Понятно дело оно особо при дидосах не спасет, но со сканерами и «танками» заебись справится.
В nginx есть параметр
limit_req_zone
, он то нам и пригодится. Этот параметр ограничивает количество одновременных запросов с одного айпишника.Поехали настраивать.
Создаем файл
/etc/nginx/conf.d/assholes.conf
geo $limited {
default 1;
192.168.1.1 0; # Этот IP не лимитируется
10.0.0.0/24 0; # 10.0.0.0/24 тоже без ограничений
}
map $limited $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=bashdays:20m rate=200r/s;
limit_req_zone
- ключ для отслеживания запросов.$binary_remote_addr
- системная переменная nginx, внутри хранит ip адрес клиента.zone=bashdays:20m
- произвольное имя зоны, 20m это объём памяти в мегабайтах для хранения данных. В этой зоне хранятся данные о количестве запросов от каждого уникального клиента.rate=200r/s
- ограничение равное 200 запросов в секунды с одного ip клиента. Для рейта есть такая табличка:
Сценарий rate burst
-------------------------------------------
API с высокой нагрузкой 100r/s 200
Средний веб-сайт 50r/s 100
Анти-DDoS защита 10r/s 20
CDN или кеширующий прокси 500r/s 1000
тестируем так:
ab -n 1000 -c 50 http://bashdays.ru/
wrk -t4 -c100 -d10s http://bashdays.ru/
И смотрим нет ли ошибок 503 Слишком дохуя запросов и корректно ли отрабатывает лимит.
Сука! А как рассчитать эту 20m памяти? Щаа…
Максимальное количество клиентов = размер зоны в байтах / размерзаписинаклиента
Пардон, хуйню сморозил, давай на котиках:
Пример расчёта для 20m (20 мегабайт = 20 × 1024 × 1024 = 20 971 520 байт):
20 971 520 / 128 = 163 840
То есть, зона
20m
может хранить лимиты примерно для 163 тысяч уникальных клиентов одновременно.А откуда взялось 128?
Как я написал выше nginx хранит каждого уникального клиента (ключ
$binary_remote_addr
или другое значение) в зоне, используя примерно 128 байт на запись.Есть такая табличка:
< 20 000 = 4m
~80 000 = 10m
~160 000 = 20m
500 000+ = 64m
Да, еще можно настроить
burst
для резких пиков. burst
позволяет временно превышать rate
, прежде чем включится жёсткий лимит.Например:
limit_req zone=bashdays burst=400 nodelay;
Клиенту разрешается до 400 мгновенных запросов, а затем он попадает в ограничение 200r/s.
nodelay
означает, что первые 400 запросов проходят сразу, а потом начинается строгий лимит.Теперь по мапингам и гео хуйне.
В первом блоке про гео:
1. Все пользователи получат
$limited = 1
(по умолчанию).2. Те, кто с
192.168.1.1
или из 10.0.0.0/24
, получат $limited = 0
и не будут ограничены.Во втором блоке про мапинг:
1. Если
$limited = 1
, то $limit = $binary_remote_addr
(IP-адрес клиента).2. Если
$limited = 0
, то $limit = ""
, и клиент не попадает в limit_req_zone.
Короче делаем что-то вроде белого списка и кто в него не входит — идёт нахуй! Надеюсь понятно объяснил.
Теперь чтобы вся эта поебота заработала, нужно прописать в нужный локейшен:
location / {
limit_req zone=bashdays burst=10 nodelay;
try_files $uri $uri/ /index.php?$args;
}
Про burst и nodelay выше уже рассказывал.
Ну а чтобы отдавать нужный статус при достижении лимита, делаем:
location / {
limit_req_status 429;
limit_req zone=bashdays burst=10 nodelay;
try_files $uri $uri/ /index.php?$args;
}
Возвращаем 429 Слишком дохуя запросов, вместо стандартного 503.
Бездумно это настраивать не советую, могут пострадать обычные пользователи, а вот если всё вдумчиво сделать — спасешь свой стартап от злых писек.
tags: #nginx #devops #security
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Очередные грабли на которые в LF многие наступили.
ㅤ
Есть nginx с такой конфигурацией:
И есть приложение:
Плюс к нему Dockerfile:
Собираем и запускаем контейнер:
Идем в браузере на
Важно! Уже по этой ошибке можно сделать какие-то выводы, эт не стандартная ошибка от nginx, а значит запрос отлично доходит до приложения. Но где-то внутри приложения теряется. Тренируй насмотренность, у nginx ошибки обычно по центру выводятся, а тут align вправо.
Еще как вариант, можешь остановить контейнер и еще раз в браузере тыкнуться, если получишь 502 Плохой шлюх, то значит что nginx нормально всё у тебя передает запросы на Flask. Но где-то внутри Flask происходит какое-то гавнище.
А что случилось? Всёж верно? Локейшен в nginx прописан, прокси-пасс тоже присутствует, где ответ от приложения?
Все дело в слэшах!
В конце порта 5000 ставим слэш и проверяем. Хуяк и оно начинает работать!
Что вообще происходит?
Когда мы делаем локейшен без последнего слэша в прокси-пассе, nginx проксирует запросы на приложение без изменения пути.
То есть приложение
А когда мы добавляем слэш, nginx добавляет путь после
Короче опять заумно расписал, давай снова на котиках!
➡️ Без слэша запрос
➡️ С слэшем запрос
В общем с конечным слэшем nginx «удаляет» часть пути
Вот и вся наука. Грабли прям жизненные и порой доставляют проблемы с многочасовым дебагом.
Так что держи это в голове, если с виду вроде все правильно, но не работает, пиздани в конце слэш, типа метод тыка.
Вечерком еще чтива подвезу, случайно набрал интеграций, теперь отдуваюсь.
tags: #nginx #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgate
ㅤ
Есть nginx с такой конфигурацией:
server {
listen 80;
server_name _;
location /app {
proxy_pass http://localhost:5000;
}
}
И есть приложение:
from flask import
Flask app = Flask(__name__)
@app.route('/')
def hello():
return 'Привет, Linux Factory!'
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Плюс к нему Dockerfile:
FROM python:3.8-slim
WORKDIR /app COPY .
/app RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
Собираем и запускаем контейнер:
docker build -t bashdays .
docker run -d -p 5000:5000 bashdays
Идем в браузере на
http://bashdays.ru/app
и получаем хуй с маслом:Not Found. The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Важно! Уже по этой ошибке можно сделать какие-то выводы, эт не стандартная ошибка от nginx, а значит запрос отлично доходит до приложения. Но где-то внутри приложения теряется. Тренируй насмотренность, у nginx ошибки обычно по центру выводятся, а тут align вправо.
Еще как вариант, можешь остановить контейнер и еще раз в браузере тыкнуться, если получишь 502 Плохой шлюх, то значит что nginx нормально всё у тебя передает запросы на Flask. Но где-то внутри Flask происходит какое-то гавнище.
А что случилось? Всёж верно? Локейшен в nginx прописан, прокси-пасс тоже присутствует, где ответ от приложения?
Все дело в слэшах!
location /app {
proxy_pass http://localhost:5000/;
}
В конце порта 5000 ставим слэш и проверяем. Хуяк и оно начинает работать!
Что вообще происходит?
Когда мы делаем локейшен без последнего слэша в прокси-пассе, nginx проксирует запросы на приложение без изменения пути.
То есть приложение
app.py
получает роут /app
а его там естественно нет. А есть просто корень /
.А когда мы добавляем слэш, nginx добавляет путь после
/app
к целевому урлу.Короче опять заумно расписал, давай снова на котиках!
/app
проксируется на http://localhost:5000/app
, что не совпадает с маршрутом, настроенным в Flask./app
проксируется на http://localhost:5000
, и приложение Flask обслуживает его как корневой путь /
.В общем с конечным слэшем nginx «удаляет» часть пути
/app
и отправляет запрос на корень приложения Flask.Вот и вся наука. Грабли прям жизненные и порой доставляют проблемы с многочасовым дебагом.
Так что держи это в голове, если с виду вроде все правильно, но не работает, пиздани в конце слэш, типа метод тыка.
Вечерком еще чтива подвезу, случайно набрал интеграций, теперь отдуваюсь.
tags: #nginx #devops #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Очередной распространенный вопрос - а схуяли нужно гитлаб изучать?
ㅤ
Почему не github / pornhub / gitea?
Именно по этой причине всем кому не лень напихали себев жопу на self-hosting этого гитлаба, завели на него процессы и радуются.
Например, в вакансиях этот пункт про гитлаб будет в 99% случаев. Раньше еще можно было встретить Bitbucket, но эти письки съебали с РФ и поэтому все дружно послали atlassian в пешее эротическое.
Что не так с гитлабом?
Всё с ним так, единственный минус — он дохуя прожорлив, если у тебя слабенький сервачок то будет больно. Ну и ежечасные обновления бесят, заебывает эта всплывашка — ай, я снова дырявый, подлатай меня сучка!
Сюда еще можно добавить — бесконечная документация, нет четких инструкций по бест-практикам как писать пайплайны. Одну задачу можно решить несколькими способами, а способы порой бывают достаточно костыльные и упоротые.
Кто-то вообще умудряется превратить пайплайны в ООП. Это отдельный костяк отбитых инженеров, приверженцы бас-фактора.
На самом деле неважно где ты натаскаешься писать пайплайны, тут главное иметь представления как они работают.
Так и с пайпами, познакомился с yaml разметкой, взял из интернетов болванку с пайплайном и переписал под свои нужды, хоть для бакета, гитхаба, гитлаба, неважно.
Так что если ты изучаешь пайпы на гитхабе, да ради бога, база у тебя в голове будет и ты без труда сможешь адаптировать все для гитлаба.
И если видишь в вакухе — знания гитлаба, а ты его не знаешь, да и хуй с ним. Скажи — знаю! А там уже за пару часов разберешься, ничего в этом сложного нет. Но конечно же при условии, что ты пайпы хоть раз в жизни писал для чего-нибудь другого.
Такие дела!
tags: #рабочиебудни #devops
—
🔔 @bashdays➡️ @gitgate
ㅤ
Почему не github / pornhub / gitea?
Ответ простой — Бесплатная версия GitLab (Community Edition) с открытым кодом даёт возможность изучить платформу без затрат. Для бизнеса это ещё и свобода от привязки к вендору.
Именно по этой причине всем кому не лень напихали себе
Например, в вакансиях этот пункт про гитлаб будет в 99% случаев. Раньше еще можно было встретить Bitbucket, но эти письки съебали с РФ и поэтому все дружно послали atlassian в пешее эротическое.
Что не так с гитлабом?
Всё с ним так, единственный минус — он дохуя прожорлив, если у тебя слабенький сервачок то будет больно. Ну и ежечасные обновления бесят, заебывает эта всплывашка — ай, я снова дырявый, подлатай меня сучка!
Сюда еще можно добавить — бесконечная документация, нет четких инструкций по бест-практикам как писать пайплайны. Одну задачу можно решить несколькими способами, а способы порой бывают достаточно костыльные и упоротые.
Кто-то вообще умудряется превратить пайплайны в ООП. Это отдельный костяк отбитых инженеров, приверженцы бас-фактора.
На самом деле неважно где ты натаскаешься писать пайплайны, тут главное иметь представления как они работают.
Как пример, в школе я писал на Паскале, в голове сложил как работает программирование, ну и потом без труда пересел на сиськи потому что имел представление как работают программы. Синтаксис везде разный, но общая составляющая по базе одинаковая.
Грубо говоря — нарисовал в голове блок схему, напрограммировал. Благо сейчас полно книжек — Java для детей, Golang - для бабушек и т.п. Читаешь книжку за пару дней, знакомишься с синтаксисом и пошел кодить. Функции, циклы, условия они везде одинаковые.
Так и с пайпами, познакомился с yaml разметкой, взял из интернетов болванку с пайплайном и переписал под свои нужды, хоть для бакета, гитхаба, гитлаба, неважно.
Так что если ты изучаешь пайпы на гитхабе, да ради бога, база у тебя в голове будет и ты без труда сможешь адаптировать все для гитлаба.
И если видишь в вакухе — знания гитлаба, а ты его не знаешь, да и хуй с ним. Скажи — знаю! А там уже за пару часов разберешься, ничего в этом сложного нет. Но конечно же при условии, что ты пайпы хоть раз в жизни писал для чего-нибудь другого.
Такие дела!
tags: #рабочиебудни #devops
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Вчера многие обратили внимание на конструкцию в 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 79
Сегодня будем запирать врата ада.
ㅤ
Ситуация: Есть физический сервер, на нём торчит само собой 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.pub
error: 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_config
UsePAM 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_config
Match User <имя юзера>
AuthenticationMethods publickey,keyboard-interactive
Настроек там жопой кушай, я тебе лишь концепт показал как эту хуйню можно быстренько настроить.
А как работать с 2FA и QR кодами из консоли, можешь почитать тут.
Главное не спеши и делай всё вдумчиво, чтобы не проебать доступ к серверу. Ну а если все проебал, да и хуй с ним, ебани кофейка и мультики посмотри.
tags: #linux #devops #linuxfactory
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Ребята с LF порой интересуются — а нахуя в nginx нужна поддержка lua? Можно какой-то пример, но только не Hello World?
ㅤ
Конечно можно!
Понадобилось мне как-то реализовать продвинутый basic auth, чтобы nginx сходил в mysql базу и сопоставил введенные учетные данные.
А как блядь это сделать?
Тут-то и пригодится Lua!
Для начала создаем базу (nginx_auth) и табличку users. Ну и в ней колонки username и password. В username храним имя пользователя, в password захэшированный пароль:
Эту команду выполняешь в mysql, в ответ он выплюнет тебе хэш, его и нужно будет заебенить в колонку password.
Дальше конфигуряем nginx:
Ну и сам скрипт кидаем в
Всё! Релоадим nginx и получаем прокаченный Basic Auth.
Теперь nginx лезет в базу и при успешном исходе кидает пользователя в локейшен
Да, скрипт работает на mariadb. Для всяких перкон и т.п. возможно нужно будет переделать SELECT.
Вот такие пироги, вот тебе и заебачее применение Lua!
➡️ Кстати, если увидел вектор атаки, поделись в комментах.
tags: #linux #devops #lua #nginx
—
🔔 @bashdays➡️ @gitgate
ㅤ
Конечно можно!
Понадобилось мне как-то реализовать продвинутый basic auth, чтобы nginx сходил в mysql базу и сопоставил введенные учетные данные.
А как блядь это сделать?
Тут-то и пригодится Lua!
Для начала создаем базу (nginx_auth) и табличку users. Ну и в ней колонки username и password. В username храним имя пользователя, в password захэшированный пароль:
SHA1('$UpperPa$$word')
Эту команду выполняешь в mysql, в ответ он выплюнет тебе хэш, его и нужно будет заебенить в колонку password.
Дальше конфигуряем nginx:
location / {
content_by_lua_file /etc/nginx/lua/auth.lua;
}
location @authenticated {
root /var/www/bashdays/htdocs/site;
index index.html;
}
В nginx само собой добавляем модуль Lua, Как его собрать можешь в гугле посмотреть, ну либо взять какойнить openresty.
Ну и сам скрипт кидаем в
/etc/nginx/lua/auth.lua;
local mysql = require "resty.mysql"
local sha1 = require "resty.sha1"
local resty_string = require "resty.string"
local db, err = mysql:new()
-- Установка таймаута
if not db then
ngx.log(ngx.ERR, "failed to create mysql object: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
db:set_timeout(1000)
-- Подключение к базе данных
local res, err = db:connect{
host = "db",
port = 3306,
database = "nginx_auth",
user = "nginx_user",
password = "password",
charset = "utf8",
}
if not res then
ngx.log(ngx.ERR, "failed to connect to MySQL: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- Извлекаем данные из заголовков Authorization
local auth = ngx.var.http_authorization
if not auth or not auth:find("Basic ") then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- Парсим Basic Auth заголовок
local encoded = auth:sub(7) -- Убираем "Basic " из начала
local decoded = ngx.decode_base64(encoded)
if not decoded then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- Разделяем строку на имя пользователя и пароль
local username, password = decoded:match("([^:]+):(.+)")
if not username or not password then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- Хешируем пароль
local sha1_obj = sha1:new()
sha1_obj:update(password)
local password_hash = resty_string.to_hex(sha1_obj:final())
-- Проверяем пользователя и пароль в базе данных
local sql = string.format("SELECT * FROM users WHERE username = '%s' AND password = '%s'", username, password_hash)
local res, err = db:query(sql)
if not res or #res == 0 then
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- Передаем управление Nginx для загрузки страницы
ngx.exec("@authenticated")
Всё! Релоадим nginx и получаем прокаченный Basic Auth.
Сам скрипт не претендует на совершенство и очень простой, объяснять его не вижу смысла. Пробегись глазами и всё сам поймешь.
Теперь nginx лезет в базу и при успешном исходе кидает пользователя в локейшен
@authenticated.
Да, скрипт работает на mariadb. Для всяких перкон и т.п. возможно нужно будет переделать SELECT.
Вот такие пироги, вот тебе и заебачее применение Lua!
tags: #linux #devops #lua #nginx
—
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
Привет, один из наших подписчиков попросил анонсировать его пепяку. Она уже пролетала в gitgate, но ничего страшного, пусть и тут полежит. Тем более штука маст-хэвная.
Если кратко,
ㅤ
Ты скажешь — блядь, да есть же например tfenv и asdf, зачем очередной велосипед?
Во-первых, автора
Ну и, во-вторых, все эти утилиты не поддерживают OpenTofu, Terragrunt и т.п. К тому же, требуют много консольных костылей/зависимостей и хуёва работают НЕ на Linux.
Установка:
Сейчас лично потыкал, всё работает как часики. После установки запускаем
НО, так как хашикорпы — письки (
В общем рекомендую потыкать и поддержать проект звездами. Годнота!
➡️ Страница проекта и документация
tags: #utilites #devops
—
🔔 @bashdays➡️ @gitgate
TENV
Ёпта!Если кратко,
TENV
это консольный менеджер для управления версиями Terraform, Terragrunt, OpenTofu, Atmos.ㅤ
TENV
написан на гошке, не требует дополнительных зависимостей и может быть запущен под любой операционкой. Удобно чё.Ты скажешь — блядь, да есть же например tfenv и asdf, зачем очередной велосипед?
Во-первых, автора
TENV
зовут Александр, а не «Аннадурай Сатьямурти Чидамбарампиллаи». А это уже о чем-то говорит!Ну и, во-вторых, все эти утилиты не поддерживают OpenTofu, Terragrunt и т.п. К тому же, требуют много консольных костылей/зависимостей и хуёва работают НЕ на Linux.
asdf не поддерживает автоматическое переключение версий на базе спецификации версии Terraform / OpenTofu внутри проекта с помощью HCL файлов. В целом, asdf скорее переключалка по запросу, а tenv более заточен под OpenTofu/Terraform проекты.
Установка:
LATEST_VERSION=$(curl --silent https://api.github.com/repos/tofuutils/tenv/releases/latest | jq -r .tag_name)
curl -O -L "https://github.com/tofuutils/tenv/releases/latest/download/tenv_${LATEST_VERSION}_amd64.deb"
sudo dpkg -i "tenv_${LATEST_VERSION}_amd64.deb"
Сейчас лично потыкал, всё работает как часики. После установки запускаем
tenv
, выбираем из списка (стрелочками и на пробел) что установить и жмем ENTER.НО, так как хашикорпы — письки (
This content is not currently available in your region
), в РФ надо трафик прогнать через одно место, чтобы вытащить бинари терраформа.Вот тут я бы пожелал автору добавить киллер-фичу, сделать чтобы tenv обращался к таким заблокированным серверам не самостоятельно, а например через какую-то прокладку. Тогда сука цены бы не было!
Александр, добавь для нас такую возможность, буду прям лично твоей штукой пользоваться, достаточно удобно!
В общем рекомендую потыкать и поддержать проект звездами. Годнота!
tags: #utilites #devops
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Proxmox post install in 2025 (часть 1)
ㅤ
Давай разберемся, что нужно сделать после установки proxmox.
Наш путь — это всё сделать ручками, чтобы было понимание и контроль над процессом.
Для начала пиздуем сюда:
И добавляем дополнительные репозитории:
Затем отключаем интерпрайзный репозиторий в файле:
В нем комментируем одну строчку:
Следом отключаем платный
Комментируем и добавляем халявную репу:
После этого выполняем:
Всё раздуплится и обновится из бесплатных репозиториев. После этого перезагружаем сервер, потому что прилетело достаточно много важного и серьезного.
Дальше выполняем в терминале proxmox:
Эта команда отключит
На этом можно и закончить, но есть еще момент с прокидываем физических устройств в виртуальные машины.
Этот момент рассмотрим во второй части (завтра в 14:13 МСК залетит, пост в отложке), там похитрее всё.
🛠 #proxmox #devops
—
✅ @bashdays / @linuxfactory / @blog
ㅤ
Давай разберемся, что нужно сделать после установки proxmox.
Как вариант сразу накатить эту штуку Proxmox VE Post Install, но процесс не прозрачный.
Наш путь — это всё сделать ручками, чтобы было понимание и контроль над процессом.
Для начала пиздуем сюда:
/etc/apt/sources.list
И добавляем дополнительные репозитории:
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
deb http://security.debian.org/debian-security bookworm-security main contrib
Затем отключаем интерпрайзный репозиторий в файле:
/etc/apt/sources.list.d/pve-enterprise.list
В нем комментируем одну строчку:
# deb https://enterprise.proxmox.com/debian/pve bookworm pve-enterprise
Следом отключаем платный
ceph
, идем в файл:/etc/apt/sources.list.d/ceph.list
Комментируем и добавляем халявную репу:
# deb https://enterprise.proxmox.com/debian/ceph-quincy bookworm enterprise
deb http://download.proxmox.com/debian/ceph-quincy bookworm no-subscription
После этого выполняем:
apt update && apt upgrade
reboot
Всё раздуплится и обновится из бесплатных репозиториев. После этого перезагружаем сервер, потому что прилетело достаточно много важного и серьезного.
Дальше выполняем в терминале proxmox:
sed -Ezi.bak "s/(Ext.Msg.show\(\{\s+title: gettext\('No valid sub)/void\(\{ \/\/\1/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
Эта команда отключит
No valid subsciption
, сообщение о том, что у нас отсутствует подписка на интерпрайз. Довольно нозящая и заёбистая тема. Чтобы изменения вступили в силу, скинь кэш в браузере. Всё, больше это информационное окошко тебя не побеспокоит.
На этом можно и закончить, но есть еще момент с прокидываем физических устройств в виртуальные машины.
Этот момент рассмотрим во второй части (завтра в 14:13 МСК залетит, пост в отложке), там похитрее всё.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Proxmox post install in 2025 (часть 2)
Такс, следующим этапом после установки proxmox необходимо настроить проброс реальных устройств в виртуальные машины.
ㅤ
Если устройство проброшено в виртуальную машину, то ни хостовая машина ни другие виртуальные машины использовать это устройство не смогут. Короче устройство будет изолировано.
Открываем на редактирование файл:
И правим
Если у тебя Intel:
Если у тебя AMD
Сохраняем изменения и обновляем загрузчик:
По-хорошему proxmox нужно отправить в перезагрузку, но это не точно. В любом случае для чистоты эксперимента я все же ребучу.
Загружаем модули:
Открываем на редактирование:
И прописываем:
С версии ядра 6.2 модуль vfio_virqfd больше нахуй не нужен.
Сохраняем и запускаем:
Здесь обязательно нужен ребут, без ребута нихуя НЕ заработает!
Проверяем:
И ищем строчку:
Если нашел, то поздравляю, у тебя всё получилось! Если же нет, то еще раз внимательно выполни все шаги и не забудь про ребут.
На закуску
Чтобы изолировать GPU карточку от хостовой системы, нужно еще с бубном побегать.
Узнаём ID карточки, а дальше подставляем этот ID в эту команду:
И пиздярим блеклисты:
Ну и само собой отправляем proxmox в ребут.
Проброс HDD
Узнаём ID диска и выполняем команду:
Вот и вся наука. Всё лично протестировано и работает как часы, включая проброс видюхи.
Если есть чего добавить, велком в комменты.
🛠 #proxmox #devops
—
✅ @bashdays / @linuxfactory / @blog
Такс, следующим этапом после установки proxmox необходимо настроить проброс реальных устройств в виртуальные машины.
ㅤ
Проброс устройств подразумевает — устройства которые подключены к материнской плате на хостовой машине. Например, видюха, модемы и т.п. То есть виртуальные машины смогут их использовать.
Если устройство проброшено в виртуальную машину, то ни хостовая машина ни другие виртуальные машины использовать это устройство не смогут. Короче устройство будет изолировано.
У меня таким боком прокинут рутокен в виндовую виртуалку, чтобы в ЭДО доки подписывать с любого устройства и из любой жопы мира.
Открываем на редактирование файл:
/etc/default/grub
И правим
GRUB_CMDLINE_LINUX_DEFAULT
, должно получиться так:Если у тебя Intel:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on pt=on"
Если у тебя AMD
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on pt=on"
iommu=on — включает IOMMU (Input-Output Memory Management Unit) для процессоров. Этот механизм позволяет изолировать устройства ввода-вывода, повышая безопасность и управление памятью.
pt=on — включает поддержку PCI passthrough для виртуализации, позволяя передавать устройства (например, видеокарты или другие PCI-устройства) непосредственно в виртуальные машины.
Сохраняем изменения и обновляем загрузчик:
update-grub
reboot
По-хорошему proxmox нужно отправить в перезагрузку, но это не точно. В любом случае для чистоты эксперимента я все же ребучу.
Загружаем модули:
Открываем на редактирование:
/etc/modules
И прописываем:
vfio
vfio_iommu_type1
vfio_pci
С версии ядра 6.2 модуль vfio_virqfd больше нахуй не нужен.
Сохраняем и запускаем:
update-initramfs -u -k all
reboot
Здесь обязательно нужен ребут, без ребута нихуя НЕ заработает!
Проверяем:
dmesg | grep -e DMAR -e IOMMU or dmesg | grep -e DMAR -e IOMMU
И ищем строчку:
Interrupt remapping enable
Если нашел, то поздравляю, у тебя всё получилось! Если же нет, то еще раз внимательно выполни все шаги и не забудь про ребут.
На закуску
Чтобы изолировать GPU карточку от хостовой системы, нужно еще с бубном побегать.
lspci -nn
Узнаём ID карточки, а дальше подставляем этот ID в эту команду:
echo "options vfio-pci ids=10de:____,10de:____ disable_vga=1" > /etc/modprobe.d/vfio.conf
И пиздярим блеклисты:
echo "blacklist radeon" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidia" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidia_drm" >> /etc/modprobe.d/blacklist.conf
echo "blacklist i915" >> /etc/modprobe.d/blacklist.conf
Ну и само собой отправляем proxmox в ребут.
Проброс HDD
ls -n /dev/disk/by-id/
Узнаём ID диска и выполняем команду:
/sbin/qm set [VM-ID] -virtio2 /dev/disk/by-id/[DISK-ID]
Вот и вся наука. Всё лично протестировано и работает как часы, включая проброс видюхи.
Если есть чего добавить, велком в комменты.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Бомбардиро крокодило!
ㅤ
Я выспался, можно продолжать радовать вас всякой «нужной» хуйней.
Давно про
Суть этого сервиса — автоматически разрешать поддомены в IP адреса без необходимости поднимать свой DNS сервер.
Сейчас как мы делаем, локально редактируем файл
Например:
И если перейти по адресу
А ведь это база. С помощью которой ты к примеру поднимаешь новый продакшен. Но что бы протестировать его, тебе нужно подкинуть на новый продакшен домен со старого продакшена. А тебе такое сделать не дадут.
Вот и прописываешь себе в
Вернемся к
Теперь открыв
Давай потыкаем
У меня на IP
Пингуем:
В ответ я получаю такую картинку:
Отлично, пинг прошел, вернулся локальный айпишник. То есть мы пинганули какой-то глобальный домен, а он привел нас на локальный сервис.
Теперь я направляюсь в браузер и открываю url:
Мне открывается стартовая страница
Хуяк и видим предупреждение:
Ну клёвое же. Запрос прошел через глобальный домен и перенаправил запрос в мою локальную сеть. Без необходимости что-то прописывать в
Просто жмем «продолжить» и попадаем снова на стартовую страницу
Еще вариант с портами:
На порту
А можно прям кучу поддоменов плодить:
И всё будет работать.
А еще можно на такие домены получить SSL сертификаты, но у тебя должен быть белый айпишник.
Хуяк и у тебя готовый SSL для домена
Минусы nip.io:
1. Не поддерживает wildcards, но в большинстве случаев они избыточны. Инструмент заточен больше на удобное тестирование при разработке.
2. SSL работает только с публичными IP. Для
У
Хорошо тебе провести эти выходные. Ну а я пошел фиксить баги.
Увидимся!
🛠 #devops #networks
—
✅ @bashdays / @linuxfactory / @blog
ㅤ
Я выспался, можно продолжать радовать вас всякой «нужной» хуйней.
Давно про
nip.io
ничего не слышал, но всё чаще встречаю его у ребят с Linux Factory. Суть этого сервиса — автоматически разрешать поддомены в IP адреса без необходимости поднимать свой DNS сервер.
Сейчас как мы делаем, локально редактируем файл
/etc/hosts
, прописываем в него какие-то свои локальные айпишники на вымышленные домены. Например:
192.168.0.10 nginx.local
192.168.0.11 grafana.local
И если перейти по адресу
nginx.local
попадаешь на виртуалку с айпишником 192.168.0.10
. Это всё очевидно.Но опять же как оказалось про манипуляции с hosts файлом многие не знали.
А ведь это база. С помощью которой ты к примеру поднимаешь новый продакшен. Но что бы протестировать его, тебе нужно подкинуть на новый продакшен домен со старого продакшена. А тебе такое сделать не дадут.
Вот и прописываешь себе в
hosts
этот домен, указываешь айпишник нового прода, идешь тестишь, если все ок, то меняешь A
запись.Вернемся к
nip.io
, суть там такая же, прописываешь айпишники и нужные домены и по итогу получаешь такое:nginx.192.168.0.10.nip.io → 192.168.0.10
app.192.168.0.11.nip.io → 192.168.0.11
test.192.168.0.12.nip.io → 192.168.0.12
Теперь открыв
nginx.192.168.0.10
.nip.io
ты попадешь на 192.168.0.10
без редактирования своего hosts
файла.Давай потыкаем
У меня на IP
192.168.10.6
в локалке висит малина со всякими открытыми портами. Пингуем:
ping 192.168.10.6.nip.io
В ответ я получаю такую картинку:
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: 192.168.10.6.nip.io
Address: 192.168.10.6
Отлично, пинг прошел, вернулся локальный айпишник. То есть мы пинганули какой-то глобальный домен, а он привел нас на локальный сервис.
Теперь я направляюсь в браузер и открываю url:
http://192.168.10.6
Мне открывается стартовая страница
nginx
. Тут всё понятно и логично. А теперь давай сделаем так.http://nginx.192.168.10.6.nip.io
Хуяк и видим предупреждение:
Для сайта 192.168.10.6.nip.io не поддерживается защищенное подключение
Ну клёвое же. Запрос прошел через глобальный домен и перенаправил запрос в мою локальную сеть. Без необходимости что-то прописывать в
hosts
файле.Просто жмем «продолжить» и попадаем снова на стартовую страницу
nginx
.Еще вариант с портами:
http://sync.192.168.10.6.nip.io:8384
На порту
8384
у меня висит syncthing
и всё отлично открывается. То есть можно пробрасывать запросы через домен прям на порты или в докер контейнеры.А можно прям кучу поддоменов плодить:
http://a.b.c.d.192.168.10.6.nip.io/
И всё будет работать.
А еще можно на такие домены получить SSL сертификаты, но у тебя должен быть белый айпишник.
sudo certbot certonly --standalone -d nginx.204.0.115.50.nip.io
Хуяк и у тебя готовый SSL для домена
nginx.204.0.115.50.nip.io
. Ну а если не хочется возиться с certbot
можно воспользоваться алтернативами, например acme.sh
или caddy
.Минусы nip.io:
1. Не поддерживает wildcards, но в большинстве случаев они избыточны. Инструмент заточен больше на удобное тестирование при разработке.
2. SSL работает только с публичными IP. Для
127.0.0.1.nip.io
или 192.168.x.x.nip.io
Let's Encrypt не выдаст сертификат.У
nip.io
есть альтернативы: xip.io или sslip.ioВ общем я показал, а тебе уже самому решать где это применить или не применить.
Хорошо тебе провести эти выходные. Ну а я пошел фиксить баги.
Увидимся!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
У
ㅤ
То есть ты не напрямую подключаешься к серверу:
А подключаешься к серверу через сервер с
Настраивается эта штука так:
На сервере с
Создаём под это дело отдельную роль:
На сервере к которому хотим подключаться, делаем:
Добавляем в конфиг
И перезапускаем:
Переходим на свою локальную машину, с которой будем подключаться:
Этой командой подписываем свой публичный ключ через
Сохраняем на локальную машину подписанный ключ:
Смотрим параметры получившегося ключа:
Опять же получишь портянку информации, можно посмотреть валидность и время жизни этого ключа.
Теперь подключаемся:
Ну и вишенка, подключаемся через враппер:
В этом случае подписывать ключ не обязательно.
Доступ к серверам контролирует
Что-то вроде центра сертификации, писал как-то отдельный пост на эту тему.
Нашел еще видос у пиндоса на эту тему, можешь визуально глянуть и проникнутся.
Такие дела!
🛠 #linux #devops
—
✅ @bashdays / @linuxfactory / @blog
Hashicorp Vault
есть прикольная фишка со встроенным ssh враппером и подписными ключами.ㅤ
То есть ты не напрямую подключаешься к серверу:
ssh root@server
А подключаешься к серверу через сервер с
Vault
, получается что-то вроде бастиона. Vault
подписывает ключи и запускает тебя в нужное место.Настраивается эта штука так:
На сервере с
Vault
выполняем:vault secrets enable -path=ssh ssh
vault write ssh/config/ca generate_signing_key=true
Создаём под это дело отдельную роль:
vault write ssh/roles/devops -<<"EOH"
{
"allow_user_certificates": true,
"allowed_users": "*",
"allowed_extensions": "permit-pty,permit-port-forwarding,permit-agent-forwarding,permit-user-rc,permit-X11-forwarding",
"default_extensions": [
{
"permit-pty": ""
}
],
"key_type": "ca",
"default_user": "root",
"ttl": "30m0s"
}
EOH
На сервере к которому хотим подключаться, делаем:
curl -o /etc/ssh/trusted-user-ca-keys.pem https://vault.bashdays.ru:8200/v1/ssh/public_key
Добавляем в конфиг
/etc/ssh/sshd_config
строчку: TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
И перезапускаем:
systemctl restart sshd
Переходим на свою локальную машину, с которой будем подключаться:
export VAULT_TOKEN="token"
vault write -address='https://vault.bashdays.ru:8200' ssh/sign/devops public_key=@$HOME/.ssh/id_rsa.pub
Этой командой подписываем свой публичный ключ через
vault
сервер. В ответ получаем кучу всякой хуйни типа: serial_number
и signed_key
.Сохраняем на локальную машину подписанный ключ:
export VAULT_TOKEN="token"
vault write -address='https://vault.bashdays.ru:8200' --field=signed_key ssh/sign/devops public_key=@$HOME/.ssh/id_rsa.pub > ~/.ssh/id_rsa_signed_key.pub
Смотрим параметры получившегося ключа:
ssh-keygen -Lf /Users/user/.ssh/id_rsa_signed_key.pub`
Опять же получишь портянку информации, можно посмотреть валидность и время жизни этого ключа.
Теперь подключаемся:
ssh -i ~/.ssh/id_rsa_signed_key.pub -i ~/.ssh/id_rsa root@server
Ну и вишенка, подключаемся через враппер:
vault ssh -address='https://vault.bashdays.ru:8200' -private-key-path=~/.ssh/id_rsa -public-key-path=~/.ssh/id_rsa.pub -mode=ca -role=devops -user-known-hosts-file=/dev/null root@server
В этом случае подписывать ключ не обязательно.
Доступ к серверам контролирует
Vault
. Можно быстро накручивать необходимые права, забирать и отзывать ключи. Ну и там много чего еще можно сделать.Выглядит крайне неудобно и не интуитивно. Но порой такую штуку можешь встретить в компаниях. Хотя я против такой хуйни, какая-то блядь избыточная безопасность.
Что-то вроде центра сертификации, писал как-то отдельный пост на эту тему.
Нашел еще видос у пиндоса на эту тему, можешь визуально глянуть и проникнутся.
Такие дела!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 56
Как оказалось многие испытывают неистовые жопные боли при настройке
ㅤ
Сегодня покажу как избавиться от боли и на лету получать SSL для
Устанавливаем angie:
Начиная с
Открываем айпишник сервера в браузере и убеждаемся что все работает. Если всё заебись, получишь стартовую страницу
Конфигуряем angie на домен two.su.
Создаем файл
А в файле
Если
Проверяем:
Полученный сертификат и соответствующий ключ будут доступны в конфигурации через переменные $acme_cert_<имя> и $acme_cert_key_<имя>.
Перезапускаем:
Если получил ошибку, закинь сертификаты заглушки в
У меня никаких ошибок не возникло.
В папке:
Захожу в браузере на
Меня вся эта кухня полностью устраивает. Понятно дело есть
Когда что-то настраиваешь руками, а не мышкой, то имеешь представление как работает технология изнутри. А если ты это знаешь, то легко сможешь отдебажить баги и найти первопричину.
По крайней мере меня так учили и я с этим полностью согласен.
🛠 #linux #devops #angie #ssl
—
✅ @bashdays / @linuxfactory / @blog
angie
со встроенной поддержкой SSL сертификатов от Lets Encrypt.ㅤ
Сегодня покажу как избавиться от боли и на лету получать SSL для
angie
. Без всяких там certbot
и acme.sh
. Довольно удобно реализовано.Для чистоты эксперимента я взял чистый, прерываемый сервер, без nginx’ов и т.п. на базе Ubuntu 24.04.
angie
это аналог nginx
, но на стероидах, у меня он крутится на уроках для LinuxFactory и в блоге. Подкупил он меня нативной поддержкой LUA и кучей модулей включая авто-получение SSL сертов.Устанавливаем angie:
sudo curl -o /etc/apt/trusted.gpg.d/angie-signing.gpg https://angie.software/keys/angie-signing.gpg
echo "deb https://download.angie.software/angie/$(. /etc/os-release && echo "$ID/$VERSION_ID $VERSION_CODENAME") main" | sudo tee /etc/apt/sources.list.d/angie.list > /dev/null
sudo apt-get update
sudo apt-get install -y angie
Начиная с
Angie 1.3.0
, модуль ACME (http_acme_module
) включён по умолчанию в основной пакет angie
.Открываем айпишник сервера в браузере и убеждаемся что все работает. Если всё заебись, получишь стартовую страницу
angie
. Дефолтная страница практически один в один повторяет дефолтную страницу от nginx
.Дальше у меня есть домен two.su который живет в Cloudfalre. В настройках DNS я прописываю A запись и указываю айпишник нового сервера. Весь трафик идет напрямую, без фильтрации самого Cloudfalre.
Конфигуряем angie на домен two.su.
Создаем файл
two.su.conf
в /etc/angie/httpd.d/
с таким содержимым.server {
listen 443 ssl;
server_name two.su www.two.su;
acme letsencrypt;
ssl_certificate $cert_letsencrypt;
ssl_certificate_key $cert_key_letsencrypt;
location / {
root /var/www/html;
}
}
А в файле
/etc/angie/angie.conf
в секцию http
добавляем:acme_client letsencrypt https://acme-v02.api.letsencrypt.org/directory;
resolver 127.0.0.53;
map $acme_cert_letsencrypt $cert_letsencrypt {
'' /etc/angie/ssl-self-signed/cert.pem;
default $acme_cert_letsencrypt;
map $acme_cert_letsencrypt $cert_key_letsencrypt {
'' /etc/angie/ssl-self-signed/key.pem;
default $acme_cert_key_letsencrypt;
}
Если
angie
у тебя работает в докере, то в resolver
пропиши: 127.0.0.11
.Проверяем:
angie -t
и в ответ получаем:angie: the configuration file /etc/angie/angie.conf syntax is ok
angie: configuration file /etc/angie/angie.conf test is successful
Полученный сертификат и соответствующий ключ будут доступны в конфигурации через переменные $acme_cert_<имя> и $acme_cert_key_<имя>.
Перезапускаем:
systemctl reload angie
Если получил ошибку, закинь сертификаты заглушки в
/etc/angie
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=RU/O=Bashdays/CN=LinuxFactory"
У меня никаких ошибок не возникло.
В папке:
/var/lib/angie/acme/letsencrypt
появились ключи и серты.Захожу в браузере на
two.su
и вижу зеленый замочек. Что и требовалось доказать. SSL сертификат был автоматически получен и в дальнейшем будет автоматически продляться. Без всяких кронов, клиентов, API ключей и хуйни.Единый сертификат будет получен для всех доменных имён, которые были перечислены в директиве server_name. А директива acme указывает, какой ACME-клиент должен использоваться.
Меня вся эта кухня полностью устраивает. Понятно дело есть
Nginx Proxy Manager
, но я привык работать без гуёвых штук и мордочек.Когда что-то настраиваешь руками, а не мышкой, то имеешь представление как работает технология изнутри. А если ты это знаешь, то легко сможешь отдебажить баги и найти первопричину.
По крайней мере меня так учили и я с этим полностью согласен.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
3 69
Распространенный случай в пайплайнах, как ребята пишут в 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 81
Довольно частый вопрос с 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 54