Skip to main content

Подготовить ISO-образ для автоустановки ОС на выделенный сервер

Вы можете подготовить собственный образ ОС, который будет совместим с механизмом автоустановки ОС на выделенный сервер в Servercore.

Если у вас нет особых требований к ОС, мы рекомендуем использовать стандартные образы — из них можно установить ОС автоустановкой или вручную.

  1. Создайте ISO-образ.
  2. Загрузите образ в хранилище S3.
  3. Получите ссылку на объект в хранилище.
  4. Добавьте ISO-образ в панель управления.

1. Создать ISO-образ

Размер архива с образом ОС должен быть минимум на 3 ГБ меньше размера оперативной памяти выделенного сервера. Например, если размер оперативной памяти сервера 8 ГБ, размер архива с образом не должен превышать 5 ГБ.

Рекомендуем выполнять подготовку системы от пользователя root.

  1. Для подготовки архива с образом установите ОС без программного RAID и без раздела swap. Рекомендуем установить ОС автоустановкой на ваш выделенный сервер, тогда некоторые шаги инструкции будут уже выполнены.

  2. Проверьте состояние пакета sssd и удалите его, если он установлен:

    2.1. Проверьте состояние пакета sssd:

    dpkg -l sssd

    Если пакет установлен, в ответе появится строка со статусом ii, например ii sssd 2.9.1-....

    2.2. Если пакет sssd установлен, удалите его:

    sudo apt purge -y sssd
    sudo apt autoremove -y
  3. Установите обязательные пакеты:

    sudo apt install -y \
    openssh-server \
    cloud-init \
    grub2 \
    grub-efi-amd64-bin \
    mdadm \
    nftables
  4. Обновите ядро ОС до последней стабильной версии:

    linux-image-generic-hwe-24.04
    linux-headers-generic-hwe-24.04
  5. Обновите пакеты в системе:

    apt update && apt upgrade -y
  6. Подготовьте сервис cloud-init к использованию в образе:

    6.1. Удалите файлы и директории, которые содержат текущую конфигурацию cloud-init:

    rm -rf /etc/cloud/cloud.cfg.d /etc/cloud/cloud-init.disabled

    6.2. Удалите данные с прошлого выполнения cloud-init:

    cloud-init clean --logs

    6.3. Создайте директорию /etc/cloud/cloud.cfg.d:

    mkdir -p /etc/cloud/cloud.cfg.d

    6.4. Создайте файл /etc/cloud/cloud.cfg текстовым редактором vi:

    vi /etc/cloud/cloud.cfg

    6.5. Добавьте в файл конфигурацию cloud-init:

    Файл /etc/cloud/cloud.cfg
    datasource_list:
    - NoCloud
    - None

    users:
    - default

    #disable_root: 1
    #ssh_pwauth: 0

    mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2']
    resize_rootfs_tmp: /dev
    ssh_deletekeys: 1
    ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519']
    syslog_fix_perms: ~
    disable_vmware_customization: false

    cloud_init_modules:
    - disk_setup
    - growpart
    - resizefs
    - set_hostname
    - update_hostname
    - update_etc_hosts
    - users-groups
    - ssh
    - apt-configure
    - bootcmd
    - ca_certs
    - rsyslog
    - write_files

    cloud_config_modules:
    - mounts
    - locale
    - set-passwords
    - timezone
    - runcmd
    - snap
    - ssh_import_id
    - ubuntu_drivers
    - ntp

    cloud_final_modules:
    - package-update-upgrade-install
    - scripts-per-once
    - scripts-per-boot
    - scripts-per-instance
    - scripts-user
    - ssh-authkey-fingerprints
    - keys-to-console
    - final-message
    - power-state-change
    - lxd
    - puppet
    - chef
    - mcollective
    - salt_minion
    - phone_home

    system_info:
    default_user:
    name: cloud-user
    lock_passwd: true
    gecos: Cloud User
    groups: [adm, systemd-journal]
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    shell: /bin/bash
    distro: ubuntu
    paths:
    cloud_dir: /var/lib/cloud
    templates_dir: /etc/cloud/templates
    ssh_svcname: sshd

    vendor_data:
    enabled: True

    # vim:syntax=yaml

    6.6. Выйдите из текстового редактора vi с сохранением изменений:

    :wq

    6.7. Создайте файл cloud-init-local.service текстовым редактором vi:

    sudo vi /usr/lib/systemd/system/cloud-init-local.service

    6.8. Добавьте в файл конфигурацию:

    [Unit]
    Description=Initial cloud-init job (pre-networking)
    DefaultDependencies=no
    Wants=network-pre.target
    After=hv_kvp_daemon.service
    After=systemd-remount-fs.service
    Before=NetworkManager.service
    Before=network-pre.target
    Before=shutdown.target
    Before=sysinit.target
    Conflicts=shutdown.target
    RequiresMountsFor=/var/lib/cloud
    ConditionPathExists=!/etc/cloud/cloud-init.disabled
    ConditionKernelCommandLine=!cloud-init=disabled
    ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled

    [Service]
    Type=oneshot
    ExecStartPre=sleep 30
    ExecStart=/usr/bin/cloud-init init --local
    RemainAfterExit=yes
    TimeoutSec=0

    # Output needs to appear in instance console output
    StandardOutput=journal+console

    [Install]
    WantedBy=cloud-init.target

    6.9. Выйдите из текстового редактора vi с сохранением изменений:

    :wq
  7. Добавьте и настройте скрипт per-boot:

    7.1. Создайте файл скрипта boot_order_sort.sh текстовым редактором vi:

    sudo vi /var/lib/cloud/scripts/per-boot/boot_order_sort.sh

    7.2. Добавьте в файл текст скрипта:

    Файл boot_order_sort.sh
    #!/bin/bash

    # Retrieve the output of efibootmgr
    efi_output=$(efibootmgr -D 2>&1)

    # Check if the system supports EFI
    if [[ $? -ne 0 ]]; then
    echo "[WARNING] System does not support EFI, boot order will not be changed."
    exit 0
    fi

    # Extract the current boot entry (BootCurrent)
    current_os=$(echo "$efi_output" | grep -oP '(?<=BootCurrent: )[0-9A-F]{4}')
    # Extract the boot order (BootOrder)
    boot_order=$(echo "$efi_output" | grep -oP '(?<=BootOrder: )[0-9A-F,]+')

    # Declare an associative array to store BootXXXX values and their descriptions
    declare -A boot_dict
    # boot_order_sorted will contain the sorted boot order
    # removed_entries will contain boot numbers that are not in the sorted list (and are removed)
    boot_order_sorted=()
    removed_entries=()

    # Parse all BootXXXX entries with their descriptions (remove 'Boot' prefix and *)
    boot_entries=$(echo "$efi_output" | grep -oP '(?<=Boot)[0-9A-F]{4}\*?.*')

    if [[ -z "$boot_entries" ]]; then
    echo "[ERROR] No boot entries found in EFI output."
    exit 1
    fi

    # Debug output
    echo "[INFO] Current Boot: ${current_os:-None}"
    echo "[INFO] Boot Order: ${boot_order:-None}"

    # Loop through and process each boot entry
    while read -r entry; do
    # Extract the four-digit boot number (excluding 'Boot' and '*')
    boot_number=$(echo "$entry" | grep -oP '^[0-9A-F]{4}')
    # Extract the description (everything after the boot number)
    description=$(echo "$entry" | sed 's/^[0-9A-F]\{4\}\* //')
    # Ensure the boot_number is not empty and add to the dictionary
    if [[ -n "$boot_number" ]]; then
    boot_dict["$boot_number"]="$description"
    fi
    # Add entries containing "IP4" or "PXE", but not containing "HTTP", to the sorted list
    if [[ ("$description" =~ "IP4" || "$description" =~ "PXE" || "$description" =~ "IPv4" || "$description" =~ "NIC") && ! "$description" =~ "HTTP" ]]; then
    boot_order_sorted+=("$boot_number")
    fi
    echo "$boot_number: $description"
    done <<< "$boot_entries"

    # Add the current OS to the main list if it exists
    if [[ -n "$current_os" ]]; then
    boot_order_sorted+=("$current_os")
    fi

    # Find all entries with the same description as current_os and add them to the sorted list
    if [[ -n "$current_os" ]]; then
    current_description="${boot_dict[$current_os]}"
    for boot_number in "${!boot_dict[@]}"; do
    # If description matches the current OS but boot number is not the same, add it to the sorted list
    if [[ "$boot_number" != "$current_os" && "${boot_dict[$boot_number]}" == "$current_description" ]]; then
    boot_order_sorted+=("$boot_number")
    fi
    done
    fi

    # Find all boot numbers that are not in the main sorted list and remove them
    if [[ ${#boot_dict[@]} -eq 0 ]]; then
    echo "[INFO] No boot entries to process."
    else
    for boot_number in "${!boot_dict[@]}"; do
    if [[ ! " ${boot_order_sorted[*]} " =~ " $boot_number " ]]; then
    # Remove the boot entry from the system
    efibootmgr -b "$boot_number" -B > /dev/null 2>&1
    removed_entries+=("$boot_number") # Add removed boot number to the removed entries list
    echo "[INFO] Removed Boot Entry: $boot_number"
    fi
    done
    fi

    # Convert the main boot order list to a comma-separated string
    if [[ ${#boot_order_sorted[@]} -eq 0 ]]; then
    boot_order_sorted_str="None"
    else
    boot_order_sorted_str=$(IFS=,; echo "${boot_order_sorted[*]}")
    efibootmgr -o "$boot_order_sorted_str" > /dev/null 2>&1
    echo "[INFO] Updated boot order: $boot_order_sorted_str"
    fi

    # Show the final EFI boot entries for verification
    efibootmgr -D

    7.3. Выйдите из текстового редактора vi с сохранением изменений:

    :wq

    7.4. Установите права на файл boot_order_sort.sh:

    sudo chmod 700 /var/lib/cloud/scripts/per-boot/boot_order_sort.sh
  8. Опционально: настройте SSH. По умолчанию при установке ОС сервис cloud-init задает пароль только для пользователя root. Вы можете использовать собственную схему аутентификации, например запретить вход по паролю и под пользователем root, создав отдельного пользователя с авторизацией по SSH-ключу. В этом случае пароль root, переданный при установке, будет установлен, но использоваться не будет.

    8.1. Откройте файл конфигурации /etc/ssh/sshd_config текстовым редактором vi:

    sudo vi /etc/ssh/sshd_config

    8.2. Если хотите разрешить вход по SSH от имени пользователя root, измените или добавьте параметр PermitRootLogin yes.

    8.3. Если хотите разрешить аутентификацию по паролю, измените или добавьте параметр PasswordAuthentication yes.

    8.4. Выйдите из текстового редактора vi с сохранением изменений:

    :wq
  9. Опционально: настройте grub:

    9.1. Откройте файл конфигурации /etc/default/grub текстовым редактором vi:

    sudo vi /etc/default/grub

    9.2. Измените или добавьте параметры:

    GRUB_DEFAULT=0
    GRUB_TIMEOUT=5
    GRUB_DISTRIBUTOR=Ubuntu
    GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet nomodeset"
    GRUB_CMDLINE_LINUX="rd.auto=1 net.ifnames=0 biosdevname=0"
    GRUB_PRELOAD_MODULES="part_gpt part_msdos"
    GRUB_TIMEOUT_STYLE=menu
    GRUB_TERMINAL_INPUT=console
    GRUB_GFXMODE=auto
    GRUB_GFXPAYLOAD_LINUX=keep
    GRUB_DISABLE_RECOVERY=true
    GRUB_DISABLE_OS_PROBER=false

    9.3. Выйдите из текстового редактора vi с сохранением изменений:

    :wq
  10. Опционально: установите и настройте Fail2ban — сервис блокировки IP-адреса в случае неудачных попыток авторизации:

    10.1. Установите Fail2ban:

    fail2ban

    10.2. Откройте файл конфигурации /etc/fail2ban/jail.d/service.conf текстовым редактором vi:

    sudo vi /etc/fail2ban/jail.d/service.conf

    10.3. Измените или добавьте параметры:

    [sshd]
    enabled = true
    port = ssh
    filter = sshd
    action = nftables[name=sshd, port=ssh, protocol=tcp]
    logpath = /var/log/auth.log
    maxretry = 10
    findtime = 3600
    bantime = 86400

    10.4. Выйдите из текстового редактора vi с сохранением изменений:

    :wq
  11. Опционально: внесите дополнительные изменения в систему, например установите дополнительное ПО, пакеты или выполните другие необходимые настройки для вашего образа. Убедитесь, что внесенные изменения не противоречат предыдущим шагам инструкции.

  12. Отключите режим сна и гибернации:

    systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
  13. Создайте символьную ссылку для mdamd:

    ln -s /usr/sbin/mdadm /usr/bin/mdadm
  14. Включите службу system-resolved:

    systemctl enable --now systemd-resolved
    ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
  15. Удалите неиспользуемые пакеты:

    apt autoremove -y
  16. Примените изменения, для этого перезагрузите систему:

    systemctl reboot
  17. Обнулите уникальный идентификатор системы, чтобы каждый экземпляр установленной системы получал собственный идентификатор:

    truncate -s 0 /etc/machine-id /var/lib/dbus/machine-id
  18. Подготовьте файл со списком каталогов, которые не должны попасть в архив образа ОС:

    18.1. Создайте файл exclude.txt текстовым редактором vi:

    sudo vi /root/exclude.txt

    18.2. Добавьте в файл exclude.txt список каталогов, которые нужно исключить из архива:

    /tmp/*
    /proc/*
    /sys/*
    /dev/*
    /run/*
    /mnt/*
    /media/*
    /var/lib/lxcfs
    /var/spool/postfix
    /lost+found

    18.3. Выйдите из текстового редактора vi с сохранением изменений:

    :wq
  19. Создайте архив файловой системы:

    tar -czp -f /mnt/base.tar.gz --exclude-from=/root/exclude.txt /

2. Загрузить образ в хранилище S3

Для загрузки архива с образом в хранилище S3 используйте инструкцию Загрузить объект.

Если при создании ISO-образа VMware ESXi вы подготовили файл setul.tpl, загрузите его в хранилище вместе с образом.

Для получения ссылки на объект в хранилище S3 используйте инструкцию Получить ссылку на объект.

4. Добавить образ в панель управления

  1. В панели управления в верхнем меню нажмите Продукты и выберите Выделенные серверы.

  2. Перейдите в раздел Образы.

  3. Нажмите Добавить образ.

  4. Выберите семейство ОС.

  5. Введите имя образа.

  6. Добавьте ссылку на образ, который вы загрузили на этапе 2 в хранилище S3.

  7. Если на шаге 6 в качестве ссылки вы добавили путь к образу в S3, введите Access key и Secret key.

  8. Нажмите Создать образ.