Украденный секрет опасен ровно настолько, насколько широки его права доступа. В большинстве CI/CD-пайплайнов права выдаются с запасом, ведь так проще настроить, но это и есть главная проблема.
Если токен деплоя утечёт, злоумышленник получит доступ ко всему, что этот токен может делать. Если права ограничены только деплоем, то и ущерб минимален. Если токен читает продовую базу и ходит в сторонние сервисы — ущерб катастрофический.
Разделите секреты по ролям:
• Задача сборки (
build) компилирует код. Ей не нужны никакие облачные креды вообще. Если они там есть — уберите.• Задача тестирования (
test) работает с тестовыми данными. Она не должна видеть продовые креды. Заведите отдельные credentials для тест-окружения с доступом только на чтение к тестовой базе.• Задача деплоя (
deploy) — единственная, которой нужны продовые секреты. И только те, что нужны именно для деплоя, ничего лишнего.Раз в квартал проводите аудит секретов. Удаляйте всё, что не используется ни одной задачей прямо сейчас.
Пример для GitHub Actions
GitHub Actions позволяет привязать секреты к конкретным
environments. Продовые секреты становятся доступны только при деплое в production, а не во всех задачах подряд:jobs:
test:
runs-on: ubuntu-latest
# Продовых секретов здесь нет
# Тесты используют моки или тестовую базу
env:
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
deploy:
runs-on: ubuntu-latest
environment: production # Отдельный scope секретов + требует подтверждения
needs: test # Запускается только после успешных тестов
env:
# Продовые секреты доступны только здесь
AWS_ROLE_ARN: ${{ secrets.PROD_AWS_ROLE_ARN }}
Ключевой момент: параметр
environment: production не просто логическая метка. Он изолирует секреты этого environment от других задач и, по умолчанию, требует ручного подтверждения перед запуском деплоя.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🥱1
Атака на
axios сработала потому, что злоумышленник получил долгоживущий классический токен npm от аккаунта мейнтейнера. Если бы была включена 2FA, одного токена не хватило бы для публикации новой версии пакета.Как включить 2FA
Для личного аккаунта:
npm profile enable-2fa auth-and-writes
Режим
auth-and-writes требует второй фактор и при входе, и при публикации. Это сильнее, чем auth-only, который защищает только вход, но не публикацию.Для организации нужны права администратора:
npm access 2fa-required --otp=ВАШ_КОД your-org
Либо через интерфейс: Organisation Settings > Security > Require two-factor authentication.
Что ещё стоит сделать
Классические токены npm живут вечно и дают широкий доступ. В 2022 году появились гранулярные токены. Они ограничены конкретными пакетами и позволяют задать режим
read-only или publish-only. Переходите на них.Классические токены, которые существуют больше 90 дней, стоит проверить и пересоздать. Найти их можно в Account Settings > Access Tokens.
Если разработчик ушёл из команды, то сразу отзывайте его доступ к публикации. npm не делает это автоматически, права сохраняются бессрочно.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Ручной
mysqldump работает ровно до того момента, пока кто-то не забыл его запустить. Для продакшна нужен автоматический запуск по расписанию.Скрипт с ротацией и сжатием
Создаём файл
/opt/scripts/mysql-backup.sh:#!/bin/bash
BACKUP_DIR="/opt/backups/mysql"
CONTAINER="mysql-container"
DB_USER="root"
DB_PASS="yourpassword"
DATABASE="mydatabase"
RETENTION_DAYS=7
mkdir -p "$BACKUP_DIR"
FILENAME="$BACKUP_DIR/${DATABASE}_$(date +%Y%m%d_%H%M%S).sql.gz"
docker exec "$CONTAINER" mysqldump \
-u "$DB_USER" -p"$DB_PASS" \
--single-transaction \
--routines \
--triggers \
"$DATABASE" | gzip > "$FILENAME"
if [ $? -eq 0 ]; then
echo "Backup completed: $FILENAME"
else
echo "Backup failed!" >&2
exit 1
fi
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
Флаг
--single-transaction снимает дамп без блокировки таблиц — важно для InnoDB в продакшне. --routines и --triggers включают в дамп хранимые процедуры и триггеры, которые по умолчанию не экспортируются. find в конце удаляет файлы старше RETENTION_DAYS дней.Добавляем в cron. Запуск каждый день в 4 утра:
0 4 * * * /opt/scripts/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1
Ограничения
Для небольшого пет-проекта этого хватит. Но у подхода есть три слабых места, которые становятся проблемой при серьёзной нагрузке.
Нет алертов при сбое. Скрипт пишет ошибку в лог, но никто не узнает об этом, пока не заглянет туда вручную. Бэкап может не работать неделями без каких-либо уведомлений.
Файлы хранятся локально. Если сервер упадёт или диск сгорит, бэкапы уйдут вместе с данными. Для надёжности нужен вывод в S3 или другое внешнее хранилище.
Плохо масштабируется. Несколько баз — значит несколько копий скрипта, которые нужно поддерживать отдельно.
Для проекта, потеря данных в котором некритична, этот скрипт закрывает задачу. Для всего остального эти три пункта рано или поздно дадут о себе знать.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
☕️ Java и лимиты
Запускаете Java-приложение и через час получаете звонок, что сервер лежит? Знакомо.
По умолчанию JVM берёт столько памяти и CPU, сколько захочет. На проде это боль. Разберёмся, как это починить.
Память
Два главных флага:
•
•
Ставьте
CPU / потоки
Ограничить количество потоков GC и компилятора:
Особенно актуально в Docker/Kubernetes, ведь JVM видит все ядра хоста, а не контейнера. Без этого флага она создаст лишние потоки и будет драться за ресурсы.
Если запускаете в контейнере
Начиная с Java 11+ JVM умеет читать cgroup-лимиты контейнера автоматически. Но лучше явно включить:
И добавьте
📌 Итого: минимальный набор для продакшена
Дальше смотрите на метрики и подкручивайте под своё приложение.
➡️ Больше про Java без воды в канале. Подписывайтесь, там научат делать Java-Java
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
Запускаете Java-приложение и через час получаете звонок, что сервер лежит? Знакомо.
По умолчанию JVM берёт столько памяти и CPU, сколько захочет. На проде это боль. Разберёмся, как это починить.
Память
Два главных флага:
•
-Xms512m — сколько памяти выделить сразу при старте•
-Xmx2g — максимум, выше которого heap не вырастетjava -Xms512m -Xmx2g -jar app.jar
Ставьте
-Xmx всегда. Без него JVM может решить, что ей нужна половина RAM сервера и будет права по своей логике.CPU / потоки
Ограничить количество потоков GC и компилятора:
-XX:ActiveProcessorCount=2
Особенно актуально в Docker/Kubernetes, ведь JVM видит все ядра хоста, а не контейнера. Без этого флага она создаст лишние потоки и будет драться за ресурсы.
Если запускаете в контейнере
Начиная с Java 11+ JVM умеет читать cgroup-лимиты контейнера автоматически. Но лучше явно включить:
-XX:+UseContainerSupport
И добавьте
-Xmx через переменную окружения, чтобы удобно менять без пересборки:JAVA_OPTS="-Xms256m -Xmx1g -XX:ActiveProcessorCount=2"
java $JAVA_OPTS -jar app.jar
📌 Итого: минимальный набор для продакшена
-Xms256m
-Xmx1g
-XX:ActiveProcessorCount=2
-XX:+UseContainerSupport
Дальше смотрите на метрики и подкручивайте под своё приложение.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🧑💻 Kernel Panic при загрузке: находим причину и чиним
Сервер не поднимается после перезагрузки. Экран с kernel panic, и всё. Это одна из тех ситуаций, когда важно действовать методично, а не наугад.
Что обычно ломается
Три самые частые причины:
• Повреждённый
• Проблемы с GRUB. После обновления ядра или ручной правки конфига загрузчик может потерять путь к системе.
• Аппаратные сбои. Отказ диска или памяти тоже проявляется как panic при загрузке, поэтому железо стоит проверить сразу.
Как чинить
Загружаемся в recovery mode. В меню GRUB выбираем
Проверяем диск:
Сверяем UUID в
Вывод покажет реальные UUID всех разделов. Открываем
Если проблема в GRUB, переустанавливаем его:
Как не попасть в это снова
Перед любыми правками в
Изменения в загрузочной конфигурации тестируем на staging-окружении. Продакшн-сервер — плохое место для экспериментов с GRUB.
Если инфраструктура позволяет, настраиваем снапшоты перед каждым обновлением ядра. Откатиться за 30 секунд гораздо приятнее, чем чинить вручную в 3 ночи.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
Сервер не поднимается после перезагрузки. Экран с kernel panic, и всё. Это одна из тех ситуаций, когда важно действовать методично, а не наугад.
Что обычно ломается
Три самые частые причины:
• Повреждённый
/etc/fstab. Если UUID раздела не совпадает с тем, что прописано в файле, система не может смонтировать диск и падает на старте.• Проблемы с GRUB. После обновления ядра или ручной правки конфига загрузчик может потерять путь к системе.
• Аппаратные сбои. Отказ диска или памяти тоже проявляется как panic при загрузке, поэтому железо стоит проверить сразу.
Как чинить
Загружаемся в recovery mode. В меню GRUB выбираем
Advanced options и строку с (recovery mode). Получаем root-шелл без монтирования основной системы.Проверяем диск:
fsck -f /dev/sda1
fsck найдёт и исправит ошибки файловой системы. Флаг -f запускает проверку даже если диск помечен как чистый.Сверяем UUID в
/etc/fstab:blkid
Вывод покажет реальные UUID всех разделов. Открываем
/etc/fstab и проверяем, что значения совпадают. Расхождение в одном символе — и система не загрузится.Если проблема в GRUB, переустанавливаем его:
grub-install /dev/sda
update-grub
/dev/sda — диск, не раздел. Убедитесь, что указываете устройство без цифры на конце.Как не попасть в это снова
Перед любыми правками в
/etc/fstab или конфигах загрузчика делаем бэкап:cp /etc/fstab /etc/fstab.bak
Изменения в загрузочной конфигурации тестируем на staging-окружении. Продакшн-сервер — плохое место для экспериментов с GRUB.
Если инфраструктура позволяет, настраиваем снапшоты перед каждым обновлением ядра. Откатиться за 30 секунд гораздо приятнее, чем чинить вручную в 3 ночи.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥2🌚1
В Linux права определяются не именем пользователя, а его UID. У root всегда UID=0. Если создать пользователя с тем же UID=0, система будет воспринимать его как root со всеми вытекающими правами.
Добавляем запись напрямую в /etc/passwd. Открываем файл:
sudo vipw
Добавляем строку в конец файла:
superadmin:x:0:0:Super Admin:/root:/bin/bash
Ставим пароль новому пользователю:
sudo passwd superadmin
Проверяем, что всё работает:
id superadmin
#uid=0(root) gid=0(root) groups=0(root)
Альтернатива через useradd
Команда useradd не позволяет напрямую задать UID=0, но можно создать пользователя и потом поправить запись:
sudo useradd -o -u 0 -g 0 -d /root -s /bin/bash superadmin
sudo passwd superadmin
Флаг
-o разрешает дублирование UID. Без него команда завершится с ошибкой.Если вы используете sudo, убедитесь что новый пользователь тоже может его вызывать. Добавьте строку в /etc/sudoers через visudo:
superadmin ALL=(ALL:ALL) ALL
Такой подход используют в нескольких сценариях: аварийный доступ при утере основного пароля, автоматизация через отдельный сервисный аккаунт с полными правами, или командная работа где нескольким людям нужен root без общего пароля.
Два аккаунта с UID=0 означают двойную поверхность атаки. Следите за тем, кому и зачем открываете такой доступ и включайте аудит действий через
auditd или аналоги.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🚮 Drop правила для фильтрации мусорных логов
Если вы используете Grafana Cloud Logs, скорее всего, часть логов там вообще не нужна. Health check каждые 5 секунд, DEBUG-записи из забытого сервиса, многословный INFO из batch-джобы — всё это идёт в хранилище и увеличивает счёт.
Раньше убрать этот мусор было неудобно. Нужно было лезть в конфиги, договариваться с командами, менять пайплайн. Теперь в Adaptive Logs появились drop rules — правила, которые отфильтровывают ненужные логи до записи в хранилище.
Что делают drop rules
Правило задаёт условие: какие логи отбрасывать и с какой долей. Можно указать лейбл сервиса, уровень лога, строку в теле — или всё вместе. Поддерживается частичный дроп: например, оставить 10% от потока, а остальное не сохранять.
Несколько сценариев, где это полезно:
Если
Batch-джоба пишет одно и то же тысячи раз в день. Оставляем 10% для выборки:
Выбросить конкретный паттерн. Сервис пишет
Как это работает внутри
Каждый входящий лог проходит три шага по порядку:
1. Exemptions — если лог попадает под исключение, он записывается без изменений.
2. Drop rules — правила применяются по приоритету. Первое совпавшее правило задаёт процент дропа.
3. Patterns — к оставшимся логам применяются рекомендации от самого Adaptive Logs на основе анализа 15 дней запросов.
Exemptions нужны для логов, которые нельзя терять ни при каких условиях, — аудит, ошибки из критичных сервисов. Drop rules — для того, что точно не нужно. Patterns — для всего остального, что Grafana сама определит как малоценное.
Как начать
Функция доступна в public preview в Grafana Cloud. Нужна роль
Путь в интерфейсе:
Adaptive Telemetry → Adaptive Logs → Drop rules → Create a new drop rule
Управлять правилами также можно через CLI
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
Если вы используете Grafana Cloud Logs, скорее всего, часть логов там вообще не нужна. Health check каждые 5 секунд, DEBUG-записи из забытого сервиса, многословный INFO из batch-джобы — всё это идёт в хранилище и увеличивает счёт.
Раньше убрать этот мусор было неудобно. Нужно было лезть в конфиги, договариваться с командами, менять пайплайн. Теперь в Adaptive Logs появились drop rules — правила, которые отфильтровывают ненужные логи до записи в хранилище.
Что делают drop rules
Правило задаёт условие: какие логи отбрасывать и с какой долей. Можно указать лейбл сервиса, уровень лога, строку в теле — или всё вместе. Поддерживается частичный дроп: например, оставить 10% от потока, а остальное не сохранять.
Несколько сценариев, где это полезно:
Если
payment-service в продакшне шлёт DEBUG-логи, которые никто не смотрит:service_name = payment-service
log_level = DEBUG
drop rate = 100%
Batch-джоба пишет одно и то же тысячи раз в день. Оставляем 10% для выборки:
service_name = batch-processor
drop rate = 90%
Выбросить конкретный паттерн. Сервис пишет
GET /healthz 200 каждые несколько секунд. Указываем строку в теле лога и дропаем 100%.Как это работает внутри
Каждый входящий лог проходит три шага по порядку:
1. Exemptions — если лог попадает под исключение, он записывается без изменений.
2. Drop rules — правила применяются по приоритету. Первое совпавшее правило задаёт процент дропа.
3. Patterns — к оставшимся логам применяются рекомендации от самого Adaptive Logs на основе анализа 15 дней запросов.
Exemptions нужны для логов, которые нельзя терять ни при каких условиях, — аудит, ошибки из критичных сервисов. Drop rules — для того, что точно не нужно. Patterns — для всего остального, что Grafana сама определит как малоценное.
Как начать
Функция доступна в public preview в Grafana Cloud. Нужна роль
plugins:grafana-adaptivelogs-app:admin — по умолчанию она есть у Grafana Admin и Org Admin.Путь в интерфейсе:
Adaptive Telemetry → Adaptive Logs → Drop rules → Create a new drop rule
Управлять правилами также можно через CLI
gcx если нужна автоматизация или интеграция с агентами.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
Иногда нужен простой список подов и их образов. Без лишних колонок, без шума.
kubectl get pods -o wide выдаёт слишком много данных, которые в этот момент не нужны.Для таких случаев есть флаг
-o custom-columns. Он позволяет выбрать только те поля, которые важны прямо сейчас.Чтобы получить таблицу с именем пода и образом контейнера, достаточно одной команды:
kubectl get pods -o custom-columns='NAME:.metadata.name,IMAGE:.spec.containers[*].image'
Результат — чистая таблица без лишнего.
[*] в пути означает, что команда учитывает все контейнеры в поде, включая сайдкары.Формат колонки строится по простому правилу: сначала заголовок, потом путь к полю в JSON-структуре объекта. Любое поле из
kubectl get pod -o json можно вытащить таким же способом.Это особенно удобно в скриптах и CI, где важна предсказуемость вывода. Никаких сюрпризов при обновлении версии
kubectl.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
🧑💻 5 базовых команд девопса
➡️ Команда
Везде, где нужно быстро понять объём:
Набирать
Теперь вместо
Работает и с пайпами:
37 пятисотых ошибок. Быстро и понятно.
➡️
Когда заканчивается место на диске, первым делом хочется понять, кто его съел.
Если нужно отсортировать по размеру, добавляем
Флаг
➡️
Если в именах файлов есть пробелы, безопаснее использовать разделитель через null:
Ещё полезный приём. Посчитать общее количество строк во всех Python файлах проекта:
➡️
Вывод многих команд выглядит как каша из слов, разделённых пробелами.
Хорошо работает с CSV, если указать разделитель:
➡️
Эта команда будет каждые 2 секунды показывать состояние дисков. Удобно, когда ждёте, пока освободится место, или следите за каким-то процессом.
Можно изменить интервал через
Каждые 5 секунд обновляет статус подов. Проще, чем жать стрелку вверх и Enter раз за разом.
Все эти команды работают в любом Linux и macOS из коробки. Ничего ставить не нужно.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
wc -l считает строки в файле или в пайпе. Одна из тех вещей, которые используешь каждый день. Логи, CSV, исходники, конфиги. Везде, где нужно быстро понять объём:
$ wc -l server.log
4821 server.log
Набирать
wc -l несложно, но можно сделать ещё проще. Создаём алиас lc (line count) и добавляем в конфиг шелла:# Добавьте в ~/.bashrc или ~/.zshrc, затем: source ~/.bashrc
alias lc='wc -l'
Теперь вместо
wc -l пишем просто lc:$ lc server.log
4821 server.log
Работает и с пайпами:
$ cat access.log | grep "500" | lc
37
37 пятисотых ошибок. Быстро и понятно.
du -sh * — сколько весит каждая папкаКогда заканчивается место на диске, первым делом хочется понять, кто его съел.
du -sh * покажет размер каждого элемента в текущей директории в человекочитаемом формате:$ du -sh *
1.2G node_modules
4.0K README.md
256M dist
12K src
node_modules на первом месте. Как обычно.Если нужно отсортировать по размеру, добавляем
sort:$ du -sh * | sort -rh
1.2G node_modules
256M dist
12K src
4.0K README.md
Флаг
-r сортирует по убыванию, -h понимает суффиксы K, M, G.xargs — передать результат одной команды как аргументы другойxargs берёт строки из stdin и подставляет их как аргументы. Например, найти все .log файлы и удалить их:$ find /tmp -name "*.log" | xargs rm
Если в именах файлов есть пробелы, безопаснее использовать разделитель через null:
$ find /tmp -name "*.log" -print0 | xargs -0 rm
Ещё полезный приём. Посчитать общее количество строк во всех Python файлах проекта:
$ find . -name "*.py" | xargs wc -l
column -t — превратить текст в ровную таблицуВывод многих команд выглядит как каша из слов, разделённых пробелами.
column -t выравнивает столбцы и делает вывод читаемым:$ cat data.txt
name age city
alice 30 berlin
bob 25 munich
$ column -t data.txt
name age city
alice 30 berlin
bob 25 munich
Хорошо работает с CSV, если указать разделитель:
$ column -t -s',' users.csv
watch — повторять команду каждые N секундwatch запускает любую команду с заданным интервалом и обновляет вывод в терминале. По умолчанию интервал 2 секунды:$ watch df -h
Эта команда будет каждые 2 секунды показывать состояние дисков. Удобно, когда ждёте, пока освободится место, или следите за каким-то процессом.
Можно изменить интервал через
-n:$ watch -n 5 kubectl get pods
Каждые 5 секунд обновляет статус подов. Проще, чем жать стрелку вверх и Enter раз за разом.
Все эти команды работают в любом Linux и macOS из коробки. Ничего ставить не нужно.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍5
Кто-то поправил инфраструктуру руками через консоль. Terraform об этом ничего не знает. При следующем
terraform apply начинаются конфликты, откаты и разбор полётов. Это называется drift. Состояние инфраструктуры разошлось с тем, что описано в коде. Terraform сам по себе drift не отслеживает. Но у него есть инструмент, который помогает это делать.
Как обнаружить drift
У
terraform plan есть флаг -detailed-exitcode. Он возвращает разные коды выхода в зависимости от результата.terraform plan -detailed-exitcode
Код
0 означает, что изменений нет. Код 1 говорит об ошибке. А вот код 2 сигнализирует, что план нашёл расхождения между стейтом и реальной инфраструктурой. Именно код 2 и есть индикатор drift.Проверять это вручную каждый раз неудобно. Гораздо надёжнее встроить проверку в CI. Например, в GitHub Actions это можно сделать так:
name: Drift Detection
on:
schedule:
- cron: '0 9 * * 1'
jobs:
detect-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform plan -detailed-exitcode
continue-on-error: true
id: plan
- run: echo "Drift detected!"
if: steps.plan.outcome == 'failure' && steps.plan.outputs.exitcode == '2'
Этот воркфлоу запускается раз в неделю по понедельникам. Если
plan вернул код 2, значит, кто-то менял инфру в обход Terraform. Аналогичную логику можно настроить и в Jenkins через проверку $? после выполнения команды.Drift неизбежен в командах, где инфраструктурой занимается больше одного человека. Регулярная автоматическая проверка через CI помогает поймать расхождения до того, как они превратятся в проблему на проде.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
su и sudo дают доступ к привилегиям суперпользователя, но работают по-разному.Что делает su
su (substitute user) переключает текущую сессию на другого пользователя. По умолчанию — на root. При вызове команда запрашивает пароль того пользователя, на которого вы переключаетесь.После ввода пароля
root вы получаете полноценную root-сессию. Все последующие команды выполняются от имени суперпользователя до тех пор, пока вы не выйдете через exit.Если нужно переключиться с загрузкой окружения целевого пользователя, используйте форму с дефисом:
su -
Это загрузит переменные окружения,
$HOME, $PATH и профиль root так, как если бы вы залогинились напрямую.Что делает sudo
sudo (superuser do) выполняет одну конкретную команду с повышенными привилегиями. Пароль запрашивается ваш собственный, а не пароль root.sudo apt update
Команда отработает от имени
root, после чего вы вернётесь в свою обычную сессию. Никакого переключения пользователя не происходит.Список пользователей, которым разрешено использовать
sudo, и допустимые для них команды задаются в файле /etc/sudoers. Редактировать его нужно только через visudo, чтобы избежать синтаксических ошибок, которые могут заблокировать доступ.Ключевые отличия
su требует знать пароль root. sudo требует только ваш пароль и запись в sudoers. Это принципиальная разница с точки зрения безопасности. Раздавать пароль
root нескольким администраторам — плохая практика. С sudo каждый работает под своей учёткой, а все действия логируются с привязкой к конкретному пользователю.su открывает постоянную root-сессию. Забыли выйти — любая случайная команда выполнится с максимальными правами. sudo работает точечно, на одну команду, что снижает риск случайного повреждения системы.Когда что использовать
sudo подходит для большинства задач администрирования. Обновить пакеты, перезапустить сервис, отредактировать конфиг — всё это удобнее и безопаснее делать через sudo.su оправдан, когда нужно выполнить серию команд от root подряд, и переключение в полноценную root-сессию экономит время. Но даже в этом случае можно заменить его на:sudo -i
Эта команда открывает интерактивную root-сессию через механизм
sudo, без необходимости знать пароль root.В современных дистрибутивах
sudo стал стандартом. Ubuntu, например, по умолчанию вообще отключает вход под root и предлагает использовать только sudo. Это безопаснее, прозрачнее для аудита и не требует распространения root-пароля. Используйте
su только если точно понимаете, зачем вам полная root-сессия.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤🔥2❤2
🛠 Переключение namespace в kubectl одной командой
Если вы работаете с Kubernetes, то наверняка устали дописывать
Проблема решается одной строкой:
Эта команда меняет namespace по умолчанию в текущем контексте вашего kubeconfig. После выполнения все последующие вызовы
Допустим, вы работаете с namespace
Теперь
Как проверить текущий namespace
Убедиться, какой namespace сейчас выставлен, можно так:
Если команда ничего не вернула, значит, используется
Что важно понимать
Настройка сохраняется в файле
Для тех, кто переключает namespace часто, есть утилита
Мелочь, но экономит десятки лишних символов в день.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
Если вы работаете с Kubernetes, то наверняка устали дописывать
-n my-namespace к каждой команде. Это раздражает, отнимает время и рано или поздно приводит к ошибке — забыли флаг, команда ушла в default, получили не тот результат.Проблема решается одной строкой:
kubectl config set-context --current --namespace=<namespace>
Эта команда меняет namespace по умолчанию в текущем контексте вашего kubeconfig. После выполнения все последующие вызовы
kubectl будут работать с указанным namespace без дополнительных флагов.Допустим, вы работаете с namespace
staging:kubectl config set-context --current --namespace=staging
Теперь
kubectl get pods покажет поды именно из staging. Не нужно писать kubectl get pods -n staging каждый раз.Как проверить текущий namespace
Убедиться, какой namespace сейчас выставлен, можно так:
kubectl config view --minify --output 'jsonpath={..namespace}'Если команда ничего не вернула, значит, используется
default.Что важно понимать
Настройка сохраняется в файле
~/.kube/config и действует не только на текущую сессию терминала. Она будет активна до тех пор, пока вы не переключитесь на другой namespace или не смените контекст. Для тех, кто переключает namespace часто, есть утилита
kubens из пакета kubectx. Она делает то же самое, но короче:kubens staging
Мелочь, но экономит десятки лишних символов в день.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Полноценный мониторинг вроде Zabbix или Prometheus не всегда оправдан, особенно на небольших проектах или dev-серверах. Иногда достаточно простого скрипта, который проверит список сервисов и скажет, что именно не работает.
Ниже готовый скрипт с проверкой через
systemctl и отправкой уведомлений в Telegram.Базовая версия
Создаём файл:
nano check_services.sh
Содержимое:
#!/bin/bash
SERVICES=("nginx" "postgresql" "redis" "ssh")
echo "===== СТАТУС СЕРВИСОВ ====="
echo ""
for SERVICE in "${SERVICES[@]}"; do
STATUS=$(systemctl is-active "$SERVICE" 2>/dev/null)
if [ "$STATUS" = "active" ]; then
echo "[OK] $SERVICE"
else
echo "[УПАЛ] $SERVICE"
fi
done
Даём права и запускаем:
chmod +x check_services.sh
./check_services.sh
Массив
SERVICES правите под свой стек. Вывод будет примерно таким:===== СТАТУС СЕРВИСОВ =====
[OK] nginx
[OK] postgresql
[УПАЛ] redis
[OK] ssh
Версия с уведомлением в Telegram
Базовая версия показывает результат в консоли. Но если скрипт работает по cron, вы его вывод не увидите. Добавим отправку сообщения в Telegram при обнаружении упавшего сервиса.
Для этого понадобится бот и chat_id. Бота создаёте через
@BotFather, chat_id получаете через @userinfobot или из API бота после отправки ему любого сообщения.#!/bin/bash
SERVICES=("nginx" "postgresql" "redis" "ssh")
BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
CHAT_ID="987654321"
FAILED=""
for SERVICE in "${SERVICES[@]}"; do
STATUS=$(systemctl is-active "$SERVICE" 2>/dev/null)
if [ "$STATUS" != "active" ]; then
FAILED="${FAILED} ${SERVICE}\n"
fi
done
if [ -n "$FAILED" ]; then
HOSTNAME=$(hostname)
MESSAGE=" Проблема на ${HOSTNAME}\n\nУпавшие сервисы:\n${FAILED}"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="$CHAT_ID" \
-d text="$(echo -e "$MESSAGE")" \
-d parse_mode="HTML" > /dev/null
fi
Скрипт отправляет сообщение только когда что-то упало. Если все сервисы работают, он молчит и не спамит в чат.
Добавляем в cron
Открываем crontab:
crontab -e
Добавляем строку для проверки каждые 5 минут:
*/5 * * * * /path/to/check_services.sh
Что можно доработать
Скрипт намеренно простой, но его легко расширить. Например, добавить автоматический перезапуск упавшего сервиса через
systemctl restart "$SERVICE" прямо в блоке проверки. Или писать результаты в лог-файл для истории. Если серверов несколько, можно запускать скрипт удалённо через ssh в цикле по списку хостов.Для продакшена с десятками сервисов и серверов лучше смотреть в сторону полноценных решений. Но для пары серверов этот скрипт закрывает задачу за пять минут настройки.
📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2
Каждый день вы подключаетесь к серверам. Каждый раз набираете IP, имя пользователя, порт, путь к ключу. Это работает, но отнимает время и внимание.
Файл
~/.ssh/config решает эту проблему. Он позволяет описать все параметры подключения один раз и обращаться к серверу по короткому имени. Но это только начало. Через тот же файл настраиваются jump-хосты, автовыбор ключей, переиспользование соединений и многое другое.В первой части разберём основы: алиасы, шаблоны и ProxyJump.
Как это устроено
~/.ssh/config читается при каждом вызове ssh, scp, sftp или rsync. Файл состоит из блоков Host, каждый из которых задаёт параметры для конкретного хоста или группы хостов по шаблону.Если файла ещё нет, создайте его:
mkdir -p ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
Структура простая:
Host staging
HostName 203.0.113.50
User ubuntu
Port 2222
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Теперь вместо длинной команды с кучей флагов достаточно написать:
ssh staging
То же самое работает с
scp и rsync:scp staging:/var/log/app.log ./
rsync -avz staging:/var/www/html/ ./backup/
Шаблоны и подстановки
Блок
Host поддерживает wildcards. Например, чтобы задать настройки для всех продакшн-серверов:Host *.prod.example.com
User ec2-user
IdentityFile ~/.ssh/id_ed25519_prod
ServerAliveInterval 60
Символ
? работает как подстановка одного символа. Host web-? совпадёт с web-1, web-a, но не с web-10.Можно указать несколько имён в одном блоке:
Host web db cache
User ubuntu
IdentityFile ~/.ssh/id_ed25519_work
А через
! исключить конкретный хост:Host * !bastion.prod.example.com
ServerAliveInterval 30
Блок
Host * применяется ко всем подключениям и удобен для общих настроек. Важный момент: SSH читает файл сверху вниз и применяет первое совпавшее значение для каждой директивы. Поэтому конкретные блоки размещайте выше общих.ProxyJump. Прозрачный доступ через bastion
Продакшн-серверы обычно закрыты от прямого доступа. Подключение идёт через bastion-хост. Без конфига это два шага: сначала SSH на bastion, потом оттуда на целевой сервер. С конфигом всё прозрачно:
Host bastion
HostName bastion.prod.example.com
User ubuntu
IdentityFile ~/.ssh/id_ed25519_prod
Host *.prod.internal
User ubuntu
IdentityFile ~/.ssh/id_ed25519_prod
ProxyJump bastion
Теперь
ssh db.prod.internal автоматически пойдёт через bastion. Работает и с scp, и с rsync.Для цепочки из нескольких jump-хостов перечислите их через запятую:
Host deep.internal
ProxyJump bastion.example.com,internal-gateway.example.com
В старых конфигах можно встретить
ProxyCommand ssh -W %h:%p bastion.example.com. Это делает то же самое, но ProxyJump короче и понятнее. Для новых конфигов используйте его.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1
🛠 SSH Config. Ключи, производительность и отладка. Часть 2
В первой части мы разобрали алиасы, шаблоны и ProxyJump. Теперь — автовыбор ключей, переиспользование соединений и отладка.
Управление ключами
Если у вас несколько SSH-ключей, конфиг сам подберёт нужный:
Если на одной машине два GitHub-аккаунта, создайте алиасы
Общие настройки
Не забудьте
Отладка
Частые проблемы: конфиг игнорируется из-за прав 644 вместо 600, SSH берёт не тот ключ без
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#root_prompt
В первой части мы разобрали алиасы, шаблоны и ProxyJump. Теперь — автовыбор ключей, переиспользование соединений и отладка.
Управление ключами
Если у вас несколько SSH-ключей, конфиг сам подберёт нужный:
Host *.work.example.com
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
IdentitiesOnly yes запрещает SSH перебирать все ключи из агента. Без этой директивы можно получить отказ на серверах с низким MaxAuthTries.Если на одной машине два GitHub-аккаунта, создайте алиасы
github-personal и github-work с HostName github.com и разными ключами. В remote репозитория укажите алиас вместо github.com:git remote set-url origin git@github-work:org/repo.git
Общие настройки
ControlMaster переиспользует открытое TCP-соединение вместо нового хендшейка. Keepalive не даёт файрволам закрывать неактивные сессии. ConnectTimeout ограничивает ожидание при подключении к недоступному хосту. Для медленных каналов (VPN, мобильный интернет) добавьте Compression yes.Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist 4h
ServerAliveInterval 60
ServerAliveCountMax 3
ConnectTimeout 10
Не забудьте
mkdir -p ~/.ssh/sockets.Отладка
ssh -G staging покажет итоговую конфигурацию без подключения. ssh -vvv staging выдаст подробный лог с информацией о том, какой блок совпал и какой ключ используется.Частые проблемы: конфиг игнорируется из-за прав 644 вместо 600, SSH берёт не тот ключ без
IdentitiesOnly yes, ControlMaster падает из-за несуществующей директории для сокетов. Правильные права:chmod 700 ~/.ssh/
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_*
~/.ssh/config окупается за полчаса настройки. Этот файл стоит хранить в dotfiles-репозитории и обновлять при изменениях в инфраструктуре. По сути это рабочая документация о том, как устроен доступ к вашим серверам.📍 Навигация: Вакансии • Задачи • Собесы
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Вместо поиска нужных полей через grep, awk и sed можно использовать jq.
bash kubectl get pods -o json | jq -r '.items[].metadata.name'
bash kubectl get pods -o json | jq -r ' .items[] | select(.status.phase != «Running») | .metadata.name'
bash kubectl get pods -o json | jq '.items | length'
bash echo '{"version»:"1.25"}' | jq -r '.version'
Если работаете с Kubernetes, API или автоматизацией — jq быстро становится одной из самых полезных утилит в терминале
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥3👍2🎉1
Чтобы не теряться в потоке постов, собрали удобную навигацию по рубрикам:
#root_prompt — полезные команды, CLI-лайфхаки, однострочники и практические приёмы, которые можно сразу применять в работе
#архитектура_на_салфетке — схемы, диаграммы и инфографика по DevOps, Kubernetes, сетям, CI/CD и облачным технологиям
#разбор_полётов — анализ реальных инцидентов, постмортемов, крупных сбоев и технических кейсов с выводами
#пульс_индустрии — важные новости из мира DevOps, Cloud Native и платформенной инженерии с кратким разбором и контекстом
#арсенал_инженера — инструменты, сервисы, плагины и скрытые возможности Docker, Kubernetes, Git, Terraform, Ansible и других технологий
#локализация — переводы и краткие выжимки свежих зарубежных материалов, исследований и технических статей
#холиварня — опросы, дискуссии и вечные споры инженеров: Vim или VS Code, Kubernetes или Nomad, монолит или микросервисы
#dev_null — вопросы подписчиков, обсуждение рабочих ситуаций и обмен опытом внутри сообщества
#задача_со_звёздочкой — задачи с собеседований, практические кейсы и инженерные головоломки
#дайджест_недели — главные публикации канала, полезные ссылки и материалы за неделю в одном посте
#пятничный_деплой — мемы, юмор, забавные скриншоты и истории из жизни DevOps-инженеров
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥2
docker run \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
nginx
--cap-drop ALL отключает все Linux Capabilities.--cap-add NET_BIND_SERVICE возвращает только право слушать привилегированные порты (<1024).Чем меньше привилегий у контейнера — тем меньше потенциальная поверхность атаки.
#root_prompt #docker #security
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍2
Если задача по cron ещё не завершилась, а уже стартовал следующий запуск, можно получить несколько одновременно работающих экземпляров скрипта. Это приводит к конфликтам, лишней нагрузке и непредсказуемому поведению.
Решить проблему поможет lckdo из пакета moreutils
sudo apt install moreutils
lckdo /tmp/my-script.lock /usr/local/bin/script.sh
Если предыдущий экземпляр ещё работает, новый запуск завершится сразу.
```
lckdo -w /tmp/my-script.lock /usr/local/bin/script.sh```
* * * * * lckdo /tmp/backup.lock /usr/local/bin/backup.sh
Теперь новый запуск начнётся только после завершения предыдущего.
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Чтобы не держать в голове всю синтаксическую магию, собрали удобные примеры: for, while, until, диапазоны, чтение файлов и даже управление потоком с break и continue.
for i in /etc/*; do
echo $i
done
# То же самое (альтернативный синтаксис), также работает с другими видами циклов
for i in /etc/*
do
echo $i
done
for ((i = 0; i < 100; i++)); do
echo $i
done
# альтернативный синтаксис
for ((i = 0; i < 100; i++))
do
echo $i
done
for i in {1..10}; do
echo "Number: $i"
done
# С шагом
# ⇒ {НАЧАЛО..КОНЕЦ..ШАГ}
for i in {5..50..5}; do
echo "Number: $i"
done
# увеличение значения
i=1
while [[ $i -lt 4 ]]; do
echo "Number: $i"
((i++))
done
# уменьшение значения
i=3
while [[ $i -gt 0 ]]; do
echo "Number: $i"
((i--))
done
# длинная форма while true
while true; do
# TODO
# TODO
done
# или короткая запись
while :; do
# TODO
# TODO
done
# использование пайпов
cat file.txt | while read line
do
echo $line
done
# ИЛИ использование перенаправления ввода
while read line; do
echo $line
done < "/path/to/txt/file"
# команда seq может использоваться для генерации диапазонов
for number in $(seq 1 3); do
if [[ $number == 2 ]]; then
continue
fi
echo "$number"
done
for number in $(seq 1 3); do
if [[ $number == 2 ]]; then
# Пропустить оставшуюся часть цикла или выйти из цикла
break
fi
# Здесь выведется только 1
echo "$number"
done
# увеличение значения
count=0
until [ $count -gt 10 ]; do
echo "$count"
((count++))
done
# уменьшение значения
count=10
until [ $count -eq 0 ]; do
echo "$count"
((count--))
done
#root_prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉4❤3🔥2