chore(ops): скрипты аудита и первичной настройки выделенного сервера Selectel #3050

Merged
lekss361 merged 2 commits from chore/selectel-bootstrap into main 2026-08-22 11:53:34 +00:00
Owner

Сервер Poincare (SPB-4, 188.246.224.93) поднят 22.08.2026. Два скрипта под переезд — эпик #2989, задачи #3027-#3032.

ops/selectel-audit.sh — только чтение

Отвечает на вопрос, который надо закрыть до установки чего бы то ни было: собраны ли диски в зеркало. Переставить ОС можно только пока сервер пустой.

Результат первого прогона на живом сервере:

RAID RAID1 на всех трёх разделах/boot, swap, /, все [2/2] [UU]
Диски Samsung 980 PRO 1TB + 970 EVO Plus 1TB (модели разные, зеркало собрано)
CPU Ryzen 5 5600G, 6 ядер / 12 потоков, до 4.47 ГГц
Память 62 ГБ, non-ECC подтверждено (Error Correction Type: None)
Диск 910 ГБ, занято 2%
Ядро 6.17.0-35 (на Beget — 6.8)

Переставлять ОС не нужно.

ops/selectel-bootstrap.sh — идемпотентная настройка

Пользователь с ключом, ufw, Docker версий текущего прода (29.4.1 / v5.1.3), лимит журналов контейнеров, sysctl, unattended-upgrades, fail2ban, ужесточение sshd.

Порядок шагов выбран так, чтобы не потерять доступ: правило для SSH добавляется до включения файрвола, а sshd в конце намеренно не перезапускается — сначала проверяется вход по ключу в отдельном окне. При выключенном PasswordAuthentication ошибка означала бы IP-KVM за 1320 ₽.

Два умолчания выставлены по замеру, а не по привычке

Часовой пояс Europe/Moscow, не UTC. Проверил оба хоста — сейчас на MSK. Смена пояса сдвинула бы все шесть cron-задач (бэкапы в 3:30 и 4:30, dadata-backfill, геокодинг) на три часа.

Swap не создаётся, если уже есть. Установщик Selectel отдаёт раздел 4.7 ГБ в зеркале; добавлять файл поверх при 62 ГБ памяти незачем.

Срочное, что нашёл аудит

Сервер уже под сканированием: fail2ban на нём сам себя включил и держит 6 адресов в бане, в логе есть Failed password for invalid user sol. При этом:

  • PermitRootLogin yes и PasswordAuthentication yes — вход root по паролю открыт наружу;
  • ufw установлен, но inactive.

То есть прямо сейчас машина стоит с открытым парольным root-входом. Bootstrap это закрывает, но запускать его — решение владельца.

Заодно закрыт замер для #3032

Задержка Beget ↔ Selectel СПб: 17.3 мс, потерь нет. Оценка в issue была 10-15 мс — по факту на 15-70% хуже, что важно для #3028 (скраперы остаются на Beget и пишут в базу через сеть).

.gitattributes

*.sh text eol=lf. Без этого скрипт, отредактированный под Windows, падает на удалённом хосте с $'\r': command not found — поймал ровно это при первом запуске аудита.

Сервер `Poincare` (SPB-4, `188.246.224.93`) поднят 22.08.2026. Два скрипта под переезд — эпик #2989, задачи #3027-#3032. ## `ops/selectel-audit.sh` — только чтение Отвечает на вопрос, который надо закрыть **до** установки чего бы то ни было: собраны ли диски в зеркало. Переставить ОС можно только пока сервер пустой. Результат первого прогона на живом сервере: | | | |---|---| | RAID | **RAID1 на всех трёх разделах** — `/boot`, swap, `/`, все `[2/2] [UU]` | | Диски | Samsung 980 PRO 1TB + 970 EVO Plus 1TB (модели разные, зеркало собрано) | | CPU | Ryzen 5 5600G, 6 ядер / **12 потоков**, до 4.47 ГГц | | Память | 62 ГБ, **non-ECC подтверждено** (`Error Correction Type: None`) | | Диск | 910 ГБ, занято 2% | | Ядро | 6.17.0-35 (на Beget — 6.8) | Переставлять ОС не нужно. ## `ops/selectel-bootstrap.sh` — идемпотентная настройка Пользователь с ключом, ufw, Docker версий текущего прода (29.4.1 / v5.1.3), лимит журналов контейнеров, sysctl, unattended-upgrades, fail2ban, ужесточение sshd. Порядок шагов выбран так, чтобы не потерять доступ: правило для SSH добавляется **до** включения файрвола, а sshd в конце намеренно **не** перезапускается — сначала проверяется вход по ключу в отдельном окне. При выключенном `PasswordAuthentication` ошибка означала бы IP-KVM за 1320 ₽. ## Два умолчания выставлены по замеру, а не по привычке **Часовой пояс `Europe/Moscow`, не UTC.** Проверил оба хоста — сейчас на MSK. Смена пояса сдвинула бы все шесть cron-задач (бэкапы в 3:30 и 4:30, dadata-backfill, геокодинг) на три часа. **Swap не создаётся, если уже есть.** Установщик Selectel отдаёт раздел 4.7 ГБ в зеркале; добавлять файл поверх при 62 ГБ памяти незачем. ## Срочное, что нашёл аудит Сервер уже под сканированием: fail2ban на нём **сам себя включил** и держит 6 адресов в бане, в логе есть `Failed password for invalid user sol`. При этом: - `PermitRootLogin yes` и `PasswordAuthentication yes` — вход root по паролю открыт наружу; - `ufw` установлен, но **inactive**. То есть прямо сейчас машина стоит с открытым парольным root-входом. Bootstrap это закрывает, но запускать его — решение владельца. ## Заодно закрыт замер для #3032 Задержка Beget ↔ Selectel СПб: **17.3 мс**, потерь нет. Оценка в issue была 10-15 мс — по факту на 15-70% хуже, что важно для #3028 (скраперы остаются на Beget и пишут в базу через сеть). ## `.gitattributes` `*.sh text eol=lf`. Без этого скрипт, отредактированный под Windows, падает на удалённом хосте с `$'\r': command not found` — поймал ровно это при первом запуске аудита.
lekss361 added 1 commit 2026-08-22 09:49:43 +00:00
chore(ops): скрипты аудита и первичной настройки выделенного сервера Selectel
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
6484116079
Сервер Poincare (SPB-4, 188.246.224.93) поднят 22.08.2026. Два скрипта под
переезд (#2989, #3027-#3032).

selectel-audit.sh — только чтение. Отвечает на вопрос, который надо закрыть
до установки чего бы то ни было: собраны ли диски в зеркало. Переставить ОС
можно только пока сервер пустой.

Результат первого прогона: RAID1 на всех трёх разделах ([2/2] [UU] на /boot,
swap и /), память non-ECC подтверждена (Error Correction Type: None),
910G свободно из 924G.

selectel-bootstrap.sh — идемпотентная настройка: пользователь с ключом,
ufw, Docker версий текущего прода (29.4.1 / v5.1.3), лимит журналов
контейнеров, sysctl, unattended-upgrades, fail2ban, ужесточение sshd.

Порядок шагов выбран так, чтобы не потерять доступ: правило для SSH
добавляется ДО включения файрвола, а sshd в конце намеренно НЕ
перезапускается — сначала проверяется вход по ключу в отдельном окне.
При выключенном PasswordAuthentication ошибка означала бы IP-KVM за 1320 руб.

Два умолчания выставлены по факту, а не по привычке:

- часовой пояс Europe/Moscow, а не UTC — оба хоста сейчас на MSK, и смена
  пояса сдвинула бы все шесть cron-задач (бэкапы, геокодинг) на три часа;
- swap не создаётся, если он уже есть — установщик Selectel отдаёт раздел
  4.7G в зеркале, добавлять файл поверх незачем при 62G памяти.

.gitattributes: *.sh с LF — иначе скрипт, отредактированный под Windows,
падает на удалённом хосте с `$'\r': command not found`.
bot-backend added 1 commit 2026-08-22 09:56:28 +00:00
fix(ops): hardening sshd молча не применялся из-за приоритета cloud-init
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
fb75bce22d
Найдено при первом живом запуске на Poincare.

Ubuntu кладёт в /etc/ssh/sshd_config.d/ файл 50-cloud-init.conf с
PasswordAuthentication yes. sshd берёт ПЕРВОЕ встреченное значение директивы,
а не последнее, поэтому наш 60-hardening.conf проигрывал по имени: после
reload парольный вход для root остался бы открытым.

Коварство в том, что `sshd -t` при этом отвечает «конфиг валиден», и скрипт
рапортовал об успехе. Сервер уже под перебором (fail2ban держал 6 адресов),
так что тихий отказ здесь стоил бы дорого.

Три правки:
- файл называется 00-hardening.conf и читается первым; старый 60-* удаляется,
  чтобы повторный запуск не оставил два конфликтующих;
- после записи проверяется не синтаксис, а ИТОГ через `sshd -T`: если
  passwordauthentication != no, скрипт падает и НЕ перезапускает sshd;
- комментарий про версии Docker приведён в соответствие с поведением —
  ставится последняя из репозитория, версии прода служат ориентиром для
  предупреждения (приехали 29.7.2 / 5.5.0 против 29.4.1 / v5.1.3).
lekss361 merged commit 42d9eb5c1f into main 2026-08-22 11:53:34 +00:00
lekss361 deleted branch chore/selectel-bootstrap 2026-08-22 11:53:34 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3050
No description provided.