Справочник команд mitdev
Все команды: mitdev <команда> [аргументы]. Команды, меняющие систему,
требуют root (sudo mitdev …).
Справка доступна и на сервере: mitdev help — обзор, mitdev help <тема> —
подробности с примерами (net, pg, ha, k8s, app, backup, remove,
web, diag). Список тем — mitdev help topics.
Пошаговые руководства по задачам (этот файл — справочник, а не учебник):
| Задача | Документ |
|---|---|
| Объединить серверы в приватную сеть | MESH.md |
| Пережить отказ сервера без Kubernetes | HA.md |
| Подготовить проект к Kubernetes и развернуть k3s | KUBERNETES.md |
| Развернуть приложение под свой стек | DEPLOY.md |
| Разобрать конкретную аварию | TROUBLESHOOTING.md |
Диагностика
mitdev info
Обзор сервера: ОС, ядро, CPU, RAM, диск, IP, uptime; версии node/npm/pnpm/yarn/pm2; Docker (версия, контейнеры, образы, тома, сети, запущенные контейнеры); статусы служб; список процессов PM2.
mitdev doctor [--deep]
Диагностика с цветным отчётом: Docker, Node, PM2, Nginx (включая nginx -t),
диск (порог 80/90 %), RAM, swap, UFW, Fail2Ban (текущие баны), ожидающие
обновления, открытые порты (LISTEN). Код выхода = число критических проблем —
удобно для мониторинга: mitdev doctor || alert.
Отдельный блок «Кластеры / HA» сводит состояние всех отказоустойчивых сервисов в одном месте: PostgreSQL (роль/стриминг реплики или число реплик), Redis (master по Sentinel), MongoDB (replica set: primary/узлов), RabbitMQ (число узлов кластера), MinIO (кворум distributed), WireGuard (число узлов mesh). Если ничего не настроено — «HA-кластеры не настроены».
С флагом --deep дополнительно выполняются реальные функциональные
пробы (не только «служба запущена»):
nginxотвечает по HTTP (код ответа наhttp://127.0.0.1/);- PostgreSQL принимает подключения (
SELECT 1); - Redis отвечает
PONG(с учётомrequirepass); - MongoDB отвечает на
ping; - SSL-сертификаты
/etc/letsencryptдействительны (проверка на истечение <7 дней); - RabbitMQ (
rabbitmqctl status), MinIO (/minio/health/live); - firewall: SSH-порт разрешён в UFW;
- свежесть последней резервной копии (
~deploy/backups).
Каждая проваленная проба увеличивает код выхода — mitdev doctor --deep
подходит как «умный» health-check в cron/мониторинге.
mitdev services
Статус ключевых служб: ssh, nginx, docker, postgresql, redis-server, mongod, rabbitmq-server, minio, fail2ban, certbot.timer.
mitdev logs [цель]
Журналы. Без аргумента — меню. Цели: install, errors, nginx (tail -f),
pm2, system (journalctl).
mitdev ssh-key [cmd] [deploy|root|all]
Сгенерированные SSH-ключи deploy-пользователя и root для клиентов вроде Termius. Требует root.
status— пути к private/public key и подсказка для Termius (allпо умолчанию);show deployилиshow root— вывести приватный ключ для импорта;pub deployилиpub root— вывести публичный ключ;path deployилиpath root— вывести путь к private key.
Рекомендуемый SSH-профиль — deploy-пользователь с sudo. Ключ root создаётся,
но прямой root-вход может быть запрещён настройкой PermitRootLogin no.
mitdev report --json
Машиночитаемый снимок сервера: система (ОС, ядро, CPU, RAM, диск, uptime, IP), установленные службы с их состоянием, кластеры PostgreSQL и Redis, приватная сеть с пирами. Байты — для памяти и диска, секунды — для времени.
Это единственный источник данных для веб-панели: агент mitdevd выполняет
эту команду и отдаёт JSON как есть. Требует jq (ставится модулем utils).
sudo mitdev report --json | jq .system.ram
sudo mitdev report --json | jq -r '.services[] | select(.active|not) | .name'
sudo mitdev report --json | jq '.net.peers[] | {name, ip, online, latency_ms}'
Удобно для мониторинга: подставьте в Zabbix/Prometheus textfile collector или опрашивайте по SSH из системы алертинга.
Обслуживание
mitdev update [--backup]
apt update && dist-upgrade (не ломается на пакетных переходах вроде fwupd),
npm@latest, pnpm (corepack), pm2@latest + pm2 update.
Перед обновлением делается снимок конфигураций (nginx, sshd drop-in,
redis.conf, minio, fail2ban, /etc/postgresql, install.env) в
/var/lib/mitdev/pre-update/config-<дата>.tar.gz (хранятся последние 5) — так
обновление остаётся обратимым, даже если пакет тронет конфиг. Флаг --backup
дополнительно делает полный mitdev backup до обновления.
mitdev self-update [url]
Обновление самого mitdev с вашего сервера установки:
sudo mitdev self-update # URL запомнен при установке через /get
sudo mitdev self-update https://mitdev.top # или явно
Скачивает свежий mitdev.tar.gz, проверяет целостность архива и сравнивает
версии (актуальная — ничего не делает). При обновлении: прежняя версия
сохраняется в /opt/mitdev.prev (откат — переместить обратно), рантайм-копии
для systemd (watchdog, эндпоинт роли, VIP-check) обновляются с перезапуском
служб, состояние/маркеры/учётные данные не затрагиваются. Новые модули после
обновления ставятся повторным sudo /opt/mitdev/install.sh (идемпотентно).
Цикл выпуска обновления: правите проект → node site/build.mjs --url … →
перезаливаете site/public/ → на серверах sudo mitdev self-update.
mitdev clean
apt autoremove --purge, apt autoclean, обрезка journald до 100 МБ,
опционально (с подтверждением) docker system prune -f.
mitdev backup [--output <каталог>] [--volumes]
Единый архив mitdev-backup-<дата>.tar.gz (по умолчанию в ~deploy/backups,
права 0600). Содержит:
~/apps,~/docker,~/scriptsи все.env*из приложений (env-files/);/etc/nginx/sites-availableиsites-enabled;- дампы БД, когда службы активны:
pg_dumpall,dump.rdbRedis,mongodump; - SSL —
/etc/letsencrypt; - SSH — drop-in
sshd_config.d,authorized_keysdeploy и root, сгенерированные ключи/root/.mitdev-keys; - cron —
/etc/crontab,/etc/cron.d, crontab root и deploy; - RabbitMQ —
export_definitions(пользователи, vhost'ы, очереди); - MinIO —
/etc/default/minio(root-креды и опции); install.envиBACKUP-MANIFEST.txt(что внутри).
--volumes дополнительно сохраняет все именованные docker-тома (каждый —
.tar.gz; может быть объёмным).
Архив содержит ключи и сертификаты — храните защищённо. Пароли служб (
/root/.mitdev-credentials) в backup не входят — для их переноса используйтеmitdev export --secrets.
mitdev restore <архив>
Восстановление из архива. Без подтверждения — каталоги пользователя,
.env-файлы и конфигурации nginx (с nginx -t и reload). Каждое из
потенциально разрушительных — по отдельному подтверждению: дампы
PostgreSQL/Redis/MongoDB, SSL, SSH-ключи (и опц. настройки sshd — с проверкой
sshd -t), cron, определения RabbitMQ, окружение MinIO, docker-тома.
Миграция и версионирование конфигурации
Перенос сервера между VPS в два шага: конфигурация — export/import
(что и как установлено), данные — backup/restore (базы, тома, код).
mitdev export [--output <файл>] [--secrets]
Снимает переносимый манифест — какие компоненты установлены и с какими
ключевыми параметрами (список компонентов, deploy-пользователь, порт SSH,
политика входа, версия Node, роль PostgreSQL и т.д.). По умолчанию файл
~deploy/mitdev-manifest-<хост>-<дата>.env (права 0600).
--secrets— вложить в манифест/root/.mitdev-credentials(base64). Тогда переносятся пароли служб (в т.ч. пароль репликации для реплики). Храните такой файл в секрете и передавайте по защищённому каналу.
Манифест — обычный KEY="value"-файл: его можно держать в git (без --secrets)
и вести историю изменений сервера.
mitdev import <манифест> [--yes] [--components "a b c"]
Воспроизводит конфигурацию из манифеста, запуская установщик:
--yes— неинтерактивно: значения берутся из манифеста, вопросы не задаются (установщик работает через unattended-режим TUI). Идемпотентно — уже установленные компоненты пропускаются;- без
--yes— установщик запускается с подставленными из манифеста значениями по умолчанию, вы подтверждаете шаги вручную; --components "…"— переопределить список компонентов из манифеста.
Ограничения: пароли (кроме варианта с --secrets) не переносятся — часть будет
сгенерирована заново; роль replica для неинтерактивного импорта требует
пароль репликации (перенесите манифест с --secrets). Импортируйте только
доверенные манифесты (файл выполняется как конфигурация).
mitdev diff <манифест>
Сравнивает манифест с текущим сервером (только чтение): версия mitdev,
deploy-пользователь, порт SSH и, главное, компоненты — что есть в манифесте,
но не установлено здесь, и наоборот. Полезно перед import и для аудита дрейфа.
Пример переноса на новый VPS:
# на старом сервере:
mitdev export --secrets -o /root/srv.env # конфигурация (+секреты)
mitdev backup # данные (код, .env, дампы БД)
# скопировать srv.env и mitdev-backup-*.tar.gz на новый VPS, затем на нём:
curl -fsSL https://mitdev.top/get | sudo bash # поставить сам mitdev
mitdev diff /root/srv.env # посмотреть, чего не хватает
mitdev import /root/srv.env --yes # воспроизвести конфигурацию
mitdev restore mitdev-backup-*.tar.gz # вернуть данные
Приложения
mitdev app [пресет] [имя] [repo|путь] [домен]
Развёртывание приложения. Первый аргумент — необязательный пресет фреймворка, который подставляет порт и стратегию запуска, чтобы меньше думать о конфигурации:
| Пресет | Порт | Запуск | Требует модуль |
|---|---|---|---|
next nest node |
3000 | сборка (npm run build) + PM2 (pm2 start npm -- start) |
node, pm2 |
fastapi |
8000 | venv + pip install -r requirements.txt + PM2 (uvicorn main:app) |
python, pm2 |
django |
8000 | venv + deps + PM2 (gunicorn <proj>.wsgi) |
python, pm2 |
go |
8080 | go build + PM2 (бинарник) |
go, pm2 |
laravel |
— | composer install, nginx + PHP-FPM, docroot public/ |
php |
wordpress |
— | nginx + PHP-FPM, docroot репозитория | php |
static |
80 | — | nginx отдаёт каталог репозитория (root) |
docker |
8080 | docker compose up -d из репозитория |
docker |
Без пресета — прежнее полностью интерактивное поведение. Пресеты подставляют порт и стратегию запуска и реально запускают приложение (node/python/go — под PM2; PHP — через PHP-FPM; static — nginx-root), а не только настраивают nginx.
Команду запуска можно переопределить однострочным файлом .mitdev/start в
репозитории (например, .venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000).
Рантаймы ставятся отдельными модулями через install.sh (или добавьте компонент
и переустановите): php (PHP-FPM + Composer), python (Python 3 + venv),
go (официальный дистрибутив Go). Если рантайм не установлен, пресет об этом
сообщит. Для django имя проекта для gunicorn определяется автопоиском
wsgi.py; если не найдено — задайте .mitdev/start.
Шаги (то же, что и раньше):
- имя, источник (git-URL или локальный путь), домен (опц.), порт, путь к своему nginx-конфигу (опц.);
- клонирование в
~deploy/apps/<имя>(илиgit pull, если уже есть); для локального пути — копирование черезrsyncс запоминанием источника; .envиз.env.example;- зависимости — менеджер определяется по lock-файлу (pnpm-lock.yaml → pnpm, yarn.lock → yarn, package-lock.json → npm ci);
docker compose up -d, если есть compose-файл;- nginx: свой конфиг или стандартный reverse-proxy шаблон + reload;
- по подтверждению — SSL через certbot (автопродление — certbot.timer).
Свой nginx-конфиг. Три способа задать (в порядке приоритета):
- ответить путём на вопрос инсталлятора («пусто» — стандартный шаблон);
- положить файл в репозиторий проекта — ищутся
.mitdev/nginx.conf,deploy/nginx.conf,nginx.conf(mitdev найдёт и спросит подтверждение); - ничего не делать — используется стандартный шаблон (reverse proxy, websocket, security-заголовки).
В своём конфиге можно использовать плейсхолдеры __APP_NAME__,
__DOMAIN__, __PORT__ — они подставятся из ответов. Перед включением
конфиг проверяется nginx -t: при ошибке сайт не включается, прежнее
состояние восстанавливается, nginx продолжает работать. SSL с
автопродлением выпускается одинаково для своего конфига и шаблона.
mitdev deploy [имя]
Обновление приложения (без имени — меню выбора):
git pull --ff-only → зависимости → npm run build (если есть script) →
docker compose up -d --build + docker image prune -f →
pm2 restart <имя> (если процесс существует).
Для приложений, развёрнутых из локального пути, вместо git pull выполняется
ре-синхронизация из сохранённого источника (rsync); серверные
.env/node_modules сохраняются.
mitdev ssl <домен> [email]
Выпуск сертификата Let's Encrypt: certbot --nginx -d <домен> --redirect.
Автопродление — системный таймер certbot.timer.
Компоненты
mitdev docker [cmd]
status (по умолчанию) | ps | images | prune | restart | logs <контейнер>.
mitdev node [cmd]
status (версии node/npm/pnpm/yarn/pm2) | update.
mitdev nginx [cmd]
status (версия, служба, валидность конфига, сайты) | test | reload | restart.
reload/restart выполняются только после успешного nginx -t.
mitdev firewall [cmd] (алиас: ufw)
Безопасное управление файрволом:
status— подробный статус правил;enable— включение без риска локаута: правило SSH (порт из install.env) добавляется первым, затем веб-порты изUFW_EXTRA_PORTS;disable— выключение с подтверждением;allow <порт>[/proto]— открыть порт вручную.
Точечные правила БД/кластера добавляются своими командами
(mitdev pg allow, add-replica) — не открывайте 5432 «всем».
mitdev pg [cmd]
Управление PostgreSQL и кластером потоковой репликации
(алиасы: postgres, postgresql).
status— версия, роль узла (primary/replica), подключения, базы с размерами и полный отчёт по репликации;replication— на primary: подключённые реплики (pg_stat_replication, отставание в байтах WAL) и слоты; на replica: состояние WAL receiver и отставание в секундах;add-replica <ip>— на primary: запись вpg_hba.conf, правило UFW (5432/tcp только с этого IP),pg_reload_conf(); печатает инструкцию для подключения нового узла;remove-replica <ip>— на primary: убрать реплику из кластера — удалить её слот репликации (освобождает удерживаемый WAL), снять доступpg_hbaи правило UFW для этого IP. Если реплика уже отключена — предложит удалить неактивные слотыmitdev_*. Саму реплику затем очищают на её сервере (mitdev remove pgcluster --purgeилиmitdev remove postgresql --purge);promote— на replica: ручное повышение до primary (pg_ctlcluster … promote) с явным предупреждением о split-brain и двойным подтверждением;import <файл> [база]— импорт бекапа проекта на primary (см. ниже);watchdog set <ключ> <значение>— настройка без правки файлов: CHECK_INTERVAL, FAIL_THRESHOLD, PROMOTE_DELAY, AUTO_PROMOTE, PRIMARY_HOST, PEERS, ROLE_PORT;watchdog [status|enable|disable]— управление службой самовосстановления (см. ниже).
Самовосстановление (watchdog v2). Watchdog ставится на все узлы
кластера (mitdev-pg-watchdog.service, работает от postgres) и полностью
заменяет ручные действия при авариях:
На реплике:
- каждые
PG_WATCHDOG_INTERVAL(5 с) primary проверяется двумя независимыми способами —pg_isreadyи прямое TCP-подключение; сбоем считается только отказ обоих; - после
PG_WATCHDOG_THRESHOLD(6) подряд неудач и приоритетной задержкиPROMOTE_DELAY(выбирается вопросом инсталлятора: основная — 0 с, резервная — 45 с) watchdog опрашивает эндпоинты ролей остальных узлов (PEERS): если кто-то уже стал primary — сам перецепляется на него (смена primary_conninfo, без копирования данных); если нового primary нет и AUTO_PROMOTE=yes — повышается сам; - кратковременные сбои failover не вызывают: любой успешный ответ primary сбрасывает счётчик, повторная проверка после задержки отменяет повышение.
На primary (fencing): эндпоинт роли отдаёт primary tl=<timeline>;
если узел видит соседа-primary со старшим timeline — его сместили,
пока он лежал — он сам понижается: pg_rewind от нового primary
(fallback — pg_basebackup) и возврат в кластер репликой. Два primary
одновременно невозможны, ручной pg follow при авариях не нужен.
События: journalctl -t mitdev-pg-watchdog. Для строгих гарантий кворума
на 5+ узлах по-прежнему уместен Patroni, но для схемы 1+2 самовосстановление
mitdev закрывает все штатные сценарии.
Дополнительные команды кластера:
vip— состояние виртуального IP: служба keepalived, адрес, кто держит VIP сейчас, последние события;follow <ip>— ручное перецепление реплики на другого primary (плановая перестройка топологии; при авариях это делает watchdog сам): пересинхронизация черезpg_basebackup, перенацеливание watchdog. Перед запуском на новом primary:mitdev pg add-replica <ip этой реплики>.
Единая строка подключения (виртуальный IP)
Модуль pgvip ставит keepalived на все узлы кластера: свободный IP вашей
подсети («VIP») автоматически держит тот узел, который сейчас primary
(проверка pg_is_in_recovery() каждые 2 с). VIP не принадлежит ни одному
серверу: умер держатель — адрес за 2–3 секунды поднимается на новом primary
(unicast VRRP — работает и там, где multicast закрыт; правило proto 112
добавляется в UFW автоматически).
Приложения используют одну строку подключения навсегда:
postgresql://app:пароль@10.0.0.100:5432/app
После failover меняется только держатель VIP — строка не меняется. Драйвер переподключится сам при обрыве соединения.
Узлы в разных сетях? VIP работает только в одной L2-сети — используйте
mitdev pg proxy(см. раздел «Узлы в разных сетях» ниже).
Доступ приложений с других серверов: mitdev pg allow
По умолчанию PostgreSQL принимает по сети только реплики. Чтобы проект с другого сервера подключался через VIP, откройте доступ его IP:
mitdev pg allow 10.0.0.20 # база=all, пользователь=all
mitdev pg allow 10.0.0.20 app deploy # только база app, пользователь deploy
Команда добавляет запись в pg_hba.conf (scram-sha-256, /32), правило UFW
(5432/tcp только с этого IP) и перечитывает конфигурацию без рестарта.
Выполняйте на каждом узле кластера — после failover новый primary тоже должен принимать это приложение (реплике записи не мешают, а после её повышения уже работают).
Требования к сети: серверы приложений должны иметь маршрут до подсети VIP — в облаках это общая приватная сеть (private network/VPC), на bare metal — общий VLAN. VIP для клиента — обычный IP; ничего особенного на стороне приложения не требуется.
Альтернатива без VIP — multi-host строка libpq (Python/Go/Java/.NET; не поддерживается node-postgres и Prisma):
postgresql://app:пароль@10.0.0.1:5432,10.0.0.2:5432,10.0.0.3:5432/app?target_session_attrs=read-write
Узлы в разных сетях / дата-центрах (без VIP)
VIP (keepalived) работает только внутри одной L2-сети. Если три сервера у разных провайдеров с разными публичными IP — используйте локальный прокси:
Сервер приложения DB-узлы (разные ДЦ)
┌─────────────────────┐ ┌──────────────────────┐
│ app → 127.0.0.1:5432│──TLS────▶│ 203.0.113.10 primary │◀─ 200 на :8008
│ HAProxy │─чек :8008│ 198.51.100.20 replica│◀─ 503 на :8008
│ (mitdev pg proxy)│ │ 192.0.2.30 replica │◀─ 503 на :8008
└─────────────────────┘ └──────────────────────┘
Каждый DB-узел (модуль pgcluster) поднимает эндпоинт роли — HTTP-ответ
200 primary / 503 replica на порту PG_ROLE_PORT (8008). На каждом
сервере приложений:
sudo mitdev pg proxy 203.0.113.10 198.51.100.20 192.0.2.30
HAProxy начинает слушать 127.0.0.1:5432 и держит трафик на том узле,
который отвечает «primary»; при failover соединения к старому primary
принудительно рвутся, драйвер переподключается — уже к новому. Строка
подключения приложений одна навсегда:
postgresql://app:пароль@127.0.0.1:5432/app?sslmode=require
На каждом DB-узле откройте доступ серверу приложений (5432 + 8008):
sudo mitdev pg allow <ip-сервера-приложений>
Шифрование обязательно: между дата-центрами трафик идёт через интернет,
поэтому mitdev настраивает репликацию и клиентские записи pg_hba как
hostssl (соединения без TLS отклоняются), а primary_conninfo реплик —
с sslmode=require. В строках подключения приложений тоже указывайте
sslmode=require.
Watchdog авто-failover работает так же (пробы идут по публичным IP); приоритет реплики (задержка повышения) выбирается вопросом при установке.
Импорт бекапа проекта: mitdev pg import
Заливка существующей базы в кластер — одной командой на primary:
sudo mitdev pg import /path/backup.dump mydb
- формат определяется автоматически:
pg_dump -Fc(custom) → pg_restore, обычный.sql→ psql,.sql.gz→ gunzip|psql,pg_dumpall→ восстановление всех баз и ролей; - база создаётся, если её нет (владелец — deploy-пользователь);
- по завершении — число таблиц и размер базы;
- реплики получают данные автоматически через репликацию — заливать бекап на каждый узел не нужно (на реплике команда честно откажется работать).
Развёртывание кластера из трёх узлов (разные ДЦ) — только mitdev
Ни одной ручной правки файлов; вы только отвечаете на вопросы.
- Узел A:
curl -fsSL https://домен/get | sudo bash→ компоненты PostgreSQL + «PostgreSQL-кластер» → роль primary, IP реплик: B C. Пароль репликации показан в/root/.mitdev-credentials. - Бекап проекта (на A):
sudo mitdev pg import /path/backup.dump mydb. - Узел B: та же установка → роль replica, primary = A, пароль репликации; авто-failover «Да», приоритет 1 — основная.
- Узел C: так же, но приоритет 2 — резервная (задержка 45 с — настроится сама).
- Доступ приложений — на каждом из A, B, C:
sudo mitdev pg allow <IP-приложения> mydb deploy. - Сервер приложений:
sudo mitdev pg proxy <A> <B> <C>→ в.env:postgresql://deploy:ПАРОЛЬ@127.0.0.1:5432/mydb?sslmode=require. - Проверка:
mitdev pg replication(A),mitdev pg watchdog status(B, C),mitdev doctor(везде).
Тонкая настройка watchdog при нестабильной сети между ДЦ — тоже командой:
sudo mitdev pg watchdog set FAIL_THRESHOLD 12 # ~минута до failover
После failover (умер A, повысился B) — всё происходит само:
прокси переключается на B; реплика C сама перецепляется на B (увидев его
через эндпоинты ролей); ожившый A сам понижается (fencing по timeline +
pg_rewind) и возвращается репликой B. Проверка автоматики:
journalctl -t mitdev-pg-watchdog -n 30 на любом узле.
(Вариант с VIP для одной сети: те же шаги + модуль «Виртуальный IP» на всех
узлах; строка подключения — postgresql://…@<VIP>:5432/….)
mitdev k8s [cmd]
Управление кластером k3s (алиас: mitdev kubernetes).
status— версия, узлы, поды, helm, режим ingress, список приложений mitdev;nodes/pods [namespace]/services— обзор ресурсов;apply <файл.yaml>— применить произвольный манифест;logs <приложение>— журналы подов приложения (-l app=<имя>, follow);token— URL и токен присоединения нового сервера к HA-кластеру.
HA-кластер из трёх серверов. Режим выбирается вопросом инсталлятора:
single (одиночный, по умолчанию), init (первый сервер кластера,
embedded etcd) или join (присоединение: URL https://<IP-первого>:6443
и токен из mitdev k8s token). Кластеру нужно нечётное число серверов
(3 или 5); кластерные порты (etcd 2379-2380, kubelet 10250, flannel
8472/udp) открываются в файрволе точечно по IP пиров. Реплики deployment'ов
разносятся по серверам анти-аффинити: отказ любого сервера не прерывает
сервис, его поды пересоздаются на живых автоматически. Вход трафика
направляйте на все серверы (DNS-записи на все IP или LB провайдера).
mitdev k8s deploy <имя> <образ> [порт] [домен] [реплики]
Развёртывание приложения в кластер (аргументы можно опустить — будут запрошены):
- рендер манифеста (Deployment с probes/limits + Service NodePort, по умолчанию 2 реплики, rolling update без даунтайма);
kubectl apply+ ожиданиеrollout status(таймаут 180 с);- публикация домена:
- traefik включён (nginx на хосте нет) → Ingress;
- есть nginx → reverse proxy на выданный NodePort + предложение SSL (certbot).
Манифесты сохраняются в /var/lib/mitdev/k8s/ — их можно править и
переприменять через mitdev k8s apply.
mitdev k8s delete <имя>
Удаляет Deployment/Service/Ingress приложения (по метке app=<имя>) — то есть
и его поды, — его манифесты и nginx-сайт k8s-<имя>, если он создавался.
mitdev k8s delete-all
Удаляет все приложения mitdev (метка managed-by=mitdev) и их поды,
сохранённые манифесты и созданные для них nginx-сайты. Сам кластер k3s остаётся.
mitdev k8s delete-cluster
Полное удаление Kubernetes: снимает k3s целиком (все поды, рабочие нагрузки и
состояние кластера etcd/sqlite), Helm, kubeconfig deploy-пользователя и правила
файрвола кластера. Эквивалент mitdev remove kubernetes.
Отказоустойчивый Redis (Sentinel): mitdev redis
HA-кластер Redis: master + N реплик, на каждом узле — redis-sentinel,
который следит за master и при отказе автоматически повышает одну из реплик
(взаимозаменяемость, как у PostgreSQL-кластера). Узлы связываются по приватной
сети (mitdev net), если она есть. Пароль общий (requirepass = masterauth),
поэтому бывший master после failover возвращается репликой без ручной правки.
mitdev redis cluster-init [имя] [кворум] [ip...]— на первом сервере: делает узел master, генерирует/берётrequirepass, привязывает Redis к своему IP, поднимает Sentinel (порт 26379), открывает 6379/26379 в UFW для каждого указанного узла и запоминает их в/etc/default/mitdev-redis. По умолчанию имяmitdev, кворум2. Без приватной сети список IP остальных узлов обязателен — иначе кластер не сможет пережить failover (см. ниже).mitdev redis token— токен для реплик (master IP, порт, пароль, кворум, список узлов кластера).mitdev redis join <токен> [-y]— на реплике: открывает файрвол для всех узлов из токена, проверяет доступность master до внесения изменений, предупреждает о затирании локальных данных (-y— без вопроса), затемreplicaof+masterauth+ Sentinel; ждётmaster_link_status:up.mitdev redis allow <ip>— открыть 6379/26379 для узла и добавить его в список узлов кластера. Прежнее имяadd-replicaработает как алиас.mitdev redis check— проверить связность: этот узел должен видеть каждый другой на 6379. Различает «закрыт порт», «неверный пароль», «redis слушает не тот адрес». Запускать на всех узлах после сборки кластера.mitdev redis promote— ручнойSENTINEL FAILOVER(обычно не нужен — срабатывает автоматически).mitdev redis status— роль (master/replica), связь репликации, текущий master и реплики по данным Sentinel, кворум. Предупреждает, если локальный Redis считает себя master, а Sentinel так не считает.mitdev redis cluster-remove(алиасыremove-cluster,uncluster) — снять HA-оверлей (Sentinel, его конфиг, правила UFW,replicaof), не трогая сам Redis и данные. Узел возвращается в автономный master, доступный на запись. После этого можно собрать кластер заново с нуля.mitdev redis delete [--purge]— удалить Redis с сервера целиком (см. Удаление компонентов). Не путать сcluster-remove: та оставляет СУБД работать.
mitdev redis proxy <ip-узла-1> [ip-2] [ip-3]
Поднимает на этом сервере локальный HAProxy: приложение подключается к
127.0.0.1:6379 обычным Redis-клиентом, а трафик уходит на тот узел кластера,
который прямо сейчас отвечает role:master. Клиенту не нужна поддержка Sentinel.
Зачем это нужно. Failover переключает сервер, а не клиента. Приложение,
настроенное на прямой адрес мастера, после переключения продолжит стучаться в
узел, ставший репликой, и получит -READONLY на каждую запись. Кластер при этом
исправен — ляжет только приложение.
# на сервере приложения (укажите ВСЕ узлы кластера)
sudo mitdev redis proxy 10.0.0.1 10.0.0.2 10.0.0.3
sudo mitdev redis proxy-status # через прокси должен отвечать master
# порт занят локальным redis-server? возьмите другой:
sudo REDIS_PROXY_PORT=6380 mitdev redis proxy 10.0.0.1 10.0.0.2 10.0.0.3
Как устроена проверка: HAProxy сам ходит в каждый узел по протоколу Redis
(AUTH → INFO replication) и ищет role:master. Реплики отвечают
role:slave и в пул не попадают. balance first вместе с backup на всех
узлах, кроме первого, гарантирует, что запись идёт ровно в один узел — даже в
момент, когда при split-brain два узла ненадолго объявляют себя мастером.
on-marked-down shutdown-sessions рвёт старые соединения при смене мастера,
чтобы драйвер переподключился к новому.
Пароль Redis попадает в /etc/haproxy/haproxy.cfg (иначе health-check не пройдёт
аутентификацию), поэтому файл переводится в режим 640 root:haproxy.
Альтернатива без прокси — Sentinel-aware клиент: он спрашивает адрес мастера у
Sentinel на порту 26379 и переподключается сам. Так умеют ioredis (Node.js),
redis-py (Python), Lettuce (Java). Прокси нужен, когда менять код приложения
нельзя или клиентов несколько и они разные.
Приложения подключаются через Sentinel (клиент спрашивает у 26379 актуальный
адрес master) — при failover переключение прозрачно. Кворум N/2+1 определяет,
сколько Sentinel'ов должны согласиться на failover: для реального авто-переезда
нужно ≥3 узлов (нечётное число), иначе split-brain.
Почему нужен полный доступ между всеми узлами
Sentinel находит реплики, разбирая INFO на master, и сам ходит к каждой из
них на 6379. Если узел A не может достучаться до узла B на 6379, он объявляет
B недоступным (+sdown) — даже когда B прекрасно работает и другие узлы его
видят. Тогда Sentinel'ы расходятся во мнении, кто master, и начинают
перевыбирать его друг против друга: в журнале это выглядит как непрерывная
череда +switch-master и +failover-end-for-timeout, а кластер получает
двух master одновременно.
Поэтому 6379 и 26379 должны быть открыты между всеми узлами, в обе стороны —
и в UFW, и в файрволе провайдера. mitdev redis cluster-init/join делают это
сами для узлов, которые им известны; для добавленных позже выполните
mitdev redis allow <ip> на каждом узле. Проверка — mitdev redis check.
Пример: кластер из трёх узлов на публичных IP
# на узле 1 (будущий master) — перечислите ВСЕ остальные узлы
sudo mitdev redis cluster-init mitdev 2 23.134.42.2 23.134.42.3
sudo mitdev redis token # скопируйте токен
# на узлах 2 и 3
sudo mitdev redis join <токен>
# на каждом из трёх узлов — убедитесь, что видно всех
sudo mitdev redis check
Пока mitdev redis check не проходит на всех узлах, авто-failover
работать не будет.
Распределённый MinIO: mitdev minio
Distributed MinIO с erasure coding — данные и чётность распределяются по узлам, кластер переживает отказ части узлов/дисков.
Важно: набор узлов MinIO фиксируется при старте (
MINIO_VOLUMESсо списком всех узлов) и не расширяется динамически. Поэтомуcluster-initпринимает сразу все адреса, а расширение = пересоздание набора.
mitdev minio cluster-init <addr1> <addr2> … <addrN>— задать набор из всех узлов (приватные IP или<узел>.internal, включая этот). Генерирует общие root-креды, пишетMINIO_VOLUMES=http://<addr>:9000/<datadir>для каждого узла, ставит systemd drop-in (ExecStart →$MINIO_VOLUMES), открывает 9000/9001 в UFW, перезапускает. Рекомендуется ≥4 узла.mitdev minio token→mitdev minio join <токен>— на каждом остальном узле применяет идентичную конфигурацию (те же креды и список узлов).mitdev minio status— режим (single/distributed) и здоровье кластера (/minio/health/cluster— есть ли кворум).
Кластер поднимается, когда стартует кворум узлов набора (до этого MinIO ждёт
остальных — это нормально). Все узлы делят одинаковые MINIO_ROOT_USER/PASSWORD
(в /root/.mitdev-credentials).
Кластер RabbitMQ: mitdev rabbitmq
Кластеризация узлов: все делят один erlang-cookie (переносится в токене),
новый узел делает reset + join_cluster к первому. Имена узлов —
rabbit@<hostname>, резолвятся через /etc/hosts приватной сети. На vhost «/»
по умолчанию включается тип очередей quorum (реплицируются между узлами,
переживают отказ). Требуется приватная сеть (для резолва имён узлов).
mitdev rabbitmq cluster-init— подготовить первый узел: management-плагин,default-queue-type quorum, открыть в UFW порты кластера/клиента (4369, 25672, 5672, 15672) для подсети.mitdev rabbitmq token— токен (имя и IP первого узла, cookie).mitdev rabbitmq join <токен>— на новом узле: прописать резолв имени первого узла, заменить cookie,stop_app→reset→join_cluster→start_app, проверитьcluster_status.mitdev rabbitmq forget <имя>— вывести узел из кластера.mitdev rabbitmq status—cluster_status(running nodes).
Приложения подключаются к любому узлу (или через LB/HAProxy на 5672);
quorum-очереди обеспечивают отказоустойчивость сообщений при потере узла
(нужно ≥3 узлов для кворума). Учётные данные admin — из модуля rabbitmq
(/root/.mitdev-credentials), общие в пределах кластера.
Отказоустойчивый MongoDB (replica set): mitdev mongo
Нативный replica set: авто-failover и выбор нового primary встроены в MongoDB (любой secondary становится primary при отказе). Между узлами — internal auth по общему keyfile (переносится в токене), клиентская авторизация включается автоматически (keyFile ⇒ authorization). Узлы связываются по приватной сети, если она есть.
mitdev mongo cluster-init [имя]— на первом сервере: генерирует keyfile, привязывает mongod к приватному IP, включает replSet,rs.initiate(), создаёт пользователяadmin(root, пароль в/root/.mitdev-credentials), открывает 27017 в UFW для подсети. Имя набора по умолчаниюrs0.mitdev mongo token— токен (имя набора, IP primary, admin-креды, keyfile).mitdev mongo join <токен>— на новом узле: пишет keyfile, включает replSet, привязку к приватному IP, затем сам добавляет себя в набор через primary (rs.add) с admin-кредами из токена; проверяет состояние (SECONDARY/PRIMARY).mitdev mongo add-member <ip>/remove-member <ip>— явное управление составом набора с текущего узла.mitdev mongo promote—rs.stepDown()(перевыборы; MongoDB выберет новый primary автоматически).mitdev mongo status— состав набора и состояние узлов (rs.status()).
Для честного авто-failover нужно ≥3 узлов (нечётное число) — иначе при
отказе половины набор теряет кворум и уходит в read-only. Приложения используют
строку подключения с replicaSet=<имя> и списком узлов (<узел>.internal).
Приватная сеть (WireGuard mesh): mitdev net
Full-mesh приватная сеть между серверами: каждый узел напрямую соединён с
каждым (без центрального VPN-хаба), публичные IP сохраняются, для внутреннего
взаимодействия появляется приватный IP (напр. 10.100.0.1). Все службы могут
слушать только приватную сеть. Каждый узел хранит реестр всех пиров и
рендерит из него /etc/wireguard/wg0.conf; операции идемпотентны, перед
изменениями wg0.conf резервируется.
Несколько сетей на одном хосте (--project)
Один сервер может держать несколько независимых приватных сетей — по одной на
проект. Любая подкоманда net принимает флаг --project <slug>:
mitdev net create --project shop # поднять сеть проекта «shop» (wg-shop)
mitdev net token --project shop # токен именно этой сети
mitdev net status --project shop # статус только сети «shop»
mitdev net join --project shop <токен>
Без --project команды работают с исходной сетью wg0 — поведение полностью
сохранено для уже развёрнутых узлов. Подсети разных проектов на одном хосте не
должны пересекаться (проверяется при create). Имя интерфейса — wg-<slug>
(для длинных имён — с детерминированным хеш-суффиксом, ≤15 символов).
mitdev net create
Создаёт сеть (этот сервер — первый узел). Спрашивает имя, подсеть (с проверкой
пересечений с Docker/Kubernetes/локальными маршрутами), UDP-порт и
опционально IPv6 (dual-stack на ULA fdXX:XXXX:XXXX::/64 — генерируется
автоматически). Затем: ставит WireGuard, генерирует ключи (+ preshared key
сети), создаёт wg0, включает IPv4/IPv6-forward, открывает порт в UFW, включает
автозапуск wg-quick@wg0, назначает себе первый адрес (.1, при IPv6 — ::1)
и записывает .internal-имена в /etc/hosts.
При включённом IPv6 каждому узлу назначается парный адрес (тот же номер хоста:
10.100.0.7 ↔ fdXX:…::7); wg0 и правила AllowedIPs становятся dual-stack.
Сети без IPv6 работают как прежде (обратная совместимость).
mitdev net token
Печатает токен сети — полный дескриптор (имя, подсеть, порт, preshared key, все текущие пиры) в base64. Его вставляют на новом сервере.
mitdev net join <токен>
Подключает текущий сервер к сети: устанавливает WireGuard, генерирует ключи,
импортирует всех пиров из токена, выделяет свободный IP из подсети, поднимает
wg0. В конце печатает peer-токен этого узла.
Чтобы связь стала двусторонней (mesh), peer-токен нужно добавить на остальных узлах:
mitdev net add-peer <peer-токен>. Для сети из 2 серверов это один шаг; для N серверов — по одномуadd-peerна каждом существующем узле (либо используйте--sshниже — MITDEV разнесёт пир сам).
mitdev net join --ssh <host> [user]
Zero-touch подключение (сценарий «SSH» из ТЗ). MITDEV:
- подключается к существующему узлу по SSH (спрашивает пользователя и
пароль/ключ; для пароля ставит
sshpass); - забирает токен сети (
mitdev net token --rawудалённо); - локально присоединяется (импорт пиров, автовыделение IP, поднятие
wg0); - добавляет этот узел как пир на целевом сервере и на всех остальных
известных узлах (SSH →
mitdev net add-peer); - проверяет связь (
pingпо приватному IP).
Требование к удалённой стороне: SSH-пользователь либо root, либо имеет
passwordless sudo (иначе удалённый sudo недоступен). Если на части узлов
добавить пир не удалось, MITDEV честно перечислит их и покажет команду для
ручного add-peer. Токен-механизм net token/join/add-peer остаётся как
надёжный запасной путь без удалённого выполнения команд.
mitdev net add-peer <peer-токен> / remove-peer <имя>
Добавляет/убирает узел в реестре и wg0.conf (идемпотентно, без дубликатов),
перечитывает конфиг «на лету» (wg syncconf, без обрыва туннеля).
mitdev net set-ip <ip>
Меняет приватный IP этого узла. Обновляет meta, собственную строку в
реестре пиров и парный IPv6 (если сеть dual-stack); публичный ключ и endpoint
сохраняются.
Отклоняется, если адрес вне подсети или уже занят другим узлом — mitdev подскажет свободный.
sudo mitdev net set-ip 10.100.0.7
После смены на каждом другом узле нужно применить новый peer-токен
(mitdev net add-peer <токен>), иначе они продолжат слать пакеты на старый
адрес. Токен печатается прямо в выводе команды.
Основной сценарий — разрешение конфликта IP после параллельного join двух
новых узлов с одним токеном (см. MESH.md).
mitdev net status
Состояние сети: подсеть, число узлов, для каждого пира — задержка (ping),
время последнего handshake и трафик (wg show … transfer). Также попадает в
mitdev doctor.
mitdev net export [файл] / import <архив>
Экспорт/импорт всей сети (wg0.conf, ключи, реестр) одним архивом — для
быстрого восстановления или миграции узла. Архив содержит приватные ключи —
храните защищённо.
mitdev net remove / mitdev net repair
remove — снять сеть с этого узла (остановить и удалить wg0, watchdog,
закрыть порт, почистить /etc/hosts). repair — самопроверка и починка:
наличие WireGuard, ключей, конфига, службы, правила файрвола, IP-forward,
watchdog — недостающее восстанавливается из реестра. mitdev repair делает то же.
Отказоустойчивость: mitdev net watchdog [status|enable|disable]
Сеть спроектирована без единой точки отказа:
- full-mesh — каждый узел соединён с каждым напрямую; падение одного сервера не разрывает связь между остальными (нет центрального VPN-хаба);
- «главного сервера» для трафика нет; роль координатора (выдача токенов на
подключение) есть у любого узла — полный реестр пиров и preshared key
хранятся на всех, поэтому
mitdev net tokenработает с любого сервера, даже если создатель сети выключен.
Поверх этого на каждом узле работает watchdog (mitdev-wg-watchdog,
ставится автоматически при create/join), который:
- перезапускает
wg0, если интерфейс упал; - «оживляет» пиры с устаревшим handshake (генерирует трафик → новый handshake);
- переразрешает DNS-endpoint (для узлов с меняющимся IP / DDNS);
- переключает endpoint на резервный адрес, если у пира их несколько
(в реестре endpoint можно задать списком через запятую:
host1:port,host2:port) — это и есть «переход на другой адрес, если основной недоступен».
Управление: mitdev net watchdog status|enable|disable. Параметры
(CHECK_INTERVAL, STALE_THRESHOLD) — в /etc/default/mitdev-wg-watchdog.
mitdev net bind <служба> [private|public|both]
Переключает, на каком интерфейсе слушает служба (идемпотентно, обратимо, перед изменением конфиг резервируется, служба перезапускается):
private(по умолчанию) — только приватный IP сети + localhost;public— все интерфейсы (0.0.0.0); предупреждает о безопасности;both— эквивалент публичного (все интерфейсы, включая приватный).
Поддерживаемые службы и что правится:
| Служба | Файл/механизм | private |
|---|---|---|
postgresql |
drop-in conf.d/zz-mitdev-listen.conf (listen_addresses) |
'<priv>,127.0.0.1' |
redis |
bind в /etc/redis/redis.conf |
<priv> 127.0.0.1 -::1 |
mongodb |
net.bindIp в /etc/mongod.conf |
127.0.0.1,<priv> |
rabbitmq |
listeners.tcp.default + management.tcp.ip в rabbitmq.conf |
<priv>:5672 |
minio |
MINIO_OPTS в /etc/default/minio |
--address <priv>:9000 |
Для PostgreSQL drop-in назван zz-…, чтобы гарантированно перекрывать
99-mitdev-replication.conf кластера. Возврат: mitdev net bind <служба> public.
После команды показывается фактический список прослушиваемых сокетов (ss).
mitdev net bind postgresql private # PG слушает только приватную сеть
mitdev net bind redis private
mitdev net bind minio private
mitdev net bind postgresql public # вернуть на все интерфейсы
Приватные адреса других узлов доступны и по имени
<узел>.internal(записываются в/etc/hosts), так что строки подключения между серверами можно писать по именам.
Во время установки. Если приватная сеть уже создана, установщик при выборе
модулей БД/кэшей сам спросит «Слушать только приватную сеть?» (по умолчанию —
да) и применит net bind к установленным службам автоматически — вручную
запускать net bind не обязательно.
Отказоустойчивый app-ingress через Cloudflare: mitdev cf
Вводит app-узел в отказоустойчивый ingress через Cloudflare — всё только через API Cloudflare (без дашборда, без локальных tunnel-конфигов): туннель (без входящих портов на узле), DNS и Load Balancing, плюс два локальных демона (health-эндпоинт и tunnel-watchdog) для честного failover на уровне приложения. Подробно, с архитектурой и режимами — в modules/24-cloudflare.md.
Токен — только локально. Экспортируйте
CF_API_TOKEN(иCF_ACCOUNT_ID/CF_ZONE_ID) на самом узле перед командами; в чат и на чужие серверы токен не передавайте. Нужны scope: Account→Cloudflare Tunnel: Edit; Zone→DNS: Edit; Zone→Load Balancers: Edit; Account→Load Balancing: Monitors and Pools: Edit; Account→Account Settings: Read.
Четыре варианта ingress: tunnel и LB в разных сочетаниях
Режим задаётся переменной CF_INGRESS_MODE (по умолчанию lb-over-tunnel). На
практике tunnel и LB складываются в четыре варианта применения:
| Вариант | Туннель | LB | Узлов | Health-failover | Входящие порты | Поддержка в mitdev |
|---|---|---|---|---|---|---|
1. lb-over-tunnel (рекоменд.) |
✅ на каждом узле | ✅ поверх туннелей | 1..N | ✅ два эшелона (watchdog + LB-монитор) | закрыты | полная |
2. tunnel-only, один узел |
✅ один | ❌ | 1 | — (резерва нет) | закрыты | полная |
3. tunnel-only + round-robin DNS |
✅ на каждом узле | ❌ (DNS-раскидка) | 2..N | ❌ мёртвый узел держит свою долю трафика | закрыты | частичная (LB нет) |
4. LB по публичным IP без туннеля (lb-only) |
❌ | ✅ по публичным IP | 1..N | ❌ health из edge недостижим | открыты 80/443 | ❌ cf lb … падает fail-loud |
1. lb-over-tunnel — туннель на каждом узле + Cloudflare LB поверх туннелей;
единственный вариант с настоящим health-failover между узлами (полный сценарий —
ниже в этом разделе).
2. tunnel-only, один узел — один туннель + cf dns set на него, LB не нужен
(cf lb … в этом режиме откажет):
export CF_INGRESS_MODE=tunnel-only
sudo -E mitdev cf login
sudo mitdev cf tunnel create app
sudo mitdev cf tunnel config app app.example.com
sudo mitdev cf tunnel run
sudo mitdev cf dns set app.example.com CNAME <tunnel-id>.cfargotunnel.com
3. tunnel-only + round-robin DNS — по туннелю на узел и несколько CNAME на
один хост. ⚠️ Health-проверки нет: при падении узла ~его доля запросов летит в
мёртвый узел, пока запись не убрать (cf dns rm). cf watchdog install грубо
смягчает (stop cloudflared → ошибка коннектора), но «серый отказ» не ловит. Нужен
настоящий межузловой failover — берите вариант 1.
4. LB по публичным IP без туннеля (lb-only) — в mitdev не поддержан:
cf lb monitor/pool/create намеренно падают fail-loud. Причина: origin — публичный
IP узла, cloudflared нет, а health-эндпоинт слушает loopback/WG и из сети Cloudflare
недостижим — увести пробу монитора в скрытый health-хост без туннеля некому. Итог
был бы либо «все origin unhealthy → отказ ingress», либо «монитор мерит лишь живость
веб-сервера → серый отказ невидим». Нужен LB без туннеля — настраивайте его вручную
в аккаунте Cloudflare с публичным health-эндпоинтом (health-эндпоинт mitdev для
этого не подходит).
Полное описание с матрицей и архитектурой — в modules/24-cloudflare.md.
mitdev cf login
Проверяет CF_API_TOKEN (/user/tokens/verify) и сохраняет token/account/zone в
креды (chmod 600). Различает «токен невалиден», «сеть недоступна» и «Cloudflare
деградировал (5xx/429)» — в последних двух случаях менять токен бесполезно.
mitdev cf health install / remove
Поднимает/снимает health-эндпоинт узла: HTTP 200, только если живы app И БД
И Redis, иначе 503. Слушает CF_HEALTH_BIND_IP (loopback/WG, никогда
0.0.0.0) на порту CF_HEALTH_PORT (8009). Ставит socat и клиентов
pg_isready/redis-cli (иначе проверки fail-closed давали бы вечное 503).
mitdev cf watchdog install / remove
Поднимает/снимает tunnel-watchdog: при устойчивом 503 (мёртв локальный app —
серый отказ) останавливает cloudflared → узел выходит из ротации; при возврате
200 запускает обратно. Дебаунс CF_TUNNEL_FAIL_THRESHOLD/RESTORE_THRESHOLD.
По общей зависимости (лежит общая БД/Redis) узел НЕ снимает — иначе из ротации
вышли бы все узлы разом.
mitdev cf tunnel create <имя>
Создаёт remotely-managed туннель (config_src=cloudflare) или переиспользует
существующий с тем же именем; сохраняет id и connector-token в креды.
mitdev cf tunnel config <имя> <домен> [локальный_url]
Записывает ingress-правила туннеля в Cloudflare: скрытый health-хост
(health.<домен> → health-эндпоинт) + домен → локальный url (по умолчанию
http://localhost:CF_APP_PORT) + обязательный catch-all 404. Локального
config.yml на узле нет.
mitdev cf tunnel run
Ставит cloudflared, поднимает юнит mitdev-cf-tunnel (connector-token — через
EnvironmentFile, НЕ в argv) и, убедившись что коннектор активен, закрывает
вход 80/443 (исходящие 443/7844 разрешаются явно до этого). SSH не трогается.
После закрытия 80/tcp ACME HTTP-01 не пройдёт — при ingress через туннель TLS
терминирует Cloudflare.
mitdev cf tunnel remove
Снимает коннектор с узла и возвращает вход 80/443.
mitdev cf dns set <имя> <тип> <значение> [proxied] / rm <имя> <тип>
Идемпотентно создаёт/обновляет (или удаляет) запись зоны CF_ZONE_ID. Типы:
A, AAAA, CNAME, TXT. proxied по умолчанию true (CNAME на
<id>.cfargotunnel.com работает только проксированным; для TXT — только
false). Имя должно быть FQDN.
# домен на туннель:
sudo mitdev cf dns set app.example.com CNAME <tunnel-id>.cfargotunnel.com
mitdev cf lb monitor <домен> / pool <имя> <origin…> / create <домен>
Собирает Cloudflare Load Balancing поверх узлов. monitor — health-проба (идёт в
скрытый health-хост). pool — origin'ы (в lb-over-tunnel это UUID туннелей, в
lb-only — публичные IP). create — балансировщик на зоне; он сам выступает
DNS-записью на своём имени и замещает CNAME на туннель (об этом предупреждает).
Все три идемпотентны. В режиме tunnel-only LB не нужен, в lb-only health-
failover не обеспечить — команды честно откажут.
mitdev cf status
Сводка: валидность токена, туннели и их коннекторы, пулы и здоровье origin'ов,
локально — активны ли cloudflared/health/watchdog. Никогда не выдаёт «здорово» по
секции, которую не смогла опросить; rc 0 только если всё опрошено и здорово —
годится как гейт в мониторинге.
Удаление компонентов
У каждого модуля — своя команда удаления; единой «снести всё» нет. Удаление обращает вспять то, что создавал соответствующий модуль установки: останавливает службы, удаляет пакеты, конфигурацию, systemd-юниты, репозитории и служебных пользователей, созданные mitdev.
mitdev remove --list
Показывает все модули, доступные для удаления, и их статус (установлен/нет).
mitdev remove <модуль> [--purge] [-y]
Удаляет один компонент. По умолчанию данные сохраняются (базы, тома, каталоги, сертификаты) — чтобы можно было переустановить компонент без потери данных. Флаги:
--purge(алиасы--data,--with-data) — удалить и данные тоже (например,/var/lib/postgresql,/var/lib/docker,/etc/letsencrypt, бакеты MinIO, домашний каталог deploy-пользователя). Необратимо.-y(алиасы--yes,--force) — без интерактивного подтверждения.
Доступные модули: system user security node docker nginx pm2
certbot firewall fail2ban utils postgresql pgcluster pgvip
redis mongodb rabbitmq minio kubernetes.
То же изнутри службы
Чтобы не искать команду на верхнем уровне, удаление доступно и как подкоманда
самой службы — это полные синонимы mitdev remove <модуль>, флаги те же:
sudo mitdev redis delete --purge # ≡ mitdev remove redis --purge
sudo mitdev minio delete -y
sudo mitdev rabbitmq delete
sudo mitdev mongo delete # у mongo и pg алиаса `remove` нет:
sudo mitdev pg delete --purge # он путался бы с remove-member/remove-replica
Для redis, minio и rabbitmq работают также remove и uninstall.
Удаление не требует, чтобы служба была жива: если установка поломана или
снесена наполовину, команда всё равно уберёт остатки.
Не путайте с cluster-remove — та снимает только HA-оверлей (Sentinel,
правила файрвола, репликацию), оставляя саму СУБД и её данные на месте.
Что именно сохраняется/удаляется по модулям:
| Модуль | Удаляет всегда | Удаляет только с --purge |
|---|---|---|
system |
swap-файл и запись в /etc/fstab |
— (пакеты и обновления не трогает) |
user |
пользователя деплоя | домашний каталог /home/<user> |
security |
drop-in усиления SSH, возврат к дефолтам | — |
node |
Node.js, npm, corepack, репозиторий NodeSource | — |
docker |
пакеты Docker, репозиторий | образы/контейнеры/тома (/var/lib/docker) |
nginx |
пакет nginx, дефолт-сайт mitdev | всю конфигурацию /etc/nginx |
pm2 |
автозапуск и глобальный PM2 | ~/.pm2 deploy-пользователя |
certbot |
пакет и таймер продления | сертификаты /etc/letsencrypt |
firewall |
отключает UFW | сброс правил + удаление пакета |
fail2ban |
пакет и jail.local |
— |
utils |
ничего (по умолчанию) | весь набор утилит |
postgresql |
пакеты PostgreSQL (+ оверлей кластера, если был) | данные кластера + роль/базу приложения |
pgcluster |
watchdog, эндпоинт роли, настройки репликации, правила | replica: удаляет БД реплики + пересоздаёт пустой кластер; primary: роль репликации и слоты mitdev_* |
pgvip |
keepalived-конфиг, VRRP-правило, снимает VIP | пакет keepalived |
redis |
пакет redis | данные /var/lib/redis |
mongodb |
пакет и репозиторий | данные /var/lib/mongodb |
rabbitmq |
пакет, admin-пользователь mitdev | данные /var/lib/rabbitmq |
minio |
юнит, бинарник, env, системного пользователя | данные (MINIO_DATA_DIR) |
kubernetes |
k3s целиком (все поды), Helm, kubeconfig, правила | — (uninstaller и так стирает данные) |
Примеры:
mitdev remove --list # что установлено
mitdev remove pgcluster # снять оверлей кластера PostgreSQL
mitdev remove pgcluster --purge # replica → удалить её БД; primary → роль+слоты mitdev_*
mitdev remove kubernetes # удалить k3s и все поды
mitdev remove redis --purge -y # Redis вместе с данными, без вопросов
mitdev remove postgresql --purge # PostgreSQL со всеми базами
mitdev pg cluster-remove [--purge]
Синоним mitdev remove pgcluster. Снимает оверлей потоковой репликации
(watchdog, эндпоинт роли, conf.d-настройки, записи pg_hba, правила
файрвола). Поведение --purge зависит от роли узла:
- replica — её база данных является физической копией primary, поэтому
--purgeудаляет реплицированную БД и пересоздаёт пустой кластер. Узел возвращается к чистому состоянию: можно заново подключить как реплику (переустановка) или удалить СУБД целиком (mitdev remove postgresql --purge). Это и есть «удаление реплики и её базы»; - primary —
--purgeудаляет роль репликации и все слотыmitdev_*(в т.ч. зависший слот от упавшей реплики). Чтобы убрать одну реплику, не трогая остальные, используйтеmitdev pg remove-replica <ip>.
Без --purge удаляется только оверлей; PostgreSQL и данные остаются.
Сценарии:
# Убрать ненужную реплику 10.0.0.5 из кластера:
# на primary:
mitdev pg remove-replica 10.0.0.5 # слот + pg_hba + файрвол
# на самой реплике 10.0.0.5:
mitdev remove pgcluster --purge # удалить её БД (или remove postgresql --purge)
# Переустановить/пересобрать реплику (например, после сбоя pg_basebackup):
# на реплике:
mitdev remove pgcluster --purge # чистое состояние
# на primary (если остался зависший слот):
mitdev pg remove-replica <ip_реплики> # снять слот
# затем заново установить роль replica через install.sh
Если
pg_basebackupна реплике упал и на primary остался слотmitdev_…, выполните на primarymitdev pg remove-replica <ip>(адресно) илиmitdev remove pgcluster --purge(все слотыmitdev_*).
Веб-панель
mitdev web install
Устанавливает и настраивает панель управления (mitdevd) на этом сервере:
скачивает бинарник под архитектуру хоста, создаёт systemd-юнит, генерирует
внутренний CA и сертификаты, заводит администратора с паролем и TOTP (2FA).
mitdev web agent-install
Ставит только агента — на узел, который должен отображаться в панели, но
сам панель не размещает. Агент отдаёт mitdev report --json по защищённому
каналу.
mitdev web status
Состояние службы, порт, активные сессии.
sudo mitdev web install
sudo mitdev web status
sudo mitdev report --json | jq . # ровно те данные, что показывает панель
Панель — read-only дашборд: система, службы, кластеры PostgreSQL и Redis, пиры приватной сети. Обновляется опросом каждые несколько секунд.
Прочее
mitdev version
Версия и дата установки.
mitdev uninstall
Удаляет сам mitdev: /opt/mitdev, симлинк, состояние, (опционально)
журналы. Установленные пакеты и данные приложений не трогает. Чтобы удалить
установленные компоненты, используйте mitdev remove <модуль> (см. выше).
mitdev help [тема]
Без аргумента — обзор всех команд на один экран.
С темой — подробная справка с примерами и разбором частых ошибок:
| Тема | Содержание |
|---|---|
net |
приватная mesh-сеть: create, join, add-peer, bind, watchdog, --project |
pg |
PostgreSQL: репликация, watchdog, VIP, локальный прокси |
ha |
отказоустойчивость: Redis, MongoDB, RabbitMQ, MinIO |
k8s |
Kubernetes: кластер, деплой, чек-лист готовности приложения |
app |
развёртывание приложений, пресеты, SSL |
backup |
бэкапы, восстановление, перенос конфигурации на другой VPS |
remove |
удаление компонентов, что сохраняется без --purge |
web |
веб-панель управления |
diag |
диагностика: doctor, logs, services, куда смотреть при проблемах |
mitdev help # обзор
mitdev help topics # список тем
mitdev help net # подробно про приватную сеть
Темы принимают синонимы: mitdev help mesh = mitdev help net,
mitdev help kubernetes = mitdev help k8s, mitdev help redis =
mitdev help ha.