title: "Концепция: Install Profile — создание дистрибутива платформы"
version: 1.0.0
date: 2026-04-02
status: active
type: concept
Принцип: любой дистрибутив создаётся итеративно.
Ставим → тестируем → сносим → исправляем → повторяем.
Только когда результат чистый — фиксируем как финальный профиль.
Install Profile — это воспроизводимый пакет: скрипты + конфиги + тесты,
которые позволяют поднять окружение на чистом сервере и получить
заранее известный, проверенный результат.
Это применимо к любому дистрибутиву: сервер, сервис, приложение, кластер.
DRAFT ──► TEST ──► BROKEN? ──► FIX ──► WIPE ──► TEST (повтор)
│
PASSED?
│
RECORD ──► FINAL ──► RELEASE
| Фаза | Действие | Результат |
|---|---|---|
| DRAFT | Написать скрипты, конфиги, тесты | Набор файлов в system/install/ |
| TEST | Запустить на свежем сервере | Журнал установки |
| BROKEN | Выявить что сломалось | Список багов |
| FIX | Исправить скрипты (НЕ сервер!) | Патч в git |
| WIPE | Уничтожить сервер полностью | Чистая машина |
| REPEAT | Ставить заново по исправленному | Новый прогон |
| RECORD | Зафиксировать: версия + теги + артефакты | releases/v1.0.0/ |
| RELEASE | Опубликовать профиль | Готов к использованию |
Вариант А (рекомендуется): Snapshot rollback
1. Создать snapshot ПЕРЕД установкой
2. Запустить install.sh
3. Прогнать тесты
4. Если провалились → rollback snapshot → исправить → повторить
5. Если прошли → сохранить snapshot как «CLEAN-v1.0.0»
Вариант Б: Пересоздание VPS
1. Создать VPS (Beget/Hetzner/etc)
2. Запустить install.sh
3. Прогнать тесты
4. Если провалились → удалить VPS → создать новый → исправить → повторить
5. Если прошли → зафиксировать профиль
Каждый модуль должен иметь проверку. Тесты пишутся вместе со скриптом.
system/install/tests/
├── test-system.sh ← пакеты, UFW, fail2ban
├── test-docker.sh ← docker, compose, daemon.json
├── test-networks.sh ← proxy-net существует
├── test-wireguard.sh ← wg0 запущен, IP доступен
├── test-core.sh ← postgres healthy, gitea отвечает
├── test-ops.sh ← portainer, vaultwarden, uptime-kuma
├── test-proxy.sh ← SOCKS5 проксирует запросы
└── run-all.sh ← запускает все тесты, выводит сводку
#!/bin/bash
# test-docker.sh — проверка Docker после install_docker()
PASS=0; FAIL=0
check() {
local desc="$1"; shift
if eval "$@" &>/dev/null; then
echo " ✓ ${desc}"
((PASS++))
else
echo " ✗ ${desc}"
((FAIL++))
fi
}
check "docker запущен" systemctl is-active docker
check "docker версия ≥ 24" docker version --format '{{.Server.Version}}' | awk -F. '$1>=24'
check "compose plugin работает" docker compose version
check "log rotation настроен" grep -q '"max-size"' /etc/docker/daemon.json
echo ""
echo "Итог: PASS=${PASS} FAIL=${FAIL}"
[[ $FAIL -eq 0 ]]
#!/bin/bash
# run-all.sh
TOTAL_FAIL=0
run_test() {
local file="$1"
echo "━━ $(basename $file) ━━"
bash "$file" || ((TOTAL_FAIL++))
echo ""
}
for t in "$(dirname $0)"/test-*.sh; do
run_test "$t"
done
if [[ $TOTAL_FAIL -eq 0 ]]; then
echo "✅ ВСЕ ТЕСТЫ ПРОШЛИ — профиль готов к записи"
else
echo "❌ ПРОВАЛЕНО: ${TOTAL_FAIL} тест(ов) — не записывать профиль"
exit 1
fi
[ Тестовая Мать ] [ Тестовая Дочка ]
чистый Ubuntu чистый Ubuntu
любой IP любой IP
# На тестовой Матери:
git clone <arch-infra> /opt/install
bash /opt/install/system/install/install.sh
# → выбрать "Мать"
# → заполнить конфиг (тестовый домен)
# → выбрать стеки: CORE + OPS + CREATOR + PROJECTOR
bash /opt/install/system/install/tests/run-all.sh
Если FAIL → запись в журнал → исправить скрипт → WIPE → повторить
# На тестовой Дочке:
bash /opt/install/system/install/install.sh
# → выбрать "Дочка"
# → ввести публичный ключ Матери
# → выбрать стеки: PROJECTOR
# На Дочке:
ping 10.10.0.1 # Мать
wg show # VPN активен
# На Матери:
ping DAUGHTER_WG_IP # Дочка
# Создать тестовый репозиторий в Gitea на Матери
# Подключить Проектор на Дочке к репозиторию
# Проверить что Проектор видит свои проекты, НЕ видит чужие
bash /opt/install/system/install/release.sh v1.0.0
#!/bin/bash
# release.sh — фиксация версии профиля
VERSION="${1:?Укажите версию: release.sh v1.0.0}"
RELEASE_DIR="system/install/releases/${VERSION}"
mkdir -p "${RELEASE_DIR}"
# Копировать все скрипты
cp -r system/install/{lib,modules,configs,tests} "${RELEASE_DIR}/"
cp system/install/install.sh "${RELEASE_DIR}/"
cp system/install/MANUAL-STEPS.md "${RELEASE_DIR}/"
# Зафиксировать дату и результат тестов
{
echo "version=${VERSION}"
echo "date=$(date '+%Y-%m-%d %H:%M')"
echo "tested_on=$(hostname)"
echo "tester=$(git config user.name)"
} > "${RELEASE_DIR}/RELEASE.txt"
# Прогнать тесты последний раз
bash system/install/tests/run-all.sh >> "${RELEASE_DIR}/test-results.txt" 2>&1
if [[ $? -ne 0 ]]; then
echo "❌ Тесты провалились — релиз не создан"
rm -rf "${RELEASE_DIR}"
exit 1
fi
# Коммит
git add "${RELEASE_DIR}"
git commit -m "release: install profile ${VERSION}"
git tag "${VERSION}"
echo "✅ Профиль ${VERSION} зафиксирован"
При каждом цикле тестирования записывать:
## Итерация 1 — 2026-04-02
**Сервер:** тест-vps-1 (91.x.x.x)
**Прогон:** install.sh → Мать → CORE+OPS
**Результат тестов:**
- ✓ system: все прошли
- ✗ docker: log rotation не применился (daemon.json перезатёрся)
- ✗ core: postgres не стартовал (init-db.sh — синтаксическая ошибка)
**Исправления:**
- docker.sh: systemctl restart после записи daemon.json
- core.sh: исправлен heredoc в init-db.sh
**WIPE:** да (snapshot rollback)
---
## Итерация 2 — 2026-04-02
...все прошли → RECORD v1.0.0
Файл: system/install/ITERATIONS.md
.envcore-postgres, не 172.x)