Сверка fr1 показала, что дока расходится с фактом по десятку пунктов —
значит нужен не разовый проход, а контракт и инструмент.
CLAUDE.md — правило «тронул сервер, обнови servers/<хост>.md в том же
прогоне» плюс стиль: факт + причина + что сломается молча. Лежит именно
в CLAUDE.md, потому что AGENTS.md автоматически агенту не подгружается.
.claude/skills/server-audit/ — метод сверки и накопленные грабли: где
дока врёт чаще всего, почему ufw не отвечает на вопрос об открытых
портах, почему нужен up -d --dry-run, почему «executed successfully»
не доказывает работу задания.
scripts/snapshot.sh — инвентаризация живого состояния за один проход:
только чтение, без sudo, секретов не печатает, недоступное под root
помечает и подсказывает команду.
Первый же прогон скрипта нашёл две вещи, обе описаны:
- IPv6 не «починился», а мигает: за один день FAILED -> REACHABLE ->
FAILED без единой правки конфига. Описан как мигающий, с выводом
ничего на него не завязывать.
- В основном sshd_config стоит PermitRootLogin yes (правка шаблона
Contabo). Root-вход закрыт только потому, что Include дроп-инов
стоит выше, а sshd берёт первое значение. Уберёшь дроп-ин —
включится.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.7 KiB
6.7 KiB
name, description
| name | description |
|---|---|
| server-audit | Сверить фактическое состояние сервера с его описанием в servers/*.md и обновить описание. Использовать после любых работ на сервере (поднял/погасил сервис, поменял конфиг, удалил каталог, завёл ключ), а также когда просят проверить, соответствует ли дока реальности, актуализировать описание хоста или разобраться, что на сервере вообще происходит. |
Сверка описания сервера с фактом
Цель — чтобы servers/<хост>.md описывал сервер таким, какой он есть, и
чтобы по нему можно было принимать решения. Правила оформления — в
CLAUDE.md репозитория, здесь метод и грабли.
Порядок
- Собери факт до чтения доки. Сначала
./scripts/snapshot.sh <хост>, потом читай описание. Наоборот — начнёшь подгонять наблюдения под текст. - Сверяй по пунктам, не по впечатлению. Прогоняй утверждения доки через факт по одному: версии, размеры, пути, порты, «включено/выключено». При сверке fr1 2026-09-08 неверными оказались десять утверждений, включая «IPv6 не работает» про работавший IPv6 и версию Gitea на два минора назад.
- Добери то, что требует root — snapshot это помечает. Неинтерактивный
sudo не проходит: нужен
ssh -t <хост> 'sudo ...', то есть попроси пользователя выполнить, а не пытайся обойти. - Правь описание в том же прогоне. Не откладывай на «потом опишу».
- Незакрытое — в «Открытые хвосты» файла хоста. Токен, который не удалось отозвать; права, которые не поправил; решение, которое за пользователя не принимаешь.
Где дока врёт чаще всего
- Версии и размеры — меняются молча при обновлении контейнера. Смотри
фактический тег у запущенного контейнера, а не запись в compose: они
расходятся, и тогда
docker compose up -dоткатывает сервис. - «Не работает» — могло починиться на стороне провайдера. И наоборот:
IPv6 на fr1 за один день был
FAILED, потомREACHABLE, потом сноваFAILED— такое надо описывать как мигающее, а не как состояние. - Открытые порты.
ufw statusне отвечает на вопрос «что торчит наружу»: docker публикует порты в iptables напрямую, минуя ufw. Толькоss -tlnH+docker ps. Непубликуемый порт контейнера всё равно доступен с хоста по адресу контейнера — «внутренняя сеть» не периметр. - Процессы вне контейнеров.
docker psих не покажет, а они не переживут перезагрузку. ИщиpsсPPID=1и чужими пользователями. - Кроны других пользователей — в
docker psи вcrontab -lих нет. Осиротевшее задание может годами падать молча: MTA не установлен, вывод крона теряется. - Планы, записанные как факт. «Планируется перенести DNS» при уже перенесённом DNS. Проверяй раздел «планируется» отдельно.
Грабли, которые стоили времени (не повторяй)
- Пути в БД абсолютные. Прежде чем контейнеризовать сервис, проверь
все префиксы путей в его базе, а не только основной каталог данных:
select substr(file_path,1,30), count(*) from images group by 1;Монтируй в тот же путь, что на хосте, иначе часть данных пропадёт молча. up -d --dry-runперед любым compose-действием. Он показывает, что compose собирается сделать, — например поднять забытый контейнер того же проекта и словить конфликт портов.- Задание может глушить свои ошибки. У imgbot
analyzeлогирует исключение и возвращается нормально, поэтому планировщик пишетexecuted successfullyпосле падения. Отсутствие ошибок не доказывает работу — проверяй результат, а не статус. - Ретенция. journald был на 500M (11 дней), sysstat на
HISTORY=7. Сервер, где разбирают аварии, обязан хранить историю дольше, чем живёт проблема. У sysstat приHISTORY>28имена переключаются наsaYYYYMMDD— иначе поднятие числа бессмысленно. - Группа
docker= root. Пользователь без sudo, но в группе docker, монтирует/в контейнер и делает что угодно. Учитывай при описании доступа.
Проверка результата
Перед отчётом прогони по получившемуся файлу: каждое ⚠️ подтверждено
наблюдением? у каждого изменения указана дата и прежнее значение? не
попали ли в текст секреты? если роль хоста изменилась — поправлена ли
строка в AGENTS.md?