Bash Days | Linux | DevOps
23.7K subscribers
225 photos
26 videos
776 links
Авторский блог от действующего девопса

Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

MAX: https://max.ru/bashdays

Курс: @tormozilla_bot
Блог: https://bashdays.ru
Download Telegram
Как из РФ создать новую учётку в Gitlab

У ребят в Linux Factory довольно часто возникает вопрос — а как зарегистрировать новую учетку в Gitlab?

Онож там и карту просит и смс и еще хуй пойми чего.

Вариантов есть много, но работают они 50 на 50. У кого-то работает одно, у кого-то другое, но нет золотой середины.

Сейчас я покажу 100% рабочий вариант.

Регистрируешься в Putsbox. Это сервис для временных почтовых ящиков. Проверен лично мной годами, никогда не косячит.

Про этот сервис я как-то давненько рассказывал здесь.


Тут важно зарегистрироваться, а не просто создать новый ящик.

Это важно, потому что Gitlab рано или поздно снова запросит подтвердить твою личность и отправит код на почту. А если ты не порегаешься в putsbox, то ящика того самого не будет.

Короче регаешься в putsbox, входишь в учетку и создаешь почтовый ящик.

Дальше скачиваешь себе TOR Browser и регаешься в Gitlab на ящик который создал в ранее. Проходишь капчу, челенджи с количеством камней и т.п. Да, будет подтормаживать, но за пару минут управишься.

После регистрации на ящик в putsbox приходит код с подтверждением, подтверждаешь. Закрываешь TOR Browser.

Идешь в свой браузер и без проблем залетаешь в Gitlab под новой учёткой.

Без карт, смс и прочей хуиты. Если в будущем оно попросит тебя снова подтвердить личность, идешь в старый ящик putxbox и подтверждаешь.

А если запуск пайплайнов требуют верификации, то читаем этот пост.


На самом деле всё просто. Единственный момент — TOR Browser, возможно сразу он у тебя не запустится, нужно будет поиграть с мостами либо заранее подключить VPN. Короче тут сам разберешься, это уже дело третье.

Если такая ебатория не по тебе, можешь локально Gitlab воткнуть. В этом посте я по шагам показал как это сделать. И не нужно думать что эта тварь сильно прожорливая, под лабу хватит минимального конфига по железу.


Такие дела, тыкай, изучай.

🛠 #linuxfactory #gitlab #services

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
647
Очередные грабли. При клонировании Linux машин, клонированные машины получают по DHCP тот же IP адрес, что и донор. Возникает конфликт интересов.

Проблема распространенная, лечится довольно просто.

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 адрес, который не будет конфликтовать с донором.

Вот и вся наука. Пользуйся.

🛠 #linux #linuxfactory

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
88
Распространенный случай в пайплайнах, как ребята пишут в LF:

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_configMaxSessions, а плюсом еще работает Fail2ban или нечто подобное.

И по итогу пайплайн будет вечно делать хуйню, внезапно падать и т.п.

Что делать?

Передать команды в рамках одной сессии.

Например, так:

script:
- |
ssh ${USER}@${HOST} << EOF
docker pull ...
docker down ...
docker up -d ...
...
EOF


В YAML, конструкция | перед блоком многострочного текста указывает, как обрабатывать переносы строк. | означает: сохраняй все переносы строк, как они написаны.


Либо пропихать так:

script:
- ssh ${USER}@${HOST} "docker pull ...; docker down ...; ..."


Но предпочтительнее первый вариант, он консистентный и более читаемый.

Учись сразу делать нормально и учитывать такие моменты.

Ну и с праздником тебя и твоих ребятишек!

🛠 #devops #linuxfactory #cicd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
782
Довольно частый вопрос с LFКак жить с gitlab раннерами?

Да просто там всё. Если у тебя основная инфра в кубе, то в кубе и крутим.

Ну а если ламповые сервера, без всей этой кубовой хуйни, то вариантов не много.

Заводим себе отдельный сервер/сервера, чисто под раннеры. Заводим с учетом на то, что на этих серверах будут собираться докер образы. Со временем место будет забиваться.

Здесь важно раздуплить себе какой-нибудь гарбаж коллектор, либо башник в крону накидать.

Часто раннеры пихают прям на продакшен сервера, где крутятся все бизнес процессы. В этом случае продакшен превращается в помойку, нагрузка постоянно скачет при сборках/деплое и т.п.

Это хуёвая практика, на продакшене такого быть не должно. Лишь поэтому мы и поднимаем отдельный сервер под раннеры.


Подняли сервер, нарегали нужных раннеров. В идеале это процесс автоматизировать, ансибл-хуянсибл ну или чё там у тебя есть.

Раннеры можно зарегать на один токен:

Сервер 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 раннеров — ты с ними заебешься, поэтому на моменте регистрации, сделай себе табличку, пропиши в них теги раннеров и на каких серверах они у тебя живут. Опять же это можно сделать через ансибл-роль, либо скриптом генерить. Тут уже сам наколдуешь.

Основное рассказал, если что-то еще вспомню, накидаю. Если у тебя есть мысли, пиши в комментарии, будем обсуждать.

🛠 #devops #linuxfactory #cicd

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
456
GIT для девопс-инженера

Многих 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.

🛠 #git #devops

@bashdays @linuxfactory @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
68
Разбираемся с options и inputs в gitlab

Частенько ребята с LF стали приходить с такой проблемой:

stages:
- deploy
variables:
ENVIRONMENT:
description: "Deployment environment"
value: "N/A"
options:
- "N/A"
- "STAGE"
- "PRODUCTION"
deploy:
stage: deploy
script:
- echo "Выбрано окружение:" "${ENVIRONMENT}"
rules:
- when: manual


Это кусок говна пайплайна, который при запуске формирует выпадающий список окружений, выбираешь окружение и деплой проходит в него.

НО — этот список перестал появляться. Причем избрано, у кого-то есть, у кого-то хуй с маслом.


Ошибок синтаксиса в ямликах нет, каких-то разумных сообщений и наводок от гитлаба тоже нет. Чё делать?

➡️ Решение

Идем: Settings → CI/CD → Variables и кликаем в радио-батон — Developer.

Всё! Теперь выпадающие списки вновь начинают работать.

А еще людей смущает новая штука inputs, которая совсем недавно появилась. Работает она с 17й версии.

spec:
inputs:
environment:
description: "Куда деплоим?"
type: string
default: "N/A"
options:
- "N/A"
- "STAGE"
- "PRODUCTION"
---
stages:
- deploy

deploy:
stage: deploy
rules:
- when: manual
script:
- echo "Выбрано окружение: $[[ inputs.environment ]]"


Оно будет пиздеть во внутреннем редакторе - Incorrect type. Expected "string | array".yaml-schema, но будет работать если запустить пайплайн.

Ошибка возникает, потому, что Pipeline Editor использует старый YAML-валидатор. Так что, не обращай внимание на этот пиздёж.


А зачем нам этот input ведь с options и так всё работает?

Ну хотя бы из-за типизированных параметров:

type: string | number | boolean | array


То есть:

- можно сделать чекбокс (boolean)
- можно сделать список (array)
- можно сделать ограничение по диапазону (number)
- можно сделать строгие варианты (options)
- можно сделать regex-валидацию

А обычный variables такого не умеют.

GitLab постепенно превращает CI в настоящий «Pipeline as Functions».

Например, в проекте А:

spec:
inputs:
env:
type: string
options: [stage, prod]
---
deploy-job:
script: deploy_to $[[ inputs.env ]]


И проекте B можно вызвать:

deploy:
trigger:
project: A
inputs:
env: prod


Это как вызов функции с аргументом.

Что еще:

- Inputs работают даже при trigger-пайплайнах
- Inputs могут быть required
- Inputs отображаются отдельно и аккуратно в UI
- Inputs часть нового стандарта GitLab CI Components

Короче одни плюсы. Но есть большое НООООО!

Это пиздец усложняет процесс разработки и отладку пайплайна.

Да, стало удобнее и гибче, но всё это превращается в безумное ООП, где без базы и документации к проекту — ты хуй разберешься.

Пока тебе хватает обычных options используй их. Не лезь в это ООП, оно пока рано и избыточно, особенно если ты новичок.

Изучай!

Как говорится — и не такие метели в ебало летели!

🛠 #devops #cicd #linuxfactory

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
745
Docker Privileged VS Non-privileged

Как говорится — «Нам нужно досье на этого мисье»


Давай сразу к примерам:

➡️ Non-privileged

Ты ребёнок, тебя посадили в песочницу, дали совок и формочки, сказали — слышь еблан, играть можно только здесь!

Ты можешь:

— лепить куличики и кренделя
— копать ямки и могилки для жуков
— сыпать песочек в глаза другим детям
— строить свой маленький мир

Ты не можешь:

— вылазить из песочницы
— пойти на стройку и доебывать сторожа
— насрать в ладошку и кидаться этим в людей
— послать всех нахуй и сделать по своему

Ты работаешь строго в пределах песочницы. Безопасно, предсказуемо, контролируемо, изолировано. Ты бездушный non-privileged контейнер.

➡️ Privileged

Ты ребёнок, но всем на тебя поебать, ты сам выбираешь сидеть тебе в песочнице или кидаться с балкона кирпичами в пустые головы прохожих. У тебя развязаны руки, любые безумные поступки позволительны. У тебя есть ключи от всех дверей и тебе за это ничего не будет.

Всё это происходит, когда ты запускаешь:

docker run --privileged


Твой контейнер может:

— управлять сетевыми интерфейсами хоста
— лезть в /dev
— монтировать что угодно куда угодно
— работать как полноценная виртуалка
— запускать systemd, модифицировать ядро, iptables, модули и т.п

То есть, это уже не ребёнок в песочнице, а ребёнок со швейцарским армейским ножом, запертый в серверной.

➡️ Non-privileged (обычный контейнер)

- Ограниченный доступ к Linux capabilities
- Нет доступа к аппаратным устройствам
- Нет прав на управление сетью хоста
- Запуск отдельных процессов, а не мини-ОС
- Работает в namespace'ах и cgroup'ах изоляции

Используется для:

- веб-сервисов
- приложений
- баз данных
- CI/CD runner’ов (если привилегия не нужна)
- всего, что «из коробки» работает в Docker

➡️ Privileged (контейнер-всевластия)

- Доступ ко всем Linux capabilities
- Может лезть в /dev, работать с устройствами
- Может менять сетевые интерфейсы хоста
- Может работать как виртуалка
- Может запускать systemd
- Может cломать или убить сеть, firewall и модули ядра

Используется для:

- контейнеров, которым нужны реальные устройства
- low-level инструментов: tcpdump, wireshark, iptables
- Docker-in-Docker в особых сценариях
- Kubernetes kubelet / CNI плагины
- экспериментов, когда нужно «полный root над всем»

Что выбрать?

Мой алгоритм:

Задача не требует низкоуровневых операций?
всегда non-privileged.

Нужно одно конкретное действие (например NET_ADMIN)?
--cap-add вместо privileged.

Нужен доступ к устройству?
--device вместо полного доступа.

Ничего из этого не помогает?
тогда уже --privileged.


В большинстве случаев лучше выдать минимум необходимых прав, чем сразу открывать ящик пандоры.

Ну и для отладки privileged прям мастхев, чтобы исключить какие-то внешние факторы, от которых могут лезть баги.

На днях продолжим…

🛠 #linuxfactory #linux #docker

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Please open Telegram to view this post
VIEW IN TELEGRAM
1366
Настройка Yubikey + WSL2 + SSH (Часть 2)

Первая часть тут: https://xn--r1a.website/bashdays/1357

Создаём SSH ключ:

ssh-keygen -t ed25519-sk -O resident -C "shuba@bashdays"


Оно запросит у тебя PIN который мы впендюрили в самом начале. Жмем несколько раз Enter и радуемся жизни. Новый приватный ключ создан, записан на Yubikey, публичная же часть ключа упала в ~/.ssh/id_ed25519_sk.pub.

Да, рядом будем лежать файл id_ed25519_sk, но это ничего не меняет, это не приватный ключ, приватный ключ НЕ хранится на диске, он сразу записывается в Yubikey. А то что ты видишь у себя на диске, это дескриптор (handle). Этот файл содержит идентификатор Yubikey ключа, параметры и ссылку на resident key. Приватный ключ физически находится внутри YubiKey и не может быть извлечён.


А дальше по классике. Закидываем публичную часть ключа на нужный сервер и пробуем подключиться:

ssh root@bashdays.ru

Confirm user presence for key ED25519-SK


Опа, прикасаемся своим обрубком к Yubikey и успешно подключаемся к серверу. Также можно сгенерить ключ, который не требует прикосновений, либо вообще сгенерить одноразовые пины, но это уже оверхед безопасность.

Про SSH ключи я подробно расписывал в серии постов по тегу #linuxfactory нажми на тег, получишь список всех этих постов. Настоятельно рекомендую ознакомиться, такому в школах не учат. По крайней мере не рассказывают нюансы.


Фиксим баги:

После того как ты достанешь ключ из USB и затем воткнешь обратно. Всё к хуям сломается. Вот такая особенность винды и WSL2. Поэтому делаем финт ушами. Пишем powershell скрипт, который будет это фиксить.

Создаем файл YubiKeyAttachToWSL.ps1

$yubiKeyBusId = (usbipd list | Select-String "1050:0407" |
ForEach-Object { $_.Line.Split()[0] })
if ($yubiKeyBusId) {
usbipd attach --wsl --busid $yubiKeyBusId
Write-Host "YubiKey attached…"
} else {
Write-Host "YubiKey not found."
}


Не забываем изменить ID вендора и продукта. Закидываем скрипт в виндовый планировщик с параметрами:

Триггер:

- At log on (при входе в систему)
- On Event (событие USB)
- Log: System, Source: WudfUsbccidDrv, Event ID: 104

Действие:

- Запуск powershell.exe с аргументами -ExecutionPolicy Bypass -File "C:\YubiKeyAttachToWSL.ps1"

Теперь этот скрипт будет запускать при входе в систему ну и если ты будешь тыркать Yubikey туда-сюда в USB портах. Автоматизация ёпта!

Всё! Поставленная задача успешно решена. Что важно, тут не только потыкали Yubikey + SSH, но и научились прокидывать USB устройства в WSL2.

Всё остальное поищешь сам, информации полно. Я показал тебе лишь неочевидные штуки, которые могут загнать в тупик и свести с ума.

Изучай!

🛠 #security #privacy

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Please open Telegram to view this post
VIEW IN TELEGRAM
22
Контекстная конфигурация в git

При работе с git репозиториями, частенько попадаешь в просак с таким:

git config --global user.name
git config --global user.email


Один раз забил свои явки-пароли и затем git при любом коммите или пуше будет подставлять эти данные. То есть в историю коммитов будет забиваться user.name и user.email. Это логично и понятно.

Но если у тебя смешаны личные и рабочие репозитории, начинается цирк с конями. Я тысячу раз комитил в рабочую репу под личным user.name и user.email и получал за это по рукам. Получал конечно сам от себя.

Потому что смешивать личное и рабочее — фуфу!


Из этой ситуации можно выйти по-разному, кто-то изобретает безумные Bash скрипты или пишет хуки, кто-то постоянно правит конфиги перед пушем. Короче костыль на костыле. Но есть решение лучше и нативнее.

Расчехляем хоумлабу!

У нас будет 2 папки:

mkdir -p ~/projects/personal
mkdir -p ~/projects/work


Настраиваем основной конфиг:

vim ~/.gitconfig


[user]
name = Roman Shubin
email = shuba@bashdayz.ru

[includeIf "gitdir:~/projects/work/"]
path = ~/.gitconfig_work


Нюанс: / в конце work обязателен. Git интерпретирует gitdir: как префикс пути к каталогу .git.

Создаем рабочий конфиг ~/.gitconfig_work

[user]  
name = Linux Factory
email = exe@linuxfactory.ru


На этом танцы с бубном закончились, проверяем:

mkdir -p ~/projects/personal/app  
cd ~/projects/personal/app
git init

git config user.email
git config --show-origin user.email


Ага, видим что для личных проектов будет применяться shuba@bashdayz.ru и берется он из ~/.gitconfig. Последние 2 команды, как раз выводят эту информацию в терминал. Хорошо, теперь:

mkdir -p ~/projects/work/app  
cd ~/projects/work/app
git init

git config user.email
git config --show-origin user.email


Да твоюж мать! Видим Linux Factory и exe@linuxfactory.ru. Что и требовалось доказать, данные берутся из файла ~/.gitconfig_work.

Всё, мы успешно разделили контекст между личными и рабочими проектами. Таких инклудов ты можешь насоздавать сколько угодно. Самое главное это работает без костылей и каких-то лишних обвесов вокруг git.

Git скрывает очень много интересного и не всегда это очевидно. Такие дела, изучай!

🛠 #devops #linuxfactory #dev

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Please open Telegram to view this post
VIEW IN TELEGRAM
199
Когда начинаешь вкатываться в Ansible, кажется что loop нужен вот прям всегда и везде. Но это не так.

Многие пишут:

- name: install packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
update_cache: yes
loop: "{{ packages }}"


А переменная packages содержит список пакетов на установку.

И вроде тут всё ок, НО apt вызывается для каждого пакета отдельно, а update_cache может дёргаться несколько раз. Это избыточно и ломает заложенные паттерны.

Поэтому правильнее будет сделать так:

- name: install packages
ansible.builtin.apt:
name: "{{ packages }}"
state: present
update_cache: yes


Здесь apt получает сразу список пакетов, кеш обновляется один раз, установка идёт одной транзакцией. Получается меньше оверхеда, всё происходит быстрее и логичнее.

В первом случае это «хак», ты делаешь loop из одного элемента, внутри которого уже лежит список.

Главная мысль тут — если модуль умеет принимать список — loop нахуй не нужен.

Loop нужен там, где логика на каждый элемент отдельная:

- разные параметры
- условия
- шаблоны
- создание пользователей
- файлы
- сложные таски

Короче не заLOOPайся и будет тебе счастье.

Ну а если хочешь стать гуру, я всегда жду тебя здесь.


🛠 #devops #linuxfactory #ansible

💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Please open Telegram to view this post
VIEW IN TELEGRAM
284