# xboctploy Легковесная CLI-утилита на Rust для централизованного деплоя хобби-проектов (Node.js, Rust) с локального ПК на слабую VPS по SSH. - сборка, тесты и линтеры выполняются **локально** — CPU VPS не тратится - артефакты передаются по **SFTP** (без rsync, работает на Windows/Linux/macOS) - сервисные команды (`pm2 restart`, `systemctl restart`) запускаются **по SSH** - fail-fast: упавший шаг немедленно останавливает деплой (ADR-005) ## Установка ```sh cargo install --path . ``` Требуется Rust 1.88+. Кроссплатформенно: Windows (MSVC), Linux, macOS. ## Быстрый старт ```sh xboctploy --list # показать проекты из конфига xboctploy --list-servers # показать серверы из конфига xboctploy --dry-run demo # напечатать план деплоя без выполнения xboctploy demo # задеплоить проект demo ``` Вывод: ```txt deploying 'demo' [Local] running: npm run build... Success! (1.2s) [SFTP] transferring dist to /var/www/pages... Done! (14 file(s), 231.5 KiB) (829ms) [Remote] running: pm2 restart pages... Success! (102ms) Deploy successful! (total 2.3s) ``` ## Конфигурация Файл ищется по цепочке: 1. `--config PATH`, если указан явно; 2. `./deploy.toml` в текущей папке — удобно держать рядом с проектом и в тестах; 3. глобальный `~/.config/xboctploy/deploy.toml` — запуск «из любой папки». Схема: ```toml [servers.my-vps] # профиль сервера: описывается один раз host = "195.0.2.10" # алиас из ~/.ssh/config или IP port = 2222 user = "deploy" key_path = "~/.ssh/id_ed25519" [projects.my-node-app] server = "my-vps" # ссылка на профиль workdir = "~/code/my-node-app" # где выполнять локальные команды (~ разворачивается) [projects.my-node-app.env] # переменные для локальных команд сборки PUBLIC_BASE_PATH = "/my-node-app" [projects.my-node-app.local] # шаги сборки на вашей машине commands = ["npm ci", "npm run build"] [[projects.my-node-app.sync]] # что заливать на сервер source = "dist" # файл или папка (относительно workdir) target = "/var/www/pages" [projects.my-node-app.remote] # команды управления на сервере commands = ["pm2 restart pages"] ``` Проект может задать параметры подключения и напрямую (`host`, `user`, `port`, `key_path` вместо `server`) — тогда они имеют приоритет над профилем. Приоритет параметров SSH: проект → `[servers.]` → `~/.ssh/config` → дефолт. ### Windows-нюанс TOML В basic-строках `"..."` бэкслеши — escape-символы, путь `C:\Users` сломает парсинг. Для путей Windows используйте литеральные строки `'...'`: ```toml workdir = 'C:\code\my-node-app' ``` или прямые слэши `C:/code/my-node-app`. ## Аутентификация Цепочка (первый успешный способ используется): 1. **ssh-agent**: OpenSSH-агент (named pipe на Windows / `SSH_AUTH_SOCK` на Unix), затем Pageant; перебираются все ключи агента; 2. **файловый ключ** `key_path` → `identity_file` → `~/.ssh/id_rsa` (ключи с passphrase пока не поддерживаются); 3. иначе — понятная ошибка. Проверка host key — TOFU поверх вашего `~/.ssh/known_hosts`: неизвестный хост доверяется и запоминается, смена ключа сервера — громкая ошибка (MITM-защита). ## Переменные окружения (.env) Если рядом с workdir проекта есть `.env`, его переменные (KEY=VALUE, `#` комментарии, кавычки, префикс `export`) доступны всем локальным командам. `.env` не копируется на сервер, если не указан явно в `sync`. Приоритет источников: `[env]` из deploy.toml → `.env` → окружение ОС. ```env # .env NODE_ENV=production API_TOKEN="secret" export DB_URL=postgres://localhost/app ``` ## Разработка ```sh just test # fmt + clippy -D warnings + cargo test just run # деплой из test/deploy.toml (в git не входит) ```