765d7b5994
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
114 lines
8.4 KiB
Bash
Executable File
114 lines
8.4 KiB
Bash
Executable File
#!/bin/bash
|
||
# Первая загрузка сервера, установленного с образа Bridge&Join. Спрашивает ключ продукта на консоли;
|
||
# без ключа ставит ядро bj с образа (/var/lib/bj/bundle), а ключ вводится в браузере на первой
|
||
# странице настройки. Пока bj не установлен, вопрос повторяется при каждой загрузке (с таймаутом),
|
||
# адрес и подсказки всегда есть на экране входа (bj-welcome).
|
||
set -u
|
||
MARK=/var/lib/bj/.bj/installed-from-iso
|
||
SERVER=https://lic.zetit.ru
|
||
CHANNEL=stable
|
||
BUNDLE=/var/lib/bj/bundle
|
||
[ -s /etc/bj/channel ] && CHANNEL=$(tr -d ' \n' < /etc/bj/channel)
|
||
finish() {
|
||
mkdir -p "$(dirname "$MARK")" && date -Iseconds > "$MARK"
|
||
systemctl disable bj-firstboot.service >/dev/null 2>&1
|
||
[ -x /usr/local/sbin/bj-welcome ] && /usr/local/sbin/bj-welcome
|
||
}
|
||
urls() { ip -4 -o addr show scope global 2>/dev/null | awk '{split($4,a,"/"); printf " https://%s:8443%s\n", a[1], "'"$1"'"}'; }
|
||
# Пока идут вопросы, сообщения загрузки на консоль не выводятся (ядро — только аварийные,
|
||
# systemd — без строк «[ OK ] Started …»), иначе они перемешиваются с текстом на экране.
|
||
quiet_console() { dmesg -n 1 2>/dev/null; kill -s RTMIN+21 1 2>/dev/null; sleep 2; }
|
||
quiet_console
|
||
ACC_DONE=/var/lib/bj/.bj/os-accounts-set
|
||
ACCOUNTS=""
|
||
genpw() { local p=""; while [ ${#p} -lt 12 ]; do p="$p$(head -c 48 /dev/urandom | tr -dc 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789')"; done; printf '%s-%s-%s' "${p:0:4}" "${p:4:4}" "${p:8:4}"; }
|
||
askpw() { # $1 — логин, $2 — предложенный пароль; печатает итоговый пароль
|
||
while true; do
|
||
printf ' Пароль для %s: %s\n Enter — принять, или введите свой (не короче 10 символов): ' "$1" "$2" > /dev/tty
|
||
stty -echo < /dev/tty; read -r P1 < /dev/tty; stty echo < /dev/tty; printf '\n' > /dev/tty
|
||
[ -z "$P1" ] && { printf '%s' "$2"; return; }
|
||
[ ${#P1} -lt 10 ] && { printf ' Короче 10 символов, ещё раз.\n' > /dev/tty; continue; }
|
||
printf ' Повторите: ' > /dev/tty; stty -echo < /dev/tty; read -r P2 < /dev/tty; stty echo < /dev/tty; printf '\n' > /dev/tty
|
||
[ "$P1" = "$P2" ] && { printf '%s' "$P1"; return; }
|
||
printf ' Не совпало, ещё раз.\n' > /dev/tty
|
||
done
|
||
}
|
||
setup_accounts() {
|
||
[ -f "$ACC_DONE" ] && return
|
||
id user_bj >/dev/null 2>&1 || useradd -m -s /bin/bash -c "Пользователь сервера bj" -G adm,systemd-journal user_bj
|
||
id root_bj >/dev/null 2>&1 && usermod -aG sudo root_bj
|
||
clear
|
||
printf '\n Bridge&Join: учётные записи сервера\n ────────────────────────────────────────────────────────────\n'
|
||
printf ' root_bj — администратор сервера (команды через sudo)\n user_bj — обычный вход (журналы, без прав администратора)\n'
|
||
printf ' Работа с bj — в браузере; эти учётные записи нужны для обслуживания ОС.\n\n'
|
||
printf ' Шаг 1 из 2 — пароли. Для каждой учётной записи предложен пароль:\n'
|
||
printf ' • Enter — оставить предложенный (он будет показан ещё раз в конце, запишите его);\n'
|
||
printf ' • или наберите свой (не короче 10 символов, при вводе не отображается) и Enter.\n\n'
|
||
PA=$(askpw root_bj "$(genpw)"); PU=$(askpw user_bj "$(genpw)")
|
||
printf 'root_bj:%s\nuser_bj:%s\n' "$PA" "$PU" | chpasswd
|
||
mkdir -p "$(dirname "$ACC_DONE")" && date -Iseconds > "$ACC_DONE"
|
||
ACCOUNTS=$(printf ' root_bj (администратор, sudo) пароль: %s\n user_bj (обычный вход) пароль: %s\n' "$PA" "$PU")
|
||
unset PA PU
|
||
}
|
||
show_accounts() {
|
||
[ -n "$ACCOUNTS" ] || return
|
||
printf '\n ┌── ЗАПИШИТЕ: учётные записи сервера ──────────────────────────┐\n%s\n' "$ACCOUNTS"
|
||
printf ' └── пароли нигде не сохранены и больше не будут показаны ──────┘\n'
|
||
printf ' Сменить пароль: passwd (под своей учётной записью)\n\n'
|
||
}
|
||
setup_accounts
|
||
# постоянный адрес: DHCP может выдать серверу другой адрес, и bj «потеряется» (только Ubuntu/netplan)
|
||
if [ ! -f /var/lib/bj/.bj/network-asked ] && [ -x /usr/local/sbin/bj-network ] && command -v netplan >/dev/null; then
|
||
mkdir -p /var/lib/bj/.bj && date -Iseconds > /var/lib/bj/.bj/network-asked
|
||
printf '\n Сейчас адрес сервера: %s\n' "$(ip -4 -o addr show scope global 2>/dev/null | awk '{print $4}' | tr '\n' ' ')"
|
||
read -t 60 -r -p " Задать постоянный адрес (рекомендуется)? [д/Н]: " ANS < /dev/tty || ANS=""
|
||
case "$ANS" in [дДyY]*) /usr/local/sbin/bj-network < /dev/tty ;; esac
|
||
fi
|
||
clear
|
||
printf '\n Bridge&Join: установка на сервер\n ────────────────────────────────────────────────────────────\n'
|
||
printf ' Шаг 2 из 2 — установка bj. Система установлена, осталось поставить bj.\n\n'
|
||
if [ -f "$BUNDLE/manifest.json" ]; then
|
||
printf ' Ключ продукта (BJ-XXXX-XXXX-XXXX) есть в портале клиента %s/portal/.\n' "$SERVER"
|
||
printf ' Вводить его здесь необязательно: нажмите Enter — ядро bj установится с образа,\n а ключ вы введёте в браузере на первой странице настройки (там его удобно вставить).\n\n'
|
||
else
|
||
printf ' Нужен ключ продукта (BJ-XXXX-XXXX-XXXX): он есть в портале клиента %s/portal/\n\n' "$SERVER"
|
||
fi
|
||
for i in $(seq 1 30); do
|
||
curl -fsS -m 5 -o /dev/null "$SERVER/healthz" && break
|
||
[ "$i" = 1 ] && printf ' Жду сеть и связь с %s…\n' "$SERVER"
|
||
sleep 2
|
||
done
|
||
while true; do
|
||
CODE=""
|
||
if [ -f "$BUNDLE/manifest.json" ]; then
|
||
read -t 120 -r -p " Ключ продукта (Enter — установить с образа, ключ ввести в браузере): " CODE || true
|
||
else
|
||
read -t 120 -r -p " Ключ продукта (Enter — установить позже): " CODE || true
|
||
fi
|
||
CODE=$(printf '%s' "${CODE:-}" | tr -d ' ' | tr '[:lower:]' '[:upper:]')
|
||
if [ -z "$CODE" ]; then
|
||
if [ -f "$BUNDLE/manifest.json" ]; then
|
||
if /usr/local/sbin/bj-installer install --bundle "$BUNDLE" --server "$SERVER" --channel "$CHANNEL"; then
|
||
finish # адрес, код и подсказку про ключ продукта уже вывел bj-installer
|
||
show_accounts
|
||
read -r -p " Нажмите Enter, чтобы перейти к экрану входа. " _ || true
|
||
exit 0
|
||
fi
|
||
show_accounts
|
||
printf '\n Установка с образа не завершилась. Подробности выше; повторить:\n sudo bj-installer install --bundle %s\n\n' "$BUNDLE"
|
||
sleep 5; exit 0
|
||
fi
|
||
show_accounts
|
||
printf '\n Установка bj отложена. Вопрос повторится при следующей загрузке; вручную:\n sudo bj-installer install --code КЛЮЧ-ПРОДУКТА\n\n'
|
||
read -r -p " Нажмите Enter, чтобы перейти к экрану входа. " _ || true
|
||
exit 0
|
||
fi
|
||
if /usr/local/sbin/bj-installer install --code "$CODE" --server "$SERVER" --channel "$CHANNEL"; then
|
||
finish
|
||
show_accounts
|
||
read -r -p " Нажмите Enter, чтобы перейти к экрану входа. " _ || true
|
||
exit 0
|
||
fi
|
||
printf '\n Установка не завершилась. Проверьте ключ продукта и сеть и попробуйте ещё раз.\n\n'
|
||
done
|