Добавить скрипты первичной инициализации, очистки и автозапуска (BBox)

This commit is contained in:
NW
2026-08-07 14:58:14 +01:00
parent 79f6c425e5
commit 5606fb0563
5 changed files with 553 additions and 0 deletions

226
init_system.sh Executable file
View File

@@ -0,0 +1,226 @@
#!/bin/bash
# ============================================================================
# init_system.sh — первичная инициализация системы (BBox / OpenDoor base)
# ----------------------------------------------------------------------------
# Выполняется ОДИН раз после развёртывания образа на новом устройстве:
# * обновление пакетов
# * установка базовых утилит (tmux, mc, git, net-tools, curl, wget, btop)
# * установка Docker + Docker Compose
# * настройка hostname и баннера BBox (bbox.wtf)
# * сброс уникальных идентификаторов (machine-id, SSH host keys)
# * установка вспомогательных скриптов и автозапуска
#
# Безопасно повторять: повторный запуск пропускает уже выполненные шаги.
# ============================================================================
set -euo pipefail
# Цвета
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
BBOX_VERSION="1.2"
BBOX_URL="bbox.wtf"
HOSTNAME_DEFAULT="bbox-node"
log() { echo -e "${GREEN}[init]${NC} $*"; }
warn() { echo -e "${YELLOW}[init][warn]${NC} $*"; }
fail() { echo -e "${RED}[init][error]${NC} $*"; exit 1; }
# ---------------------------------------------------------------------------
# 1. Определение дистрибутива и архитектуры
# ---------------------------------------------------------------------------
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO=$ID
VERSION_CODENAME=$VERSION_CODENAME
else
fail "Не удалось определить дистрибутив."
fi
ARCH=$(uname -m)
log "Дистрибутив: $DISTRO ($VERSION_CODENAME), архитектура: $ARCH"
}
check_install() {
if command -v "$1" &> /dev/null; then
log "$1 уже установлен."
else
log "Установка $1..."
if ! apt-get install -y "$1" &> /dev/null; then
fail "Ошибка при установке $1."
fi
log "$1 установлен."
fi
}
# ---------------------------------------------------------------------------
# 2. Обновление системы
# ---------------------------------------------------------------------------
update_system() {
log "Обновление списков пакетов..."
apt-get update || fail "Ошибка apt-get update"
apt-get upgrade -y || warn "apt-get upgrade завершился с предупреждениями"
}
# ---------------------------------------------------------------------------
# 3. Установка базовых утилит
# ---------------------------------------------------------------------------
install_base_utils() {
log "Установка базовых утилит..."
check_install tmux
check_install mc
check_install git
check_install net-tools
check_install curl
check_install wget
check_install build-essential
check_install btop
}
# ---------------------------------------------------------------------------
# 4. Установка Docker
# ---------------------------------------------------------------------------
install_docker() {
if command -v docker &> /dev/null; then
log "Docker уже установлен."
return
fi
log "Установка Docker для $DISTRO..."
apt-get install -y apt-transport-https ca-certificates curl gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL "https://download.docker.com/linux/$DISTRO/gpg" | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$DISTRO $VERSION_CODENAME stable" \
> /etc/apt/sources.list.d/docker.list
apt-get update
if ! apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin; then
warn "Официальный репозиторий не подошёл, пробуем docker.io..."
apt-get install -y docker.io docker-compose-plugin || fail "Не удалось установить Docker."
fi
systemctl enable --now docker
log "Docker установлен: $(docker --version)"
}
# ---------------------------------------------------------------------------
# 5. Настройка hostname
# ---------------------------------------------------------------------------
setup_hostname() {
local NEW_HOSTNAME="${HOSTNAME:-$HOSTNAME_DEFAULT}"
local CUR_HOSTNAME
CUR_HOSTNAME=$(hostname)
if [ "$CUR_HOSTNAME" != "$NEW_HOSTNAME" ]; then
log "Смена hostname: $CUR_HOSTNAME -> $NEW_HOSTNAME"
hostnamectl set-hostname "$NEW_HOSTNAME" || warn "Не удалось сменить hostname"
echo "$NEW_HOSTNAME" > /etc/hostname
else
log "Hostname уже установлен: $CUR_HOSTNAME"
fi
}
# ---------------------------------------------------------------------------
# 6. Баннер BBox (MOTD)
# ---------------------------------------------------------------------------
setup_motd() {
local HEADER="/etc/update-motd.d/10-armbian-header"
if [ -f "$HEADER" ] && ! grep -q "BBox" "$HEADER"; then
log "Обновление баннера входа: BBox v${BBOX_VERSION} ($BBOX_URL)"
cp "$HEADER" "${HEADER}.bak"
# ASCII-баннер
sed -i 's|figlet -f small " $VENDOR"|figlet -f small " BBox"|' "$HEADER"
# Строка версии + подпись
sed -i 's|running Armbian Linux \\e\[0;92m\${KERNELID\^}\\x1B\[0m|running \\e[0;92m${KERNELID^}\\x1B[0m, built on Armbian Linux|' "$HEADER"
# Вставка строки версии/подписи после строки баннера figlet
if ! grep -q "bbox.wtf v" "$HEADER"; then
sed -i "/figlet -f small \" BBox\"/a echo -e \" \\\\e[0;92mv${BBOX_VERSION}\\\\x1B[0m ${BBOX_URL} on \$BOARD_NAME\"\necho -e \" \\\\e[0;36mCreated by free people for a free world, in the name of privacy and security.\\\\x1B[0m\"" "$HEADER"
fi
log "Баннер обновлён."
else
log "Баннер BBox уже установлен или скрипт не найден."
fi
}
# ---------------------------------------------------------------------------
# 7. Сброс уникальных идентификаторов (для клонированных образов)
# ---------------------------------------------------------------------------
reset_unique_ids() {
log "Сброс machine-id..."
rm -f /etc/machine-id /var/lib/dbus/machine-id
systemd-machine-id-setup || warn "Не удалось пересоздать machine-id"
log "Сброс SSH host keys (будут пересозданы при старте sshd)..."
rm -f /etc/ssh/ssh_host_*
systemctl restart ssh || systemctl restart sshd || warn "SSH будет перезапущен при перезагрузке"
}
# ---------------------------------------------------------------------------
# 8. Установка вспомогательных скриптов и автозапуска
# ---------------------------------------------------------------------------
install_helper_scripts() {
local SRC_DIR
SRC_DIR=$(dirname "$(readlink -f "$0")")
if [ -x "$SRC_DIR/install_scripts.sh" ]; then
log "Установка вспомогательных скриптов..."
"$SRC_DIR/install_scripts.sh" || warn "install_scripts.sh завершился с ошибкой"
else
warn "install_scripts.sh не найден рядом ($SRC_DIR), пропуск."
fi
}
# ---------------------------------------------------------------------------
# MAIN
# ---------------------------------------------------------------------------
FIRSTBOOT=0
FIRSTBOOT_MARKER="/var/lib/bbox-firstboot-done"
main() {
if [ "$(id -u)" -ne 0 ]; then
fail "Запустите скрипт от root: sudo ./init_system.sh"
fi
# --firstboot: режим автозапуска (из bbox-firstboot.service)
if [ "${1:-}" = "--firstboot" ]; then
FIRSTBOOT=1
log "Режим firstboot (автозапуск при первой загрузке)"
if [ -f "$FIRSTBOOT_MARKER" ]; then
log "Инициализация уже выполнялась, пропуск."
exit 0
fi
fi
log "=== BBox (bbox.wtf) v${BBOX_VERSION} — первичная инициализация ==="
detect_distro
update_system
install_base_utils
install_docker
setup_hostname
setup_motd
if [ $FIRSTBOOT -eq 1 ]; then
# При автозапуске не трогаем ssh/machine-id до перезагрузки
warn "Режим firstboot: сброс идентификаторов выполняется при следующем запуске"
touch "$FIRSTBOOT_MARKER"
else
reset_unique_ids
fi
install_helper_scripts
log "Инициализация завершена."
if [ $FIRSTBOOT -eq 1 ]; then
log "Сервис автозапуска завершён. Перезагрузка не требуется."
else
echo
echo "Рекомендуется перезагрузить устройство: reboot"
fi
}
main "$@"