6e503433d4
Переосмысление установщика по фидбеку: установщик должен делать чистую
установку «с нуля», а не миграцию. От пользователя требуется одна
команда и больше ничего:
curl -sSL https://.../install.sh | sudo bash
deploy/astra/install.sh переписан:
- 9 чётких этапов с прогресс-индикатором (секунды от старта)
- Авто-определение ОС: Astra SE → официально, Astra CE/Debian → warn,
Ubuntu → ask, остальные → fail
- Авто-скачивание дистрибутива ИШ (~120 МБ) с old.nsd.ru
- Авто-установка ИШ через dpkg (но если упадёт — это OK, продолжаем)
- НЕинтерактивный режим (--yes) для CI/автоматизации
- Финальная сводка с URL'ами + список ручных шагов
- Дефолтный setup.json создаётся сразу, чтоб bj-server понимал DSN
- ProtectSystem=strict, ReadWritePaths только нужные, PrivateTmp в
systemd unit'е
deploy/astra/migrate-from-redos.sh → переименован в import-data.sh
и стал ОПЦИОНАЛЬНЫМ (для тех кто переезжает с действующего стенда).
Главный путь — чистая установка через install.sh.
deploy/astra/README.md перетряхнут:
- TL;DR с одной командой в самом верху
- Объяснение Astra SE vs Astra CE vs Debian (платное/бесплатное)
- 5 скриптов вместо 6
- Раздел «что произойдёт после установки» — режим эмуляции, что
осталось руками
- 10-этапный путь от чистой ВМ до прохождения теста с роботом MOEX МОСТ
REPORT.md обновлён: установщик описан как «одна команда» вместо
«миграция», % готовности не изменился (но качество улучшилось).
385 lines
17 KiB
Bash
Executable File
385 lines
17 KiB
Bash
Executable File
#!/bin/bash
|
||
# install.sh — установка Bridge-and-Join-s одной командой.
|
||
#
|
||
# ЦЕЛЕВАЯ АУДИТОРИЯ: оператор без знания Linux/Go. Просто запускает строку:
|
||
#
|
||
# curl -sSL https://git.zetit.ru/zuevav/Bridge-and-Join-s/raw/main/deploy/astra/install.sh | sudo bash
|
||
#
|
||
# и всё работает.
|
||
#
|
||
# Поддерживаемые ОС:
|
||
# - Astra Linux Special Edition 1.6 / 1.7 (платная, для прод)
|
||
# - Astra Linux Common Edition / 1.8 (бесплатная)
|
||
# - Debian 11 / 12
|
||
# - Ubuntu 22.04 / 24.04 (с предупреждением)
|
||
#
|
||
# Что устанавливается АВТОМАТИЧЕСКИ:
|
||
# 1. Системные зависимости (apt: curl, git, podman, postgresql-client)
|
||
# 2. Go 1.24+ (скачивается с go.dev)
|
||
# 3. PostgreSQL 16 в podman-контейнере + миграции
|
||
# 4. bj-server (компилируется из исходников, ставится в /opt/bj/)
|
||
# 5. Дистрибутив ИШ НРД (скачивается с сайта НРД, ~120 МБ)
|
||
# 6. Сам ИШ устанавливается через dpkg -i (но не запускается без Валидаты)
|
||
# 7. systemd unit + автозапуск
|
||
#
|
||
# Что НЕ автоматизируется (только пользователь):
|
||
# - СКЗИ Валидата CSP — выдаётся НРД по запросу (soed@nsd.ru)
|
||
# - Сертификат подписи УЦ Московской Биржи (ca.moex.com)
|
||
# - Регистрация в TEST3 (заявка через nsd.ru)
|
||
|
||
set -euo pipefail
|
||
|
||
# ---- параметры ----
|
||
REPO_URL="${REPO_URL:-https://git.zetit.ru/zuevav/Bridge-and-Join-s.git}"
|
||
BRANCH="${BRANCH:-main}"
|
||
BIND_ADDR="${BIND_ADDR:-:8080}"
|
||
ISH_DEB_URL="${ISH_DEB_URL:-https://old.nsd.ru/upload/docs/edo/po/igate_100.0-765_amd64.deb}"
|
||
SKIP_ISH=0
|
||
NON_INTERACTIVE="${NON_INTERACTIVE:-0}"
|
||
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--skip-ish) SKIP_ISH=1 ;;
|
||
--bind=*) BIND_ADDR="${arg#*=}" ;;
|
||
--branch=*) BRANCH="${arg#*=}" ;;
|
||
--yes|-y) NON_INTERACTIVE=1 ;;
|
||
esac
|
||
done
|
||
|
||
# ---- утилиты вывода ----
|
||
NS=$(date +%s)
|
||
step() { local n=$(( $(date +%s) - NS )); printf "\033[1;36m[%4ds]\033[0m \033[1;34m▶\033[0m %s\n" "$n" "$*"; }
|
||
ok() { printf " \033[1;32m✓\033[0m %s\n" "$*"; }
|
||
warn() { printf " \033[1;33m⚠\033[0m %s\n" "$*"; }
|
||
fail() { printf " \033[1;31m✗\033[0m %s\n" "$*" >&2; exit 1; }
|
||
ask() {
|
||
[ "$NON_INTERACTIVE" = "1" ] && return 0
|
||
printf " \033[1;35m?\033[0m %s [y/N]: " "$*"
|
||
read -r REPLY < /dev/tty || REPLY=n
|
||
[ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]
|
||
}
|
||
|
||
# ---- баннер ----
|
||
clear 2>/dev/null || true
|
||
cat <<'BANNER'
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ ║
|
||
║ Bridge-and-Join-s — установка с нуля ║
|
||
║ сервис M2M-переводов с НКО АО НРД ║
|
||
║ ║
|
||
║ Установка займёт ~5-10 минут ║
|
||
║ Скачается ~150-250 МБ (Go + ИШ + миграции) ║
|
||
║ ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
BANNER
|
||
echo
|
||
|
||
[ "$EUID" -eq 0 ] || fail "Запускать от root: sudo bash $0"
|
||
|
||
# ============================================================
|
||
# ШАГ 1/9. Определение ОС
|
||
# ============================================================
|
||
step "1/9: определение операционной системы"
|
||
OS_KIND=""
|
||
OS_NAME="неизвестно"
|
||
|
||
if [ -r /etc/astra_version ]; then
|
||
OS_NAME="Astra Linux $(cat /etc/astra_version)"
|
||
OS_KIND="astra"
|
||
elif [ -r /etc/os-release ]; then
|
||
. /etc/os-release
|
||
OS_NAME="$PRETTY_NAME"
|
||
case "${ID:-}" in
|
||
astra) OS_KIND="astra" ;;
|
||
debian) OS_KIND="debian" ;;
|
||
ubuntu) OS_KIND="ubuntu" ;;
|
||
*)
|
||
case "${ID_LIKE:-}" in
|
||
*debian*) OS_KIND="debian-like" ;;
|
||
esac
|
||
;;
|
||
esac
|
||
fi
|
||
ok "Обнаружено: $OS_NAME"
|
||
|
||
case "$OS_KIND" in
|
||
astra)
|
||
ok "Astra Linux — полностью поддерживается, ИШ заработает официально"
|
||
;;
|
||
debian|"debian-like")
|
||
warn "Debian-based — bj-server установится, ИШ скорее всего тоже"
|
||
warn "(но официально НРД его не поддерживает на Debian; для прод-инфры лучше Astra Linux SE)"
|
||
;;
|
||
ubuntu)
|
||
warn "Ubuntu — bj-server установится, но ИШ может потребовать допилов"
|
||
ask "Продолжить?" || exit 1
|
||
;;
|
||
*)
|
||
fail "Неподдерживаемая ОС. Поддерживаются: Astra Linux (SE/CE), Debian, Ubuntu"
|
||
;;
|
||
esac
|
||
|
||
# ============================================================
|
||
# ШАГ 2/9. Системные пакеты
|
||
# ============================================================
|
||
step "2/9: установка системных пакетов через apt"
|
||
export DEBIAN_FRONTEND=noninteractive
|
||
apt-get update -qq >/dev/null
|
||
apt-get install -y -qq \
|
||
ca-certificates curl wget git tar gzip \
|
||
podman postgresql-client \
|
||
>/dev/null 2>&1
|
||
# podman-compose доступен либо как apt-пакет, либо как pip — пробуем оба
|
||
if ! command -v podman-compose >/dev/null 2>&1; then
|
||
apt-get install -y -qq podman-compose >/dev/null 2>&1 || \
|
||
apt-get install -y -qq python3-pip >/dev/null 2>&1 && pip3 install --quiet podman-compose 2>/dev/null || true
|
||
fi
|
||
command -v podman >/dev/null && ok "podman: $(podman --version | awk '{print $3}')" || fail "podman не установился"
|
||
command -v git >/dev/null && ok "git: $(git --version | awk '{print $3}')" || fail "git не установился"
|
||
|
||
# ============================================================
|
||
# ШАГ 3/9. Go 1.24+
|
||
# ============================================================
|
||
step "3/9: Go 1.24+"
|
||
need_go=1
|
||
if command -v go >/dev/null 2>&1; then
|
||
GO_HAVE=$(go version | awk '{print $3}' | sed 's/go//')
|
||
if printf '%s\n%s' "1.24" "$GO_HAVE" | sort -V | head -1 | grep -q '^1.24$'; then
|
||
ok "Go $GO_HAVE — подходит"
|
||
need_go=0
|
||
else
|
||
warn "Go $GO_HAVE — слишком старый, обновляю"
|
||
fi
|
||
fi
|
||
if [ "$need_go" = 1 ]; then
|
||
GO_VER="1.24.0"
|
||
ok "качаю Go $GO_VER с go.dev (~70 МБ)..."
|
||
curl -sSL "https://go.dev/dl/go${GO_VER}.linux-amd64.tar.gz" -o /tmp/go.tar.gz \
|
||
|| fail "не получилось скачать Go (нужен интернет)"
|
||
rm -rf /usr/local/go
|
||
tar -C /usr/local -xzf /tmp/go.tar.gz
|
||
ln -sf /usr/local/go/bin/go /usr/local/bin/go
|
||
ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
|
||
rm -f /tmp/go.tar.gz
|
||
ok "Go $GO_VER установлен в /usr/local/go"
|
||
fi
|
||
|
||
# ============================================================
|
||
# ШАГ 4/9. Пользователь bj и каталоги
|
||
# ============================================================
|
||
step "4/9: системный пользователь bj и каталоги"
|
||
if ! id bj >/dev/null 2>&1; then
|
||
useradd --system --create-home --home-dir /var/lib/bj --shell /bin/bash bj
|
||
ok "создан пользователь bj"
|
||
else
|
||
ok "пользователь bj уже существует"
|
||
fi
|
||
install -d -o bj -g bj -m 0755 /opt/bj /var/lib/bj /var/log/bj
|
||
install -d -o bj -g bj -m 0700 /var/lib/bj/.bj
|
||
ok "каталоги: /opt/bj /var/lib/bj /var/log/bj"
|
||
|
||
# ============================================================
|
||
# ШАГ 5/9. Клон репо и сборка bj-server
|
||
# ============================================================
|
||
step "5/9: клон репозитория и сборка bj-server"
|
||
SRC=/opt/bj/src
|
||
if [ -d "$SRC/.git" ]; then
|
||
sudo -u bj -H git -C "$SRC" fetch --quiet origin
|
||
sudo -u bj -H git -C "$SRC" reset --hard --quiet "origin/$BRANCH"
|
||
ok "репо обновлено до $BRANCH"
|
||
else
|
||
sudo -u bj -H git clone --quiet --branch "$BRANCH" "$REPO_URL" "$SRC" \
|
||
|| fail "git clone failed"
|
||
ok "репо склонирован"
|
||
fi
|
||
chown -R bj:bj "$SRC"
|
||
|
||
ok "компиляция bj-server..."
|
||
sudo -u bj -H bash -c "cd $SRC && /usr/local/bin/go build -o /opt/bj/bj-server ./cmd/bj-server" \
|
||
|| fail "go build failed"
|
||
chown bj:bj /opt/bj/bj-server
|
||
chmod 0755 /opt/bj/bj-server
|
||
ok "бинарник: /opt/bj/bj-server ($(du -h /opt/bj/bj-server | awk '{print $1}'))"
|
||
|
||
# ============================================================
|
||
# ШАГ 6/9. PostgreSQL в podman + миграции
|
||
# ============================================================
|
||
step "6/9: PostgreSQL в podman + миграции БД"
|
||
cd "$SRC"
|
||
if ! podman ps --format '{{.Names}}' 2>/dev/null | grep -qx bj-postgres; then
|
||
sudo -u bj -H podman-compose -f deploy/docker-compose/docker-compose.yml up -d postgres \
|
||
2>/dev/null || {
|
||
warn "podman-compose не сработал, пробую podman run напрямую"
|
||
sudo -u bj -H podman run -d --name bj-postgres \
|
||
-e POSTGRES_USER=bj -e POSTGRES_PASSWORD=bj_dev -e POSTGRES_DB=bj \
|
||
-p 127.0.0.1:5432:5432 \
|
||
docker.io/library/postgres:16-alpine
|
||
}
|
||
sleep 5
|
||
fi
|
||
# Ждём pg_isready
|
||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||
if sudo -u bj -H podman exec bj-postgres pg_isready -U bj -d bj >/dev/null 2>&1; then
|
||
ok "PostgreSQL готов"
|
||
break
|
||
fi
|
||
sleep 2
|
||
done
|
||
|
||
# Накат миграций
|
||
MIG_COUNT=0
|
||
for mig in migrations/fansy-store/*.sql migrations/m2m-core/*.sql; do
|
||
if [ -f "$mig" ]; then
|
||
sudo -u bj -H podman exec -i bj-postgres psql -U bj -d bj -v ON_ERROR_STOP=0 < "$mig" >/dev/null 2>&1 && \
|
||
MIG_COUNT=$((MIG_COUNT+1))
|
||
fi
|
||
done
|
||
ok "миграций накачено: $MIG_COUNT"
|
||
|
||
# Сохраняем DSN
|
||
cat > /var/lib/bj/.bj/setup.json <<EOF
|
||
{
|
||
"postgres": {"dsn": "postgres://bj:bj_dev@127.0.0.1:5432/bj?sslmode=disable"},
|
||
"crypto": {"provider": "stub", "socket_path": "/run/bj/crypto.sock"},
|
||
"nsd": {},
|
||
"lk": {},
|
||
"ca_certs": {},
|
||
"news": {},
|
||
"updated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||
}
|
||
EOF
|
||
chown bj:bj /var/lib/bj/.bj/setup.json
|
||
chmod 0600 /var/lib/bj/.bj/setup.json
|
||
ok "DSN сохранён в /var/lib/bj/.bj/setup.json"
|
||
|
||
# ============================================================
|
||
# ШАГ 7/9. systemd unit
|
||
# ============================================================
|
||
step "7/9: systemd unit для bj-server"
|
||
cat > /etc/systemd/system/bj-server.service <<EOF
|
||
[Unit]
|
||
Description=Bridge-and-Join-s — единый сервис M2M-переводов
|
||
Documentation=$REPO_URL
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=bj
|
||
Group=bj
|
||
WorkingDirectory=$SRC
|
||
ExecStart=/opt/bj/bj-server
|
||
Restart=on-failure
|
||
RestartSec=5
|
||
|
||
Environment=BJ_HTTP_ADDR=$BIND_ADDR
|
||
Environment=BJ_SETUP_PATH=/var/lib/bj/.bj/setup.json
|
||
Environment=BJ_M2M_SENDER=MC0079200000
|
||
Environment=BJ_M2M_RECEIVER=MC0010300000
|
||
|
||
NoNewPrivileges=true
|
||
ProtectSystem=strict
|
||
ProtectHome=true
|
||
ReadWritePaths=/var/lib/bj /var/log/bj
|
||
PrivateTmp=true
|
||
|
||
StandardOutput=append:/var/log/bj/bj-server.log
|
||
StandardError=append:/var/log/bj/bj-server.err
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
systemctl daemon-reload
|
||
systemctl enable bj-server >/dev/null 2>&1
|
||
systemctl restart bj-server
|
||
sleep 2
|
||
if systemctl is-active --quiet bj-server; then
|
||
ok "bj-server.service active"
|
||
else
|
||
warn "bj-server не стартанул, см. journalctl -u bj-server -n 30"
|
||
fi
|
||
|
||
# ============================================================
|
||
# ШАГ 8/9. ИШ НРД — скачивание и установка
|
||
# ============================================================
|
||
if [ "$SKIP_ISH" = "1" ]; then
|
||
step "8/9: ИШ НРД — пропущено (--skip-ish)"
|
||
else
|
||
step "8/9: Интеграционный шлюз НРД (ИШ)"
|
||
ISH_LOCAL="$SRC/dist/ish/igate_100.0-765_amd64.deb"
|
||
if [ -f "$ISH_LOCAL" ]; then
|
||
ok "дистрибутив ИШ уже в репо: $ISH_LOCAL"
|
||
else
|
||
ok "качаю дистрибутив ИШ с НРД (~120 МБ)..."
|
||
mkdir -p "$(dirname "$ISH_LOCAL")"
|
||
if curl -sSL -A "Mozilla/5.0" "$ISH_DEB_URL" -o "$ISH_LOCAL" --max-time 600; then
|
||
ok "скачан: $(du -h "$ISH_LOCAL" | awk '{print $1}')"
|
||
else
|
||
warn "не получилось скачать ИШ автоматически"
|
||
warn "скачайте вручную: $ISH_DEB_URL"
|
||
warn "и положите в $ISH_LOCAL, потом перезапустите этот скрипт"
|
||
ISH_LOCAL=""
|
||
fi
|
||
fi
|
||
|
||
if [ -n "$ISH_LOCAL" ] && [ -f "$ISH_LOCAL" ]; then
|
||
ok "установка ИШ через dpkg..."
|
||
if dpkg -i "$ISH_LOCAL" >/dev/null 2>&1; then
|
||
ok "ИШ установлен"
|
||
else
|
||
# Часто dpkg падает на зависимостях — пробуем apt-get install -f
|
||
apt-get install -f -y >/dev/null 2>&1
|
||
if dpkg -i "$ISH_LOCAL" >/dev/null 2>&1; then
|
||
ok "ИШ установлен (после починки зависимостей)"
|
||
else
|
||
warn "ИШ не встал — возможно нет Валидаты или системных пакетов"
|
||
warn "это нормально на текущем этапе — продолжаем"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# ============================================================
|
||
# ШАГ 9/9. Финальная проверка
|
||
# ============================================================
|
||
step "9/9: проверка готовности"
|
||
sleep 1
|
||
CODE=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1${BIND_ADDR}/admin/" 2>/dev/null || echo "—")
|
||
[ "$CODE" = "200" ] && ok "веб-админка отвечает: HTTP 200" || warn "веб-админка пока не отвечает (HTTP $CODE) — проверь логи"
|
||
|
||
IP=$(hostname -I | awk '{print $1}')
|
||
echo
|
||
echo "╔══════════════════════════════════════════════════════════════════╗"
|
||
echo "║ УСТАНОВКА BJ-SERVER ЗАВЕРШЕНА ║"
|
||
echo "╚══════════════════════════════════════════════════════════════════╝"
|
||
echo
|
||
echo " Веб-админка: http://$IP${BIND_ADDR}/admin/"
|
||
echo " Мастер настройки: http://$IP${BIND_ADDR}/admin/wizard"
|
||
echo " Архитектура: http://$IP${BIND_ADDR}/admin/help/architecture"
|
||
echo " Новости: http://$IP${BIND_ADDR}/admin/news"
|
||
echo
|
||
echo " Логи: tail -f /var/log/bj/bj-server.log"
|
||
echo " Сервис: systemctl status bj-server"
|
||
echo
|
||
echo " ──── ЧТО ОСТАЛОСЬ СДЕЛАТЬ (НЕ АВТОМАТИЧЕСКИ) ───────────────"
|
||
echo
|
||
echo " 1. Запросить СКЗИ Валидата CSP у НРД:"
|
||
echo " Email: soed@nsd.ru"
|
||
echo " Текст: «Запрос дистрибутива Валидата CSP для Linux + временной"
|
||
echo " лицензии для подключения к ЭДО НРД в рамках MOEX МОСТ M2M.»"
|
||
echo
|
||
echo " 2. Получить сертификат подписи в УЦ Московской Биржи:"
|
||
echo " https://ca.moex.com/"
|
||
echo
|
||
echo " 3. Подать заявку на тестирование в TEST3:"
|
||
echo " https://www.nsd.ru/workflow/zayavka-na-testirovanie/"
|
||
echo
|
||
echo " 4. Когда придёт Валидата — поставить:"
|
||
echo " sudo bash $SRC/deploy/astra/install-validata.sh /path/to/validata-*.deb"
|
||
echo
|
||
echo " 5. Когда заработает ИШ — указать его URL в /admin/setup → «ИШ НРД»"
|
||
echo
|
||
echo " ──── ПРОВЕРКА СОСТОЯНИЯ ВСЕГО ──────────────────────────────"
|
||
echo " sudo bash $SRC/deploy/astra/healthcheck.sh"
|
||
echo
|