chore(deploy): обновление ИШ v107, keymedia, экспортёр QUIK, fail2ban для bj
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+181
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env bash
|
||||
# upgrade-ish-v107.sh — полное автоматическое обновление ИШ до версии 107 на
|
||||
# Astra Linux (amd64) в headless-режиме (сервер без графической сессии).
|
||||
#
|
||||
# ИШ 107 принёс изменения, из-за которых он «из коробки» не стартует как
|
||||
# systemd-служба без графики. Этот скрипт решает ВСЕ слои (проверено 19.08.2026,
|
||||
# см. память ish-v107-upgrade):
|
||||
# 1. Установка .deb (dpkg).
|
||||
# 2. gnome-keyring для секретов (v107 хранит пароли в OS SecretStore/libsecret).
|
||||
# 3. Виртуальный дисплей Xvfb (v107 igate-svc тянет GTK/GVFS).
|
||||
# 4. Параметры канала WSL для v107 (короткий URL, TLS-отпечаток GOST, DN, chain,
|
||||
# M2M) — через configure-ish-v107.sql.
|
||||
# 5. Самоочистка stale-состояния (ExecStartPre) — иначе рестарты флакуют.
|
||||
#
|
||||
# Конфигурация ИШ живёт в PostgreSQL и ПЕРЕЖИВАЕТ обновление.
|
||||
#
|
||||
# Использование:
|
||||
# sudo ./upgrade-ish-v107.sh /путь/к/igate-107-0-930-amd64.zip
|
||||
# Опционально переменные окружения:
|
||||
# SVC_USER (по умолчанию igate) — пользователь службы ИШ
|
||||
# IGATE_DB (по умолчанию igate) — имя БД PostgreSQL
|
||||
# CHAN_ID (по умолчанию auto) — id канала в channels (auto = найти WSL)
|
||||
# KEYRING_PASS_FILE (/var/lib/igate/.keyring-pass) — файл пароля keyring
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
ZIP="${1:?укажите путь к igate-107-*-amd64.zip}"
|
||||
SVC_USER="${SVC_USER:-igate}"
|
||||
IGATE_DB="${IGATE_DB:-igate}"
|
||||
IGATE_DIR="/opt/nsd/igate"
|
||||
WRAPPER="/usr/local/bin/igate-run.sh" # вне /opt — переживает переустановку .deb
|
||||
DROPIN_DIR="/etc/systemd/system/igate.service.d"
|
||||
SQL_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
|
||||
|
||||
log(){ echo -e "\n=== $* ==="; }
|
||||
[ "$(id -u)" = 0 ] || { echo "нужен root (sudo)"; exit 1; }
|
||||
|
||||
SVC_UID="$(id -u "$SVC_USER")"
|
||||
KEYRING_PASS_FILE="${KEYRING_PASS_FILE:-/var/lib/$SVC_USER/.keyring-pass}"
|
||||
HOME_DIR="$(getent passwd "$SVC_USER" | cut -d: -f6)"
|
||||
|
||||
log "0/9 Проверка зависимостей"
|
||||
for bin in dpkg gnome-keyring-daemon dbus-run-session xvfb-run loginctl psql; do
|
||||
command -v "$bin" >/dev/null || { echo "нет $bin — установите (gnome-keyring, dbus-x11, xvfb, libsecret-tools, postgresql-client)"; exit 1; }
|
||||
done
|
||||
echo "все зависимости на месте"
|
||||
|
||||
log "1/9 Распаковка дистрибутива"
|
||||
unzip -o -q "$ZIP" -d "$WORK"
|
||||
DEB="$(ls "$WORK"/*.deb 2>/dev/null | head -1)"
|
||||
[ -n "$DEB" ] || { echo "в архиве нет .deb"; exit 1; }
|
||||
echo "пакет: $(basename "$DEB") версия: $(dpkg-deb -f "$DEB" Version)"
|
||||
|
||||
log "2/9 Бэкап установки, конфига службы и БД"
|
||||
mkdir -p "/var/backups/ish-pre107-$STAMP"
|
||||
BK="/var/backups/ish-pre107-$STAMP"
|
||||
[ -d "$IGATE_DIR" ] && tar czf "$BK/opt-nsd-igate.tar.gz" -C "$(dirname "$IGATE_DIR")" "$(basename "$IGATE_DIR")" 2>/dev/null || true
|
||||
[ -d "$DROPIN_DIR" ] && cp -a "$DROPIN_DIR" "$BK/dropin" || true
|
||||
( cd /tmp && sudo -u postgres pg_dump -d "$IGATE_DB" -Fc | cat > "$BK/igate-db.dump" ) 2>/dev/null || echo " (пропуск дампа БД)"
|
||||
echo "$BK" > /var/backups/ish-last-backup.txt
|
||||
echo "бэкап: $BK"
|
||||
|
||||
log "3/9 Остановка службы и очистка stale-состояния"
|
||||
systemctl stop igate 2>/dev/null || true
|
||||
pkill -9 -u "$SVC_USER" -f igate-svc 2>/dev/null || true
|
||||
pkill -9 -u "$SVC_USER" -f Xvfb 2>/dev/null || true
|
||||
rm -f /tmp/CoreFxPipe_NSD.IGate.* 2>/dev/null || true
|
||||
|
||||
log "4/9 Установка пакета (.deb)"
|
||||
echo "igate igate/service boolean false" | debconf-set-selections
|
||||
echo "igate igate/shortcut boolean false" | debconf-set-selections
|
||||
DEBIAN_FRONTEND=noninteractive dpkg -i --force-confnew "$DEB" || apt-get -f install -y || true
|
||||
echo "версия установлена: $(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null)"
|
||||
|
||||
log "5/9 Подготовка keyring (пароль + linger для XDG_RUNTIME_DIR)"
|
||||
loginctl enable-linger "$SVC_USER"
|
||||
if [ ! -f "$KEYRING_PASS_FILE" ]; then
|
||||
umask 077
|
||||
# локальный пароль keyring (только для сервисного хранилища секретов ИШ)
|
||||
head -c 18 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20 > "$KEYRING_PASS_FILE"
|
||||
chown "$SVC_USER":"$SVC_USER" "$KEYRING_PASS_FILE"; chmod 600 "$KEYRING_PASS_FILE"
|
||||
echo "создан $KEYRING_PASS_FILE"
|
||||
else
|
||||
echo "используется существующий $KEYRING_PASS_FILE"
|
||||
fi
|
||||
# сбросить возможно несовместимый старый login.keyring — wrapper создаст заново
|
||||
rm -f "$HOME_DIR/.local/share/keyrings/login.keyring" 2>/dev/null || true
|
||||
|
||||
log "6/9 Установка wrapper $WRAPPER"
|
||||
cat > "$WRAPPER" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
# headless-запуск igate-svc v107: gnome-keyring + виртуальный дисплей.
|
||||
# Запускается из ExecStart через dbus-run-session (сессионная шина уже есть).
|
||||
export HOME=$HOME_DIR
|
||||
export XDG_DATA_HOME="\$HOME/.local/share"
|
||||
export XDG_RUNTIME_DIR="/run/user/\$(id -u)"
|
||||
export GIO_USE_VFS=local
|
||||
eval "\$(printf '%s\n' "\$(cat $KEYRING_PASS_FILE)" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)"
|
||||
export GNOME_KEYRING_CONTROL SSH_AUTH_SOCK
|
||||
cd "\$HOME"
|
||||
exec xvfb-run -a $IGATE_DIR/igate-svc/igate-svc
|
||||
EOF
|
||||
chmod +x "$WRAPPER"; echo "wrapper установлен"
|
||||
|
||||
log "7/9 Настройка systemd (drop-in с самоочисткой и авто-рестартом)"
|
||||
mkdir -p "$DROPIN_DIR"
|
||||
cat > "$DROPIN_DIR/override.conf" <<EOF
|
||||
[Unit]
|
||||
StartLimitIntervalSec=300
|
||||
StartLimitBurst=8
|
||||
|
||||
[Service]
|
||||
User=$SVC_USER
|
||||
WorkingDirectory=$HOME_DIR
|
||||
# САМООЧИСТКА stale-состояния перед стартом — иначе рестарты флакуют
|
||||
# (осиротевшие CoreFxPipe-сокеты / login.keyring / X-локи).
|
||||
ExecStartPre=-/bin/bash -c 'rm -f /tmp/CoreFxPipe_NSD.IGate.* $HOME_DIR/.local/share/keyrings/login.keyring; find /tmp -maxdepth 1 -name ".X9*-lock" -delete 2>/dev/null; true'
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/dbus-run-session -- $WRAPPER
|
||||
Restart=on-failure
|
||||
RestartSec=8
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
|
||||
log "8/9 Параметры канала v107 (SQL) + миграция паролей"
|
||||
CHAN_ID="${CHAN_ID:-auto}"
|
||||
if [ "$CHAN_ID" = auto ]; then
|
||||
CHAN_ID="$(cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -tAc "select id from channels where type='WSL' order by id limit 1" 2>/dev/null | tr -d '[:space:]')"
|
||||
fi
|
||||
[ -n "$CHAN_ID" ] || { echo "не найден WSL-канал в channels — укажите CHAN_ID вручную"; exit 1; }
|
||||
echo "канал id=$CHAN_ID"
|
||||
if [ -f "$SQL_DIR/configure-ish-v107.sql" ]; then
|
||||
( cd /tmp && sudo -u postgres psql -d "$IGATE_DB" -v chan_id="$CHAN_ID" -f "$SQL_DIR/configure-ish-v107.sql" )
|
||||
else
|
||||
echo " ⚠️ configure-ish-v107.sql не найден рядом со скриптом — параметры канала НЕ применены"
|
||||
fi
|
||||
# Утилита миграции v107 (флаг миграции); финальный Console.ReadKey в headless
|
||||
# безвреден — миграция сохраняется до него.
|
||||
if [ -x "$IGATE_DIR/igate-mig/igate-mig" ]; then
|
||||
sudo -u "$SVC_USER" bash -c '
|
||||
export HOME='"$HOME_DIR"' XDG_DATA_HOME='"$HOME_DIR"'/.local/share XDG_RUNTIME_DIR=/run/user/'"$SVC_UID"'
|
||||
dbus-run-session -- bash -c "
|
||||
eval \$(printf %s\\\\n \"\$(cat '"$KEYRING_PASS_FILE"')\" | gnome-keyring-daemon --replace --unlock --components=secrets,pkcs11 2>/dev/null)
|
||||
echo \"\" | timeout 30 '"$IGATE_DIR"'/igate-mig/igate-mig --data '"$HOME_DIR"' >/dev/null 2>&1 || true
|
||||
"' 2>/dev/null || true
|
||||
echo "igate-mig выполнен (флаг миграции)"
|
||||
fi
|
||||
|
||||
log "9/9 Запуск и проверка"
|
||||
systemctl start igate
|
||||
OK=0
|
||||
for i in $(seq 1 8); do
|
||||
sleep 5
|
||||
if ss -tlnp 2>/dev/null | grep -q ':8090'; then OK=1; break; fi
|
||||
systemctl is-active --quiet igate || break
|
||||
done
|
||||
VER="$(python3 -c "import json;print([k for k in json.load(open('$IGATE_DIR/igate/igate.deps.json'))['libraries'] if k.lower().startswith('igate/')][0])" 2>/dev/null || true)"
|
||||
STATE="$(curl -s http://localhost:8090/api/admin/engine/state 2>/dev/null || true)"
|
||||
echo "версия: $VER"
|
||||
echo "engine/state: ${STATE:-нет ответа}"
|
||||
echo "8090: $(ss -tlnp 2>/dev/null | grep -c ':8090') слушатель"
|
||||
if [ "$OK" = 1 ] && [ "$STATE" = '"Running"' ]; then
|
||||
echo -e "\n✅ ИШ 107 запущен и работает."
|
||||
else
|
||||
cat <<MSG
|
||||
|
||||
⚠️ Web API 8090 не поднялся. Диагностика:
|
||||
• лог движка: /var/lib/$SVC_USER/.local/share/NSD Integration Gateway/logs-svc/log.txt
|
||||
(искать RefreshToken/Unable to start/fingerprint/HTTP)
|
||||
• если 'CA fingerprint mismatch' — сервер покажет actual-отпечаток, вписать его
|
||||
в wslTlsCACertFingerprint (не перепутать контур/крипту GOST↔RSA)
|
||||
• если RefreshToken пустой — проверить wslEndpoint (должен быть КОРОТКИМ базовым)
|
||||
Откат на предыдущую версию:
|
||||
systemctl stop igate && rm -rf $IGATE_DIR &&
|
||||
tar xzf $BK/opt-nsd-igate.tar.gz -C $(dirname "$IGATE_DIR") &&
|
||||
printf '[Service]\nWorkingDirectory=$HOME_DIR\n' > $DROPIN_DIR/override.conf &&
|
||||
systemctl daemon-reload && systemctl start igate
|
||||
MSG
|
||||
fi
|
||||
Reference in New Issue
Block a user