#!/bin/bash #=============================================================================== # КОНФИГУРАЦИЯ И ФУНКЦИИ ДЛЯ ПЕРВОНАЧАЛЬНОЙ НАСТРОЙКИ СЕРВЕРА #=============================================================================== # Этот файл подключается ко всем остальным скриптам через source (.) # # Структура файлов: # 00.sh - конфигурация и функции (этот файл) # 01.sh - базовая настройка (hostname, timezone, locale) # 02.sh - настройка сети (netplan) # 03.sh - обновление системы # 04.sh - установка базовых пакетов # 05.sh - создание администратора # 06.sh - настройка SSH # 07.sh - настройка firewall (nftables) # 08.sh - настройка Fail2ban # 09.sh - настройка swap # 99.sh - финальная проверка # all.sh - запуск всех шагов #=============================================================================== #------------------------------------------------------------------------------- # КОНФИГУРАЦИЯ #------------------------------------------------------------------------------- # Параметры сервера (ИЗМЕНИТЕ ПОД ВАШИ НУЖДЫ!) SERVER_HOSTNAME='mygit' SERVER_DOMAIN='git.example.com' ADMIN_USER='admin' SERVER_TIMEZONE='Europe/Minsk' # Сетевые интерфейсы IFACE_EXT='ens192' IFACE_INT='ens160' #------------------------------------------------------------------------------- # НАСТРОЙКА СЕТИ (NETPLAN) #------------------------------------------------------------------------------- # Внешний интерфейс (IFACE_EXT) # Используйте DHCP или статический IP # DHCP для внешнего интерфейса (true/false) NET_EXT_DHCP=false # Статический IP для внешнего интерфейса (если NET_EXT_DHCP=false) NET_EXT_ADDRESS='123.4.5.6/24' # IP-адрес с маской NET_EXT_GATEWAY='123.4.5.250' # Шлюз NET_EXT_DNS='8.8.8.8,8.8.4.4' # DNS-серверы (через запятую) # Внутренний интерфейс (IFACE_INT) # DHCP для внутреннего интерфейса (true/false) NET_INT_DHCP=false # Статический IP для внутреннего интерфейса (если NET_INT_DHCP=false) NET_INT_ADDRESS='10.10.10.30/24' # IP-адрес с маской # NET_INT_GATEWAY='' # Шлюз (обычно не нужен) # NET_INT_DNS='' # DNS (обычно не нужен) # Лог-файл LOG_FILE="/var/log/server-setup.log" # Цвета для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color #------------------------------------------------------------------------------- # БАЗОВЫЕ ФУНКЦИИ #------------------------------------------------------------------------------- # Инициализация логирования init_log() { exec > >(tee -a "$LOG_FILE") 2>&1 echo "" echo "===============================================================================" echo " Лог: $(date '+%Y-%m-%d %H:%M:%S')" echo " Скрипт: $(basename "$0")" echo "===============================================================================" } # Заголовок секции print_header() { echo -e "\n${BLUE}================================================================${NC}" echo -e "${BLUE} $1${NC}" echo -e "${BLUE}================================================================${NC}\n" } # Подзаголовок print_subheader() { echo -e "\n${CYAN}--- $1 ---${NC}\n" } # Успешное выполнение print_success() { echo -e "${GREEN}[OK]${NC} $1" } # Предупреждение print_warning() { echo -e "${YELLOW}[WARN]${NC} $1" } # Ошибка print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Информация print_info() { echo -e "${CYAN}[INFO]${NC} $1" } #------------------------------------------------------------------------------- # ФУНКЦИИ ПРОВЕРКИ #------------------------------------------------------------------------------- # Проверка прав root check_root() { if [[ $EUID -ne 0 ]]; then print_error "Скрипт должен запускаться от root (sudo)" exit 1 fi } # Проверка ОС check_os() { if [[ ! -f /etc/os-release ]]; then print_error "Не удалось определить ОС" exit 1 fi if ! grep -q "Ubuntu 24" /etc/os-release; then print_warning "Этот скрипт тестировался на Ubuntu 24.04" else print_success "Ubuntu 24.04 подтверждена" fi } # Проверка сетевых интерфейсов check_network_interfaces() { print_info "Сетевые интерфейсы:" ip -br addr show echo "" # Проверка внешнего интерфейса if ip link show "$IFACE_EXT" &>/dev/null; then print_success "Внешний интерфейс $IFACE_EXT найден" else print_error "Внешний интерфейс $IFACE_EXT не найден" print_info "Доступные интерфейсы:" ip link show | grep -E "^[0-9]:" | awk '{print " " $2}' | tr -d ':' return 1 fi # Проверка внутреннего интерфейса if ip link show "$IFACE_INT" &>/dev/null; then print_success "Внутренний интерфейс $IFACE_INT найден" else print_warning "Внутренний интерфейс $IFACE_INT не найден" fi return 0 } # Проверка установленного пакета is_installed() { dpkg -l "$1" 2>/dev/null | grep -q "^ii" } # Проверка существования пользователя user_exists() { id "$1" &>/dev/null } # Проверка запущенного сервиса service_running() { systemctl is-active --quiet "$1" } # Проверка существования файла/директории path_exists() { [[ -e "$1" ]] } # Проверка swap has_swap() { swapon --show | grep -q . } #------------------------------------------------------------------------------- # ФУНКЦИИ УСТАНОВКИ #------------------------------------------------------------------------------- # Установка пакетов с проверкой install_packages() { local packages=("$@") local to_install=() for pkg in "${packages[@]}"; do if ! is_installed "$pkg"; then to_install+=("$pkg") fi done if [[ ${#to_install[@]} -eq 0 ]]; then print_success "Все пакеты уже установлены" return 0 fi print_info "Установка пакетов: ${to_install[*]}" apt install -y "${to_install[@]}" print_success "Пакеты установлены" } # Создание директории с правами create_dir() { local path="$1" local owner="${2:-root:root}" local mode="${3:-755}" if [[ ! -d "$path" ]]; then mkdir -p "$path" print_success "Создана директория: $path" else print_info "Директория существует: $path" fi chown "$owner" "$path" chmod "$mode" "$path" } #------------------------------------------------------------------------------- # ФУНКЦИИ ПОЛЬЗОВАТЕЛЬСКОГО ВВОДА #------------------------------------------------------------------------------- # Запрос подтверждения confirm() { local prompt="${1:-Продолжить?}" local default="${2:-N}" local response read -p "$prompt [$default]: " response response=${response:-$default} [[ "$response" =~ ^[Yy]$ ]] } # Запрос ввода с значением по умолчанию prompt_input() { local prompt="$1" local default="$2" local var_name="$3" local response read -p "$prompt [$default]: " response response=${response:-$default} eval "$var_name='$response'" } #------------------------------------------------------------------------------- # ФУНКЦИИ КОНФИГУРАЦИИ #------------------------------------------------------------------------------- # Установка hostname set_hostname() { local hostname="$1" local domain="$2" hostnamectl set-hostname "$hostname" # Добавить в /etc/hosts если нет if ! grep -q "$hostname" /etc/hosts; then echo "127.0.1.1 $hostname.$domain $hostname" >> /etc/hosts fi print_success "Hostname установлен: $hostname" } # Установка timezone set_timezone() { local timezone="$1" timedatectl set-timezone "$timezone" print_success "Timezone установлен: $timezone" } # Установка локали set_locale() { local locale="${1:-en_US.UTF-8}" localectl set-locale LANG="$locale" locale-gen "$locale" 2>/dev/null || true print_success "Локаль установлена: $locale" } #------------------------------------------------------------------------------- # ФУНКЦИИ SSH #------------------------------------------------------------------------------- # Создание SSH-директории для пользователя setup_ssh_dir() { local user="$1" local home_dir home_dir=$(getent passwd "$user" | cut -d: -f6) mkdir -p "$home_dir/.ssh" chmod 700 "$home_dir/.ssh" touch "$home_dir/.ssh/authorized_keys" chmod 600 "$home_dir/.ssh/authorized_keys" chown -R "$user:$user" "$home_dir/.ssh" print_success "SSH-директория создана: $home_dir/.ssh" } # Генерация пароля generate_password() { openssl rand -base64 12 } #------------------------------------------------------------------------------- # ФУНКЦИИ FIREWALL #------------------------------------------------------------------------------- # Проверка nftables check_nftables() { if command -v nft &>/dev/null; then print_success "nftables установлен" return 0 else print_warning "nftables не установлен" return 1 fi } # Показать текущие правила nftables show_nftables_rules() { if nft list ruleset &>/dev/null; then nft list ruleset else print_info "Нет активных правил nftables" fi } #------------------------------------------------------------------------------- # ИНИЦИАЛИЗАЦИЯ ПРИ ПОДКЛЮЧЕНИИ #------------------------------------------------------------------------------- # Показать текущую конфигурацию show_config() { echo "" echo -e "${CYAN}Текущая конфигурация:${NC}" echo " Hostname: $SERVER_HOSTNAME" echo " Domain: $SERVER_DOMAIN" echo " Admin user: $ADMIN_USER" echo " Timezone: $SERVER_TIMEZONE" echo "" echo -e "${CYAN}Сетевые интерфейсы:${NC}" echo " IFACE_EXT: $IFACE_EXT ($( [[ "$NET_EXT_DHCP" == "true" ]] && echo "DHCP" || echo "$NET_EXT_ADDRESS"))" echo " IFACE_INT: $IFACE_INT ($( [[ "$NET_INT_DHCP" == "true" ]] && echo "DHCP" || echo "$NET_INT_ADDRESS"))" echo "" }