Илья Кондратьев
Системный администратор Linux / Junior DevOps
Фокус на администрировании Linux серверов, автоматизации, мониторинге и безопасности. Опыт в развертывании изолированных СУБД, веб окружении, контейнеризации и автоматическом CI/CD деплое.
Мои проекты
Предлагаю ознакомиться с моими проектами. Представлены краткие описания и некоторые технические моменты, которые мне захотелось подсветить. По многим проектам можно перейти на репозиторий GitLab.
1. Автоматизация администрирования (Bash-скрипты и Systemd)
Разработка комплексной системы автоматизации для снижения рутинной нагрузки на системного администратора. Включает в себя создание отказоустойчивых скриптов для регулярного резервного копирования баз данных и интерактивного мониторинга/анализа логов веб-сервера.
- Автоматизация бэкапов БД: Потоковое создание дампов баз данных MySQL/MariaDB непосредственно из работающих Docker-контейнеров с использованием
mariadb-dumpи динамическим сжатием черезgzip. - Интерактивный анализатор логов Nginx: Написание консольной утилиты для парсинга
access.log. Скрипт поддерживает аргументы командной строки и выполняет агрегацию метрик: расчет топ-10 IP-адресов, топ-10 запрашиваемых URL, выборку ошибок с кодами 5xx, а также расчет почасового распределения нагрузки. Реализована функция «горячего» скачивания свежих логов из контейнера Nginx (–refresh). - Переход на Systemd Timers: Отказ от устаревшего cron в пользу связки
systemd.service+systemd.timer. Это обеспечило гибкое управление расписанием, изоляцию процессов, автоматический перезапуск при сбоях и централизованное логирование вsystemd-journald(без риска переполнения диска лог-файлами).
📁 Структура репозитория автоматизации
backup-wp-db/
├── backup-wp-db.sh # Исполняемый скрипт бэкапа с логикой ротации
├── backup-wp-db.conf # Конфигурационный файл (параметры подключения и secrets)
├── wp-backup.service # Юнит-файл однократного запуска службы SystemD
├── wp-backup.timer # Юнит-файл таймера автоматического расписания SystemD
├── deploy_backup-wp-db.sh # Автоматизированный скрипт безопасного деплоя проекта на хост
├── README-backup.md # Инструкция по развертыванию и сценарий восстановления данных
└── VERSION-TODO-backup.md # Лог версионирования и дорожная карта развития
🔒 Безопасность и разграничение прав (Security & Deploy)
- Принцип наименьших привилегий: Процесс деплоя полностью автоматизирован через
deploy_backup-wp-db.sh. Все файлы передаются во владениеroot:root. - Защита Secrets: На конфигурационный файл с паролями принудительно выставляются права
600(-rw-------), а на саму рабочую директорию —700(drwx------). Любые сторонние пользователи хоста полностью изолированы от чтения учетных данных БД.
⚙️ Bash Best Practices (Отказоустойчивость кода)
- Предсказуемость исполнения: Скрипты работают в строгом режиме
set -euo pipefail(немедленная остановка при любой ошибке в пайплайнах или вызове необъявленной переменной). - Чистка мусора через сигналы: Внедрен перехват системных сигналов с помощью
trapна сигналEXIT. В случае аварийного прерывания бэкапа (например, не хватило места), скрипт автоматически удаляет поврежденный “огрызок” архива, предотвращая порчу мониторинга. - Качество кода:
- Реализована строгая проверка зависимостей (проверка наличия утилит
docker,gzipв системе перед стартом). - Проверка входных параметров и валидация состояния целевых Docker-контейнеров (проверка статуса
running). - Повторяющиеся операции (например, кастомное логирование с разделением потоков
stdout/stderr) вынесены в функции. - Код полностью соответствует стандартам линтера
ShellCheck. - Используются каноничные коды завершения команд (Exit Codes).
- Реализована строгая проверка зависимостей (проверка наличия утилит
🛠️ Сценарий восстановления данных (Disaster Recovery)
Разработана и задокументирована процедура быстрого восстановления базы данных «из коробки» (восстановление структуры и записей одной командой путем подачи распакованного через zcat потока в stdin контейнера):
sudo zcat /var/backups/backup-wp-db/backup_file.sql.gz | docker exec -i "$CONTAINER_NAME" mysql -u root -p database_name
2. Изолированный сервер баз данных MySQL
Организация безопасного контура хранения данных СУБД с многоуровневой сетевой изоляцией для защиты от внешних атак и несанкционированного доступа.
- Сетевая безопасность: Стандартный порт СУБД (3306) полностью закрыт для внешних запросов на уровне межсетевого экрана и конфигурации Docker.
- Ограничение прав на уровне СУБД: Доступ к базам данных разрешен строго изнутри выделенной изолированной IP-подсети Docker (
172.18.0.%). - Безопасное администрирование: Удаленное взаимодействие с СУБД, управление базами данных и подключение через GUI-клиенты реализованы исключительно через шифрованный SSH-туннель.
- Документирование: Разработана техническая документация по добавлению новых клиентов баз данных.
🔒 Изоляция на уровне запуска контейнера
Главная уязвимость многих инсталляций — проброс порта базы данных на внешний интерфейс хоста (0.0.0.0:3306). В данном проекте порт жестко привязан к локальной петле 127.0.0.1, что делает СУБД невидимой для внешних сканеров сети порт-в-порт.
docker run -d \
--name mysql-server \
--network mysql_net \
-v mysql_data:/var/lib/mysql \
-v /opt/mysql/config:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=SuperSecretRootPass \
-p 127.0.0.1:3306:3306 \
--restart unless-stopped \
mysql:8.0
🌐 Подробности сетевого взаимодействия и механика Docker NAT
Архитектура изоляции построена на комбинации локального форвардинга портов SSH и механизмов маршрутизации виртуальной сети Docker (Bridge Network):
- Локальная привязка порта (Loopback): В конфигурации порт СУБД проброшен строго на внутренний loopback-интерфейс хоста:
127.0.0.1:3306:3306. Это делает порт физически недоступным со стороны внешней сети (Internet), даже если на внешнем интерфейсе нет файрвола. - Прохождение трафика через туннель: Когда клиент инициирует сессию Standard TCP/IP over SSH, его трафик шифруется и доставляется службе
sshdна сервере. Локальный клиент СУБД отправляет запросы в этот туннель, и они «приземляются» на стороне сервера как запросы, исходящие от локального адреса127.0.0.1на порт3306. - Трансляция адресов (Docker NAT & Masquerading): Запрос принимает виртуальный сетевой интерфейс Docker. Поскольку пакеты, идущие с хоста внутрь изолированной bridge-сети контейнеров, должны быть корректно маршрутизированы обратно, подсистема сетевого моста Docker применяет Source NAT (SNAT / Маскарадинг).
- Финальная доставка: В результате подмены адреса источника пакеты входят в сетевой стек контейнера MySQL не с внешнего IP-адреса и не с адреса
127.0.0.1, а с IP-адреса шлюза Docker-сети (по умолчанию172.18.0.1). СУБД видит подключение из подсети172.18.0.%, что полностью удовлетворяет строгим политикам безопасности пользователей ('user'@'172.18.0.%') и блокирует любые сторонние попытки аутентификации.
📋 Техническая документация: Регламент предоставления доступа для нового клиента
##### 1. Действия со стороны клиента
1. Клиент генерирует пару SSH-ключей на своей рабочей машине командой:
ssh-keygen -t ed25519 -C "your_email@example.com"
2. Передает созданный публичный ключ (.pub) администратору сервера.
3. Настраивает подключение в GUI-клиенте СУБД (DBeaver, MySQL Workbench или аналог) по методу Standard TCP/IP over SSH:
- Вкладка SSH (Параметры туннеля):
SSH Hostname: SERVER_PUBLIC_IP (публичный IP-адрес сервера)
SSH Username: sqluser (выделенный служебный пользователь)
SSH Key File: Путь к локальному приватному ключу клиента
- Вкладка Main (Параметры MySQL):
MySQL Hostname: 127.0.0.1 (относительно сервера)
MySQL Port: 3306
Username: appuser
Password: client_password
##### 2. Действия со стороны администратора (заведение клиента и БД)
1. Администратор добавляет публичный ключ клиента в файл авторизации служебного пользователя:
nano ~/.ssh/authorized_keys
2. Подключается к работающему Docker-контейнеру СУБД с правами суперпользователя:
docker exec -it mysql-server mysql -uroot -p
3. Создает изолированную базу данных с поддержкой современных кодировок:
CREATE DATABASE newbase_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
4. Создание пользователя и делегирование прав с ограничением авторизации виртуальной Docker-подсетью:
CREATE USER 'appuser'@'172.18.0.%' IDENTIFIED BY 'client_password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX ON newbase_name.* TO 'appuser'@'172.18.0.%';
FLUSH PRIVILEGES;
5. Завершает сессию администрирования:
exit
##### 3. Режимы работы с базой данных
После настройки туннеля клиент может:
- Подключиться к уже выделенной и созданной для него базе данных.
- Самостоятельно развернуть структуру таблиц внутри выделенного пространства.
- Запросить создание дополнительных изолированных баз у администратора согласно регламенту.
3. Защищенный контур серверной инфраструктуры (Baseline)
Создание безопасного эталонного Linux-сервера для развертывания production-приложений с защитой от несанкционированного доступа.
- Настройка Firewall (UFW) с политикой ограничения входящего трафика по умолчанию — исключения порты SSH (22), HTTP (80), HTTPS (443).
- Интеграция Fail2ban для динамической блокировки хостов при попытках брутфорса по SSH.
- Организация удаленного доступа через WireGuard VPN и авторизация строго по SSH ключам.
🛡️ Отключение прямого доступа для root
В рамках политики безопасности выполнено отключение доступа к учетной записи root. Почему это важно?
Обычная работа должна вестись под рядовым пользователем, а повышенные привилегии запрашиваются точечно и только при необходимости через утилиту sudo.
Постоянная работа под root нарушает главные правила безопасности:
- Риск критических ошибок: Под обычным пользователем команда
rm -rf /выдаст ошибку Permission denied. Под root система сотрет себя без лишних вопросов. - Компрометация системы: Если вы запустите под root программу или скрипт, содержащий уязвимость, злоумышленник мгновенно получит полный контроль над всем сервером.
- Принцип минимальных привилегий (Principle of Least Privilege — PoLP): Фундаментальное правило безопасности — использовать в каждый момент времени только те права, которые минимально необходимы для выполнения текущей задачи.
- Отсутствие контроля (Логирование): Если все администраторы заходят на сервер напрямую под
root, в логах невозможно разобрать, кто именно совершил действие или ошибку. При использованииsudoсистема фиксирует реальное имя пользователя.
4. Production-like веб-инфраструктура WordPress
Развёртывание отказоустойчивого контейнеризированного веб-сервиса с автоматическим деплоем и изолированными слоями.
- Выполнена контейнеризация компонентов веб-приложения (Nginx, PHP-FPM, MariaDB).
- Настроено управление через Docker Compose, изолирован каждый слой инфраструктуры на уровне контейнеров и внутренних сетей Docker.
- Сконфигурирован Nginx в роли Reverse Proxy, настроена маршрутизация и upstream-сервисы.
- Настроен автоматический выпуск SSL-сертификатов Let’s Encrypt и постоянный редирект с HTTP на HTTPS.
- Развернут локальный GitLab Runner и построен автоматизированный pipeline для валидации манифестов Docker Compose и линтинга конфигураций Nginx, что позволило полностью исключить downtime (простой) веб-сервиса при обновлениях.
🏗️ Архитектурная схема веб-инфраструктуры
🔑 Ключевые архитектурные акценты
- Многоуровневая изоляция (Security Best Practice): Внешний мир имеет доступ исключительно к контейнеру Nginx по HTTP-порту. Контейнеры приложения (WordPress) и базы данных (MariaDB) находятся в приватной виртуальной сети Docker. Прямой доступ к СУБД извне полностью заблокирован, что исключает возможность брутфорса или сканирования портов базы данных.
- Разделение обязанностей (Separation of Concerns): Nginx освобождает PHP-FPM от рутины, самостоятельно обрабатывая и отдавая статические файлы (.css, .png, .js) с максимальным временем кэширования в браузере (директива expires max). Тяжелый бэкенд обрабатывает только динамический PHP-код, что снижает нагрузку на сервер.
- Безопасный CI/CD Pipeline (Automation & Zero-Downtime подход): Развертывание защищено предварительной валидацией: сначала проверяется синтаксис манифестов (
docker-compose config), затем линтится конфигурация Nginx. И только при успешных тестах локальный GitLab Runner производит деплой, минимизируя риски «уронить» рабочий сайт из-за синтаксической ошибки. - Stateful Persistence (Надежность данных): Разделение stateless-логики контейнеров и stateful-данных через именованные Docker Volumes гарантирует, что обновление, перезапуск или уничтожение контейнеров не приведет к потере пользовательского контента и базы данных.