d5b5597c67
Содержимое первого коммита:
- Структура моно-репо: cmd/{lk-gateway,m2m-core,nsd-adapter,lk-emulator,notify}/,
internal/{m2m,nsdxml,fansystore,notify}/, services/crypto-service/,
web/admin-ui/, deploy/docker-compose/, migrations/, docs/.
- Заглушки main.go во всех cmd/ — make build проходит из коробки.
- Makefile с целями build/test/lint/fmt/vet/tidy/ci/compose-up/compose-down.
- .golangci.yml, .gitignore, README.md (на русском).
- .claude/settings.json — общие ограничения Claude Code для команды
(запрет sudo, rm -rf, доступа к /etc/cryptopro, /var/cryptopro).
- README в каждом каталоге — назначение и стадия (M1..M5).
- docs/architecture/overview.md — выжимка из плана проекта.
- docs/fansy-contract/v1/, docs/lk-contract/v1/ — точки сборки контрактов
с командами Fansy и ЛК клиента.
- deploy/docker-compose/docker-compose.yml — dev-стек (PostgreSQL, MinIO).
- scripts/setup-dev-vm.sh — первичная подготовка dev-ВМ под РЕД ОС 7.x
и Ubuntu 22.04+ (для компаний без бюджета на лицензии); ставит Go 1.23,
Liberica JDK 21, Node.js 20 LTS, Podman, podman-compose, Claude Code CLI;
создаёт пользователя dev, /srv/dev, аудит-history. Идемпотентен.
- scripts/README.md — описание скрипта и ограничений.
Что НЕ коммитим:
- Секреты, ключи, сертификаты — закрыто в .gitignore.
- Локальные настройки Claude Code (settings.local.json) и сессионные
каталоги (.claude/projects/, .claude/worktrees/, .claude/logs/).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
374 lines
16 KiB
Bash
Executable File
374 lines
16 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Скрипт первичной подготовки dev-ВМ для проекта Bridge and Join's
|
||
# (сервис M2M-перевода ЦБ через НРД).
|
||
#
|
||
# Поддерживаемые ОС:
|
||
# - РЕД ОС 7.x — целевая прод-ОС (вариант с бюджетом на лицензии)
|
||
# - Ubuntu 22.04+ — бюджетная альтернатива для разработки и для
|
||
# компаний, у которых ещё нет лицензий на РЕД ОС
|
||
# (для прод-сертификации в финсекторе всё равно
|
||
# потребуется РЕД ОС / Astra SE с сертификатом ФСТЭК)
|
||
#
|
||
# Что делает:
|
||
# - определяет ОС и пакетный менеджер;
|
||
# - устанавливает базовый dev-стек (Git, Make, jq, xmlstarlet, ...);
|
||
# - устанавливает Go 1.23, Liberica JDK 21, Node.js 20 LTS, Podman;
|
||
# - устанавливает Claude Code CLI;
|
||
# - создаёт пользователя dev и каталог /srv/dev;
|
||
# - готовит безопасный shell-history с timestamp.
|
||
#
|
||
# Запуск (под root или через sudo):
|
||
# sudo bash scripts/setup-dev-vm.sh
|
||
#
|
||
# Переменные окружения для тонкой настройки:
|
||
# GO_VERSION — версия Go (по умолчанию 1.23.4)
|
||
# JDK_VERSION — версия Liberica JDK (по умолчанию 21)
|
||
# NODE_VERSION — версия Node (по умолчанию 20)
|
||
# DEV_USER — имя пользователя для разработки (по умолчанию dev)
|
||
# DEV_HOME — домашняя директория dev (по умолчанию /home/dev)
|
||
# WORKSPACE_ROOT — корень рабочих репо (по умолчанию /srv/dev)
|
||
# SKIP_USER — 1, чтобы не создавать пользователя
|
||
# SKIP_CLAUDE — 1, чтобы не ставить Claude Code CLI
|
||
#
|
||
# Скрипт идемпотентен — повторный запуск не ломает то, что уже сделано.
|
||
|
||
set -euo pipefail
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# Параметры
|
||
# --------------------------------------------------------------------- #
|
||
GO_VERSION="${GO_VERSION:-1.23.4}"
|
||
JDK_VERSION="${JDK_VERSION:-21}"
|
||
NODE_VERSION="${NODE_VERSION:-20}"
|
||
DEV_USER="${DEV_USER:-dev}"
|
||
DEV_HOME="${DEV_HOME:-/home/${DEV_USER}}"
|
||
WORKSPACE_ROOT="${WORKSPACE_ROOT:-/srv/dev}"
|
||
SKIP_USER="${SKIP_USER:-0}"
|
||
SKIP_CLAUDE="${SKIP_CLAUDE:-0}"
|
||
|
||
REPO_URL="https://git.zetit.ru/zuevav/Bridge-and-Join-s.git"
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# Хелперы
|
||
# --------------------------------------------------------------------- #
|
||
log() { printf '[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*"; }
|
||
die() { printf '[ОШИБКА] %s\n' "$*" >&2; exit 1; }
|
||
need_root() { [[ "$EUID" -eq 0 ]] || die "Нужны права root. Запусти через sudo."; }
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 0. Предусловия — определение ОС и менеджера пакетов
|
||
# --------------------------------------------------------------------- #
|
||
need_root
|
||
|
||
if [[ ! -f /etc/os-release ]]; then
|
||
die "Файл /etc/os-release не найден. Проверь, что ОС поддерживает FHS."
|
||
fi
|
||
|
||
# shellcheck disable=SC1091
|
||
. /etc/os-release
|
||
|
||
OS_FAMILY="" # rpm | deb
|
||
OS_HUMAN=""
|
||
|
||
case "${ID:-}" in
|
||
redos)
|
||
OS_FAMILY="rpm"
|
||
OS_HUMAN="РЕД ОС ${VERSION_ID:-?}"
|
||
;;
|
||
rhel|centos|rocky|almalinux|fedora)
|
||
OS_FAMILY="rpm"
|
||
OS_HUMAN="${PRETTY_NAME:-RHEL-совместимая}"
|
||
log "ВНИМАНИЕ: ОС ${OS_HUMAN} — для разработки подходит, для прод-сертификации в финсекторе нужна РЕД ОС / Astra SE."
|
||
;;
|
||
ubuntu|debian)
|
||
OS_FAMILY="deb"
|
||
OS_HUMAN="${PRETTY_NAME:-${ID} ${VERSION_ID:-?}}"
|
||
log "ОС ${OS_HUMAN} — бюджетный вариант для разработки. Для прода в финсекторе нужна РЕД ОС / Astra SE с сертификатом ФСТЭК."
|
||
;;
|
||
astra)
|
||
OS_FAMILY="deb"
|
||
OS_HUMAN="Astra Linux ${VERSION_ID:-?}"
|
||
;;
|
||
*)
|
||
log "ВНИМАНИЕ: ОС определена как ${ID:-неизвестно} ${VERSION_ID:-?}."
|
||
if command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1; then
|
||
OS_FAMILY="rpm"
|
||
elif command -v apt-get >/dev/null 2>&1; then
|
||
OS_FAMILY="deb"
|
||
else
|
||
die "Не удалось определить пакетный менеджер. Поддерживаются dnf/yum (РЕД ОС, RHEL) и apt (Ubuntu, Debian, Astra)."
|
||
fi
|
||
log "Пробуем как ${OS_FAMILY}-совместимую."
|
||
;;
|
||
esac
|
||
|
||
log "ОС: ${OS_HUMAN}, семейство: ${OS_FAMILY}"
|
||
|
||
PKG_INSTALL=""
|
||
PKG_UPDATE=""
|
||
case "${OS_FAMILY}" in
|
||
rpm)
|
||
if command -v dnf >/dev/null 2>&1; then PKG_INSTALL="dnf install -y"; PKG_UPDATE="dnf -y makecache"
|
||
elif command -v yum >/dev/null 2>&1; then PKG_INSTALL="yum install -y"; PKG_UPDATE="yum -y makecache"
|
||
else die "Не найден dnf/yum"
|
||
fi
|
||
;;
|
||
deb)
|
||
export DEBIAN_FRONTEND=noninteractive
|
||
PKG_INSTALL="apt-get install -y --no-install-recommends"
|
||
PKG_UPDATE="apt-get update -y"
|
||
;;
|
||
esac
|
||
|
||
log "Обновление кэша пакетов"
|
||
${PKG_UPDATE}
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 1. Базовый системный стек
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 1/8: установка базовых пакетов"
|
||
case "${OS_FAMILY}" in
|
||
rpm)
|
||
${PKG_INSTALL} \
|
||
git make curl wget tar gzip unzip ca-certificates \
|
||
jq xmlstarlet libxml2 \
|
||
gcc gcc-c++ binutils \
|
||
python3 python3-pip \
|
||
postgresql-libs \
|
||
openssl-libs
|
||
;;
|
||
deb)
|
||
${PKG_INSTALL} \
|
||
git make curl wget tar gzip unzip ca-certificates \
|
||
jq xmlstarlet libxml2-utils \
|
||
build-essential \
|
||
python3 python3-pip python3-venv \
|
||
libpq5 \
|
||
libssl3 \
|
||
gnupg lsb-release software-properties-common
|
||
;;
|
||
esac
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 2. Podman + podman-compose
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 2/8: установка Podman и podman-compose"
|
||
case "${OS_FAMILY}" in
|
||
rpm)
|
||
${PKG_INSTALL} podman podman-docker || true
|
||
;;
|
||
deb)
|
||
${PKG_INSTALL} podman || true
|
||
# podman-docker может отсутствовать — не критично
|
||
apt-get install -y --no-install-recommends podman-docker 2>/dev/null || true
|
||
;;
|
||
esac
|
||
|
||
if ! command -v podman-compose >/dev/null 2>&1; then
|
||
pip3 install --quiet podman-compose || \
|
||
log "ВНИМАНИЕ: не удалось установить podman-compose через pip3. Поставь вручную."
|
||
fi
|
||
|
||
# Включаем сокет podman, чтобы клиенты, ожидающие docker.sock, работали без правок
|
||
systemctl enable --now podman.socket 2>/dev/null || true
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 3. Go
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 3/8: установка Go ${GO_VERSION}"
|
||
GO_TARBALL="go${GO_VERSION}.linux-amd64.tar.gz"
|
||
GO_URL="https://go.dev/dl/${GO_TARBALL}"
|
||
|
||
if [[ -d /usr/local/go && -x /usr/local/go/bin/go ]]; then
|
||
CURRENT_GO_VER="$(/usr/local/go/bin/go version | awk '{print $3}' | sed 's/go//')"
|
||
if [[ "${CURRENT_GO_VER}" == "${GO_VERSION}" ]]; then
|
||
log "Go ${GO_VERSION} уже установлен"
|
||
else
|
||
log "Найден Go ${CURRENT_GO_VER}, переустанавливаем на ${GO_VERSION}"
|
||
rm -rf /usr/local/go
|
||
fi
|
||
fi
|
||
|
||
if [[ ! -d /usr/local/go ]]; then
|
||
TMP_TAR="/tmp/${GO_TARBALL}"
|
||
wget -q --show-progress -O "${TMP_TAR}" "${GO_URL}"
|
||
tar -C /usr/local -xzf "${TMP_TAR}"
|
||
rm -f "${TMP_TAR}"
|
||
fi
|
||
|
||
cat > /etc/profile.d/go.sh <<'EOF'
|
||
export PATH=$PATH:/usr/local/go/bin
|
||
export GOPATH=$HOME/go
|
||
export PATH=$PATH:$GOPATH/bin
|
||
EOF
|
||
chmod 0644 /etc/profile.d/go.sh
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 4. Liberica JDK
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 4/8: установка Liberica JDK ${JDK_VERSION}"
|
||
case "${OS_FAMILY}" in
|
||
rpm)
|
||
if [[ ! -f /etc/yum.repos.d/bellsoft.repo ]]; then
|
||
cat > /etc/yum.repos.d/bellsoft.repo <<'EOF'
|
||
[bellsoft]
|
||
name=BellSoft Repository
|
||
baseurl=https://yum.bell-sw.com/
|
||
enabled=1
|
||
gpgcheck=1
|
||
gpgkey=https://download.bell-sw.com/pki/GPG-KEY-bellsoft
|
||
EOF
|
||
fi
|
||
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}" || \
|
||
log "ВНИМАНИЕ: не удалось установить bellsoft-java${JDK_VERSION}. Альтернатива — скачать tar.gz с https://bell-sw.com/pages/downloads/."
|
||
;;
|
||
deb)
|
||
if [[ ! -f /etc/apt/sources.list.d/bellsoft.list ]]; then
|
||
curl -fsSL https://download.bell-sw.com/pki/GPG-KEY-bellsoft \
|
||
| gpg --dearmor -o /usr/share/keyrings/bellsoft.gpg
|
||
echo "deb [signed-by=/usr/share/keyrings/bellsoft.gpg] https://apt.bell-sw.com/ stable main" \
|
||
> /etc/apt/sources.list.d/bellsoft.list
|
||
apt-get update -y
|
||
fi
|
||
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}-full" || \
|
||
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}" || \
|
||
log "ВНИМАНИЕ: не удалось установить bellsoft-java${JDK_VERSION}. Альтернатива — скачать tar.gz с https://bell-sw.com/pages/downloads/."
|
||
;;
|
||
esac
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 5. Node.js LTS (для admin-ui и Claude Code CLI)
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 5/8: установка Node.js ${NODE_VERSION} LTS"
|
||
need_install_node=1
|
||
if command -v node >/dev/null 2>&1; then
|
||
CUR_NODE_MAJOR="$(node --version | sed 's/v//;s/\..*//')"
|
||
if [[ "${CUR_NODE_MAJOR}" == "${NODE_VERSION}" ]]; then
|
||
log "Node.js ${NODE_VERSION} уже установлен"
|
||
need_install_node=0
|
||
fi
|
||
fi
|
||
|
||
if [[ "${need_install_node}" == "1" ]]; then
|
||
case "${OS_FAMILY}" in
|
||
rpm)
|
||
curl -fsSL "https://rpm.nodesource.com/setup_${NODE_VERSION}.x" | bash -
|
||
${PKG_INSTALL} nodejs
|
||
;;
|
||
deb)
|
||
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
|
||
${PKG_INSTALL} nodejs
|
||
;;
|
||
esac
|
||
fi
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 6. Claude Code CLI
|
||
# --------------------------------------------------------------------- #
|
||
if [[ "${SKIP_CLAUDE}" != "1" ]]; then
|
||
log "Шаг 6/8: установка Claude Code CLI"
|
||
npm install -g @anthropic-ai/claude-code
|
||
else
|
||
log "Шаг 6/8: пропуск установки Claude Code CLI (SKIP_CLAUDE=1)"
|
||
fi
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 7. Пользователь dev и рабочая директория
|
||
# --------------------------------------------------------------------- #
|
||
if [[ "${SKIP_USER}" != "1" ]]; then
|
||
log "Шаг 7/8: подготовка пользователя ${DEV_USER}"
|
||
if ! id -u "${DEV_USER}" >/dev/null 2>&1; then
|
||
useradd -m -s /bin/bash -d "${DEV_HOME}" "${DEV_USER}"
|
||
log "Создан пользователь ${DEV_USER}"
|
||
else
|
||
log "Пользователь ${DEV_USER} уже существует"
|
||
fi
|
||
|
||
mkdir -p "${WORKSPACE_ROOT}"
|
||
chown "${DEV_USER}:${DEV_USER}" "${WORKSPACE_ROOT}"
|
||
|
||
HIST_SNIPPET="${DEV_HOME}/.bashrc.d-history"
|
||
cat > "${HIST_SNIPPET}" <<'EOF'
|
||
# История с timestamp и общая для всех сессий — для аудита.
|
||
export HISTTIMEFORMAT="%F %T "
|
||
export HISTSIZE=10000
|
||
export HISTFILESIZE=20000
|
||
shopt -s histappend
|
||
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-}"
|
||
EOF
|
||
chown "${DEV_USER}:${DEV_USER}" "${HIST_SNIPPET}"
|
||
|
||
if ! grep -q "bashrc.d-history" "${DEV_HOME}/.bashrc" 2>/dev/null; then
|
||
echo "[ -f ${HIST_SNIPPET} ] && . ${HIST_SNIPPET}" >> "${DEV_HOME}/.bashrc"
|
||
fi
|
||
|
||
if ! grep -q "/usr/local/go/bin" "${DEV_HOME}/.bashrc" 2>/dev/null; then
|
||
cat >> "${DEV_HOME}/.bashrc" <<'EOF'
|
||
[ -f /etc/profile.d/go.sh ] && . /etc/profile.d/go.sh
|
||
EOF
|
||
fi
|
||
else
|
||
log "Шаг 7/8: пропуск подготовки пользователя (SKIP_USER=1)"
|
||
fi
|
||
|
||
# --------------------------------------------------------------------- #
|
||
# 8. Финальные проверки
|
||
# --------------------------------------------------------------------- #
|
||
log "Шаг 8/8: проверка установленных версий"
|
||
{
|
||
printf 'git: '; git --version
|
||
printf 'make: '; make --version | head -n1
|
||
printf 'jq: '; jq --version
|
||
printf 'xmlstarlet: '; xmlstarlet --version | head -n1
|
||
printf 'podman: '; podman --version 2>/dev/null || echo "(не установлен)"
|
||
printf 'podman-compose:'; podman-compose --version 2>/dev/null || echo "(не установлен)"
|
||
printf 'go: '; /usr/local/go/bin/go version
|
||
printf 'java: '; java -version 2>&1 | head -n1
|
||
printf 'node: '; node --version 2>/dev/null || echo "(не установлен)"
|
||
printf 'npm: '; npm --version 2>/dev/null || echo "(не установлен)"
|
||
if [[ "${SKIP_CLAUDE}" != "1" ]]; then
|
||
printf 'claude: '; claude --version 2>/dev/null || echo "(не установлен или требует первого запуска)"
|
||
fi
|
||
} || true
|
||
|
||
cat <<EOF
|
||
|
||
──────────────────────────────────────────────────────────────────────
|
||
Подготовка dev-ВМ завершена.
|
||
ОС: ${OS_HUMAN}
|
||
|
||
Дальше — под пользователем ${DEV_USER}:
|
||
|
||
su - ${DEV_USER}
|
||
cd ${WORKSPACE_ROOT}
|
||
|
||
# Положи свой публичный SSH-ключ в ~/.ssh/id_ed25519.pub
|
||
# и добавь его в git.zetit.ru → Settings → SSH Keys
|
||
|
||
git clone ${REPO_URL}
|
||
cd Bridge-and-Join-s
|
||
|
||
make ci # локальный прогон линтера, тестов и сборки
|
||
make compose-up # PostgreSQL + MinIO для разработки
|
||
|
||
# Запуск Claude Code из корня репо:
|
||
claude
|
||
|
||
Дополнительные шаги, которые НЕ автоматизированы (делаются вручную при
|
||
получении соответствующих артефактов от заказчика):
|
||
|
||
1. Установка КриптоПро CSP и КриптоПро JCP под целевую ОС.
|
||
2. Установка дистрибутива Интеграционного шлюза НРД.
|
||
3. Импорт тестовых сертификатов GUEST/TEST3 (ГОСТ + RSA).
|
||
4. Конфигурирование исходящего прокси/whitelist для git.zetit.ru,
|
||
gost-*.nsd.ru, rsa-*.nsd.ru, registry.npmjs.org, proxy.golang.org,
|
||
api.anthropic.com.
|
||
|
||
ВАЖНО про прод:
|
||
Эта ВМ годится для разработки и тестирования. Для прод-стенда в
|
||
финсекторе обязательны РЕД ОС / Astra SE с сертификатом ФСТЭК и
|
||
лицензированный КриптоПро класса КС1 — Ubuntu/Debian для прода
|
||
финсектора не подходят.
|
||
──────────────────────────────────────────────────────────────────────
|
||
EOF
|