Первичная настройка, часть 4: HTTPS веб-интерфейса (:8443, самоподписанный сертификат на имя и адреса сервера, свой сертификат, перенаправление браузера с HTTP); сервер времени из настроек (ntpd/chrony/timesyncd — bj-system-admin); постоянный адрес — bj-network (netplan try с откатом), вопрос при первой загрузке с образа; раздел «Сервер: HTTPS, время, сеть»; HTTPS в итоговой проверке; адреса https:// на экране установщика и консоли
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -14,7 +14,7 @@ finish() {
|
||||
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 " http://%s:8080%s\n", a[1], "'"$1"'"}'; }
|
||||
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; }
|
||||
@@ -57,6 +57,13 @@ show_accounts() {
|
||||
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'
|
||||
|
||||
@@ -28,6 +28,7 @@ install -m 0755 "$INSTALLER" "$WORK/bj/bj-installer"
|
||||
install -m 0755 "$HERE/bj-firstboot" "$WORK/bj/bj-firstboot"
|
||||
cp "$HERE/bj-firstboot.service" "$WORK/bj/"
|
||||
install -m 0755 "$HERE/../linux/sbin/bj-welcome" "$WORK/bj/bj-welcome"
|
||||
install -m 0755 "$HERE/../linux/sbin/bj-network" "$WORK/bj/bj-network"
|
||||
cp "$HERE/../systemd/bj-welcome.service" "$HERE/../systemd/bj-welcome.timer" "$WORK/bj/"
|
||||
echo "$CHANNEL" > "$WORK/bj/channel"; echo "$VERSION" > "$WORK/bj/version"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ autoinstall:
|
||||
- cp -r /cdrom/bj/bundle /target/var/lib/bj/bundle
|
||||
- cp -r /cdrom/bj/validata /target/var/lib/bj/validata
|
||||
- sh -c 'if [ -d /cdrom/bj/debs ]; then cp -r /cdrom/bj/debs /target/var/lib/bj/debs; fi'
|
||||
- install -m 0755 /cdrom/bj/bj-installer /cdrom/bj/bj-firstboot /cdrom/bj/bj-welcome /target/usr/local/sbin/
|
||||
- install -m 0755 /cdrom/bj/bj-installer /cdrom/bj/bj-firstboot /cdrom/bj/bj-welcome /cdrom/bj/bj-network /target/usr/local/sbin/
|
||||
- install -m 0644 /cdrom/bj/bj-firstboot.service /cdrom/bj/bj-welcome.service /cdrom/bj/bj-welcome.timer /target/etc/systemd/system/
|
||||
- install -m 0644 /cdrom/bj/channel /target/etc/bj/channel
|
||||
- curtin in-target --target=/target -- systemctl enable bj-firstboot.service bj-welcome.service bj-welcome.timer
|
||||
|
||||
@@ -13,6 +13,8 @@ process_one(){
|
||||
component-install) out=$(/usr/local/sbin/bj-component-install "$staging" 2>&1) ;;
|
||||
# интеграционный шлюз НРД: состояние, установка, канал контура (TEST3 | боевой); параметры — JSON в extra
|
||||
igate-status|igate-install|igate-contour) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-igate-admin "${action#igate-}" 2>&1) ;;
|
||||
# системные настройки сервера: серверы времени (NTP)
|
||||
system-ntp) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-system-admin ntp 2>&1) ;;
|
||||
# резервное копирование и восстановление (настройки bj → bj-backup-admin); параметры — JSON в extra
|
||||
backup-config|backup-test|backup-run|backup-list|backup-verify|backup-restore) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-backup-admin "${action#backup-}" 2>&1) ;;
|
||||
# Перезапуск службы модуля из админки. Список закрытый: чужую службу
|
||||
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# bj-network — постоянный адрес сервера bj (на консоли сервера, под sudo). Ubuntu (netplan): спрашивает
|
||||
# адрес, шлюз и DNS и применяет через «netplan try» — если связь пропала и подтверждения нет 120 секунд,
|
||||
# прежние настройки возвращаются сами. Запускается и при первой загрузке с образа (bj-firstboot).
|
||||
set -u
|
||||
[ "$(id -u)" = 0 ] || { echo "запустите через sudo: sudo bj-network"; exit 1; }
|
||||
command -v netplan >/dev/null || { echo "netplan не найден: на этой системе сеть настраивается её средствами (/etc/network/interfaces)."; exit 1; }
|
||||
IF=$(ip -4 route show default 2>/dev/null | awk '{print $5; exit}')
|
||||
[ -n "$IF" ] || IF=$(ip -o link show | awk -F': ' '$2!="lo"{print $2; exit}')
|
||||
CUR=$(ip -4 -o addr show dev "$IF" scope global 2>/dev/null | awk '{print $4; exit}')
|
||||
GW=$(ip -4 route show default 2>/dev/null | awk '{print $3; exit}')
|
||||
DNS=$(resolvectl dns "$IF" 2>/dev/null | sed 's/.*: *//' | tr ' ' ',' )
|
||||
printf '\n Сеть сервера: интерфейс %s, адрес %s, шлюз %s, DNS %s\n' "$IF" "${CUR:-нет}" "${GW:-нет}" "${DNS:-нет}"
|
||||
printf ' Постоянный адрес нужен, чтобы адрес bj не менялся (DHCP может выдать другой).\n\n'
|
||||
ask() { local v; read -r -p " $1 [$2]: " v; printf '%s' "${v:-$2}"; }
|
||||
ADDR=$(ask "Адрес с маской (например 10.10.10.30/24)" "${CUR:-}")
|
||||
[[ "$ADDR" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}/[0-9]{1,2}$ ]] || { echo " адрес — вида 10.10.10.30/24"; exit 1; }
|
||||
GW2=$(ask "Шлюз" "${GW:-}")
|
||||
[[ "$GW2" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]] || { echo " шлюз — вида 10.10.10.1"; exit 1; }
|
||||
DNS2=$(ask "DNS через запятую" "${DNS:-$GW2}")
|
||||
F=/etc/netplan/60-bj-static.yaml
|
||||
[ -f "$F" ] && cp -a "$F" "$F.bak"
|
||||
{
|
||||
printf 'network:\n version: 2\n ethernets:\n %s:\n dhcp4: false\n addresses: [%s]\n routes:\n - to: default\n via: %s\n nameservers:\n addresses: [%s]\n' "$IF" "$ADDR" "$GW2" "$DNS2"
|
||||
} > "$F"
|
||||
chmod 600 "$F"
|
||||
# прежние файлы с DHCP для этого интерфейса — выключаем, чтобы не было двух адресов
|
||||
for f in /etc/netplan/*.yaml; do [ "$f" = "$F" ] && continue; grep -q "$IF" "$f" 2>/dev/null && mv "$f" "$f.disabled-by-bj"; done
|
||||
echo " Применяю. Если связь пропадёт — через 120 секунд вернутся прежние настройки."
|
||||
if netplan try --timeout 120; then
|
||||
echo " ✓ Адрес ${ADDR%/*} закреплён. Веб-вход: https://${ADDR%/*}:8443/"
|
||||
[ -x /usr/local/sbin/bj-welcome ] && /usr/local/sbin/bj-welcome
|
||||
else
|
||||
for f in /etc/netplan/*.disabled-by-bj; do [ -f "$f" ] && mv "$f" "${f%.disabled-by-bj}"; done
|
||||
rm -f "$F"; netplan apply; echo " Настройки не приняты — оставлен прежний адрес."
|
||||
fi
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# bj-system-admin — системные настройки сервера bj из веб-интерфейса (через root-демон bj-keymedia).
|
||||
# ntp — серверы времени (BJ_EXTRA: "ntp1.example.ru ntp2.example.ru"): ntpd, chrony или systemd-timesyncd —
|
||||
# что стоит на сервере. Время важно для подписей и обмена с НРД.
|
||||
set -uo pipefail
|
||||
q() { python3 -c "import json,sys;print(json.dumps(sys.argv[1],ensure_ascii=False))" "$1"; }
|
||||
ok() { echo "{\"ok\":true,\"output\":$(q "$1")}"; }
|
||||
err() { echo "{\"ok\":false,\"error\":$(q "$1")}"; exit 0; }
|
||||
cmd=${1:-}
|
||||
case "$cmd" in
|
||||
ntp)
|
||||
servers=$(printf '%s' "${BJ_EXTRA:-}" | tr ',;' ' ' | xargs)
|
||||
[ -n "$servers" ] || err "не указан сервер времени"
|
||||
for s in $servers; do [[ "$s" =~ ^[A-Za-z0-9][A-Za-z0-9.-]{0,252}$ ]] || err "недопустимое имя сервера времени: $s"; done
|
||||
if systemctl is-active --quiet ntp || systemctl is-active --quiet ntpd || [ -f /etc/ntp.conf ] && ! systemctl is-active --quiet chrony && ! systemctl is-active --quiet systemd-timesyncd; then
|
||||
conf=/etc/ntp.conf; [ -f "$conf" ] || err "нет /etc/ntp.conf"
|
||||
cp -a "$conf" "$conf.bak-bj" 2>/dev/null
|
||||
python3 - "$conf" $servers <<'PY' || err "не удалось изменить /etc/ntp.conf"
|
||||
import sys,re
|
||||
p,servers=sys.argv[1],sys.argv[2:]
|
||||
out=[]
|
||||
for l in open(p).read().split("\n"):
|
||||
if l.startswith("server ") and l.rstrip().endswith("# bj"): continue # прежние наши
|
||||
if re.match(r"^(server|pool) ",l): l="#bj# "+l # чужие — выключаем
|
||||
out.append(l)
|
||||
out+=[f"server {s} iburst # bj" for s in servers]
|
||||
open(p,"w").write("\n".join(out).rstrip("\n")+"\n")
|
||||
PY
|
||||
svc=ntp; systemctl is-active --quiet ntpd && svc=ntpd
|
||||
systemctl restart "$svc" || err "служба $svc не перезапустилась"
|
||||
ok "серверы времени: $servers (служба $svc)"
|
||||
elif systemctl is-active --quiet chrony || [ -d /etc/chrony ]; then
|
||||
d=/etc/chrony/sources.d; mkdir -p "$d"
|
||||
: > "$d/bj.sources"; for s in $servers; do echo "server $s iburst" >> "$d/bj.sources"; done
|
||||
grep -q '^sourcedir /etc/chrony/sources.d' /etc/chrony/chrony.conf 2>/dev/null || echo 'sourcedir /etc/chrony/sources.d' >> /etc/chrony/chrony.conf
|
||||
systemctl restart chrony || err "служба chrony не перезапустилась"
|
||||
ok "серверы времени: $servers (служба chrony)"
|
||||
else
|
||||
mkdir -p /etc/systemd/timesyncd.conf.d
|
||||
printf '[Time]\nNTP=%s\n' "$servers" > /etc/systemd/timesyncd.conf.d/bj.conf
|
||||
timedatectl set-ntp true >/dev/null 2>&1
|
||||
systemctl restart systemd-timesyncd || err "служба systemd-timesyncd не перезапустилась"
|
||||
ok "серверы времени: $servers (служба systemd-timesyncd)"
|
||||
fi ;;
|
||||
*) err "неизвестная команда: $cmd" ;;
|
||||
esac
|
||||
@@ -10,10 +10,11 @@ SETUP=/var/lib/bj/.bj/setup.json
|
||||
USERS=/var/lib/bj/.bj/users.json
|
||||
FIRSTRUN=/var/lib/bj/.bj/first-run.json
|
||||
PORT=8080
|
||||
TLSPORT=8443 # веб-вход по HTTPS (сертификат сервера — браузер попросит подтвердить исключение)
|
||||
HOST=$(hostname 2>/dev/null || echo bj)
|
||||
ADDRS=$(ip -4 -o addr show scope global 2>/dev/null | awk '{split($4,a,"/"); print a[1]}' | tr '\n' ' ')
|
||||
[ -z "$ADDRS" ] && ADDRS="<адрес не получен: проверьте сеть>"
|
||||
url() { for a in $ADDRS; do case "$a" in \<*) printf ' http://%s:%s%s\n' "<IP сервера>" "$PORT" "$1";; *) printf ' http://%s:%s%s\n' "$a" "$PORT" "$1";; esac; done; }
|
||||
url() { for a in $ADDRS; do case "$a" in \<*) printf ' https://%s:%s%s\n' "<IP сервера>" "$TLSPORT" "$1";; *) printf ' https://%s:%s%s\n' "$a" "$TLSPORT" "$1";; esac; done; }
|
||||
lic=""
|
||||
if [ -r "$SETUP" ]; then
|
||||
lic=$(python3 - "$SETUP" 2>/dev/null <<'PY'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"bj-component-install": {
|
||||
"fingerprint": "24f9297c039f38fa4438103d061dcaad9c7998d8c193a47ed8f38bff0bc6f23b",
|
||||
"version": "2026.09.25.15"
|
||||
"fingerprint": "c6935ab9b97592629f8f997cabfb76fe64b9b41ad043150232753f46c5740774",
|
||||
"version": "2026.10.05.15"
|
||||
},
|
||||
"bj-installer": {
|
||||
"fingerprint": "4be46092947872b652d193edaf58ae40cb7836be36f173e5fcff87d8ff746330",
|
||||
"version": "2026.09.25.24"
|
||||
"fingerprint": "39d6dca9b7789bc7cc585ba30958bfb4625a1d41cea149ec4dcfd998cf901045",
|
||||
"version": "2026.10.05.15"
|
||||
},
|
||||
"bj-lk": {
|
||||
"fingerprint": "37bf4ba7d13bc3cfb52032dfb95851b9d5d702f1a2244e185a1b6a5b87a5cfc6",
|
||||
@@ -20,8 +20,8 @@
|
||||
"version": "2026.09.25.14"
|
||||
},
|
||||
"bj-server": {
|
||||
"fingerprint": "16dfbfc7331a989f6344379136d8900a5ded00eb1dd9fa29af36980b1ed3f3b2",
|
||||
"version": "2026.09.29.2"
|
||||
"fingerprint": "c07806b81189f3963bc74b209159b64ca2358e52f6587f11754d47bf7528cb47",
|
||||
"version": "2026.10.05.15"
|
||||
},
|
||||
"crypto-service.jar": {
|
||||
"fingerprint": "2c4fd536bc9b1c20c69a70e8dcd374a61847b263aeb2e474c45debb01fbd8233",
|
||||
|
||||
Reference in New Issue
Block a user