понедельник, 22 сентября 2025 г.

Debian: Настройка полного зеркала репозитория Debian

Создание полного зеркала репозитория Debian - задача, которая требует значительных ресурсов и надежного интернет-соединения. Полное зеркало включает в себя все пакеты, обновления, обратные порты (backports) и обновления безопасности для конкретного выпуска Debian.
Debmirror - это специализированная утилита на Perl, предназначенная для создания и поддержания зеркал репозиториев Debian и Ubuntu. В отличие от стандартных методов "rsync", она предлагает более простой и надежный способ синхронизации, особенно для выборочного зеркалирования.

Далее приведем шаги для настройки зеркала репозитория Debian 13 ("trixie") используя "Debmirror":

1. Установка Debmirror и веб-сервера Apache2:
sudo apt-get update
sudo apt-get install debmirror apache2 -y


Базовый синтаксис команды debmirror следующий:

debmirror [ОПЦИИ] /путь/к/локальному/зеркалу

Ключевые параметры debmirror:
-a, --arch : Архитектуры (например, amd64,i386);
-s, --section : Разделы репозитория (main, contrib, non-free для Debian; main, restricted, universe, multiverse для Ubuntu);
-d, --dist : Дистрибутивы (кодовые имена, например, bullseye, bookworm, trixie для Debian; focal, jammy для Ubuntu). Можно указать несколько через запятую, включая обновления (bullseye-updates, bullseye-security);
-h, --host : URL-адрес исходного зеркала (например, ftp.debian.org, archive.ubuntu.com или локальный Nexus-репозиторий);
-r, --root : Корневой путь на удаленном сервере (например, /debian для Debian, /ubuntu для Ubuntu);
-e, --method : Протокол для загрузки (http, https, ftp, rsync). http или https часто наиболее надежны.
--progress : Показывать прогресс загрузки.
--nosource : Не загружать исходные коды пакетов (значительно экономит место).
--ignore-release-gpg : Игнорировать проверку GPG-подписи Release-файлов. Используйте с осторожностью, так как это снижает безопасность.
--ignore-missing-release : Продолжать синхронизацию, даже если на сервере отсутствует Release-файл.


2. Пробная синхронизация:

Создаем место хранения репозитория на диске:
sudo mkdir -p /srv/mirror/debian
sudo mkdir -p /srv/mirror/debian-security
sudo chown -R nobody:nogroup /srv/mirror/debian
sudo chown -R nobody:nogroup /srv/mirror/debian-security



Затем выполняем команды синхронизации в качестве проверки:

Синхронизация основного репозитория Debian (trixie,trixie-updates,trixie-backports):
debmirror \
-a amd64 \
--nosource \
-s main,contrib,non-free,non-free-firmware \
-d trixie,trixie-updates,trixie-backports \
-h ftp.debian.org \
-r /debian \
-e https \
--progress \
--ignore-release-gpg \
--no-check-gpg \
--rsync-extra=none \
/srv/mirror/debian


Синхронизация патчей безопасности Debian (trixie-security):
debmirror \
-a amd64 \
--nosource \
-s main,contrib,non-free,non-free-firmware \
-d trixie-security \
-h security.debian.org \
-r /debian-security \
-e https \
--progress \
--ignore-release-gpg \
--no-check-gpg \
--rsync-extra=none \
/srv/mirror/debian-security


Если все прошло без ошибок, можно приступить к следующему шагу.


3. Настройка веб-сервера (Apache2) для доступа к локальному репозиторию:

Чтобы сделать зеркало доступным по HTTP создайте файл:
sudo nano /etc/apache2/sites-available/debian-mirror.conf

со следующим содержимым:

<VirtualHost *:80>
    ServerName your-mirror-domain.com #Замените на имя вашего сервера или IP
    DocumentRoot /srv/mirror
    <Directory "/srv/mirror">
        Options +Indexes +FollowSymLinks
        IndexOptions NameWidth=* +SuppressDescription FancyIndexing
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/debian-mirror_error.log
    CustomLog ${APACHE_LOG_DIR}/debian-mirror_access.log combined
</VirtualHost>


Если необходимо добавить поддержку HTTPs:

Создайте директории для пары ключей (если они не существуют):
sudo mkdir -p /etc/ssl/private /etc/ssl/certs

Затем сгенерируйте сертификат:
sudo openssl req -x509 -nodes -days 730 -newkey rsa:2048 \ -keyout /etc/ssl/private/your-mirror.key \ -out /etc/ssl/certs/your-mirror.crt

При генерации укажите в Common Name: your-mirror-domain.com. Остальные поля можно заполнить по желанию или оставить пустыми.

Установите правильные права доступа для ключа:
sudo chmod 600 /etc/ssl/private/your-mirror.key

И создайте файл:
sudo nano /etc/apache2/sites-available/debian-mirror-ssl.conf

со следующим содержимым:

<VirtualHost *:443>
    ServerName your-mirror-domain.com #Замените на имя вашего сервера или IP
    DocumentRoot /srv/mirror
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-mirror.crt
    SSLCertificateKeyFile /etc/ssl/private/your-mirror.key
    <Directory "/srv/mirror">
        Options +Indexes +FollowSymLinks
        IndexOptions NameWidth=* +SuppressDescription FancyIndexing
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/debian-mirror_ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/debian-mirror_ssl_access.log combined
</VirtualHost>


Активируйте конфигурацию и перезапустите Apache:
sudo a2ensite debian-mirror
sudo a2ensite debian-mirror-ssl
#Для поддержки HTTPs
sudo apachectl configtest
sudo a2enmod rewrite
sudo a2enmod ssl
#Для поддержки HTTPs
sudo systemctl restart apache2


Проверьте доступность: Откройте в браузере "http://your-server-ip/debian". Должна отобразиться структура каталогов репозитория.


4. Создание скрипта для автоматизации процесса и мониторинга:

Следующий скрипт умеет помимо выполнения синхронизации нужных веток репозитория командой "debmirror" также записывать лог, отслеживать запущен ли был скрипт ранее и отправлять отчёт на email. Создайте файл:
sudo nano /usr/local/bin/update-mirror.sh

Добавьте в него текст скрипта и сделайте исполняемым:
sudo chmod +x /usr/local/bin/update-mirror.sh

#!/bin/bash

# Настройки скрипта
LOG_FILE="/var/log/mirror_update.log"
LOCK_FILE="/var/run/mirror_update.lock"
MIRROR_BASE="/srv/mirror"

# Email-уведомления
EMAIL_RECIPIENTS="admin@example.com,devops@example.com"  # Замените на реальные адреса
EMAIL_SUBJECT_PREFIX="[Mirror Update] "
SMTP_SERVER="Input_IP_of_SMTP_Server"  # Адрес SMTP-сервера
FROM_EMAIL="mirror-update@$(hostname)"  # Адрес отправителя

# Конфигурация зеркал
declare -A MIRRORS=(
    ["main"]="
        -a amd64
        --nosource
        -s main,contrib,non-free,non-free-firmware
        -d trixie,trixie-updates,trixie-backports
        -h ftp.by.debian.org
        -r /debian
        -e rsync
        --progress
        --ignore-release-gpg
        --no-check-gpg
        ${MIRROR_BASE}/debian
    "
    ["security"]="
        -a amd64
        --nosource
        -s main,contrib,non-free,non-free-firmware
        -d trixie-security
        -h ftp.by.debian.org
        -r /debian-security
        -e rsync
        --progress
        --ignore-release-gpg
        --no-check-gpg
        ${MIRROR_BASE}/debian-security
    "
)

# Функция логирования
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" >> "$LOG_FILE"
}

# Функция отправки email через curl и SMTP
send_email() {
    local subject="$1"
    local body="$2"

    # Проверяем, установлен ли curl
    if command -v curl &> /dev/null; then
        # Формируем email в формате MIME
        local email_content=$(cat <<EOF
From: ${FROM_EMAIL}
To: ${EMAIL_RECIPIENTS}
Subject: ${EMAIL_SUBJECT_PREFIX}${subject}
Date: $(date -R)
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

${body}
EOF
)

        # Отправляем через SMTP используя curl
        echo "$email_content" | curl -s --url "smtp://${SMTP_SERVER}" \
            --mail-from "${FROM_EMAIL}" \
            --mail-rcpt "${EMAIL_RECIPIENTS}" \
            --upload-file - \
            --insecure

        if [ $? -eq 0 ]; then
            log "Email sent successfully: ${subject}"
        else
            log "ERROR: Failed to send email: ${subject}"
        fi
    elif command -v sendmail &> /dev/null; then
        # Альтернативный метод через sendmail
        (
            echo "Subject: ${EMAIL_SUBJECT_PREFIX}${subject}"
            echo "From: ${FROM_EMAIL}"
            echo "To: ${EMAIL_RECIPIENTS}"
            echo
            echo "${body}"
        ) | sendmail -t
    else
        log "ERROR: No email client found. Cannot send notification: $subject"
    fi
}

# Функция проверки блокировки
check_lock() {
    if [ -e "$LOCK_FILE" ]; then
        local pid=$(cat "$LOCK_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            log "ERROR: Скрипт уже запущен с PID $pid"
            send_email "Script already running" "Mirror update script is already running with PID $pid. Current execution blocked."
            exit 1
        else
            log "WARNING: Обнаружен lock файл, но процесс не существует. Удаляю lock файл."
            rm -f "$LOCK_FILE"
        fi
    fi
}

# Функция создания блокировки
create_lock() {
    echo $$ > "$LOCK_FILE"
}

# Функция удаления блокировки
remove_lock() {
    rm -f "$LOCK_FILE"
}

# Функция выполнения debmirror
run_mirror() {
    local name="$1"
    local options="$2"

    log "Starting mirror update: $name"
    log "Command: debmirror $options"

    # Выполнение команды
    debmirror $options

    local exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log "Update successful: $name"
        return 0
    else
        log "Update failed with exit code $exit_code: $name"
        return $exit_code
    fi
}

# Основная логика
main() {
    log "=== Starting mirror update process ==="

    # Проверяем блокировку
    check_lock

    # Создаем блокировку
    create_lock

    # Добавляем обработчик для очистки при выходе
    trap 'remove_lock; log "Script interrupted"; exit 1' INT TERM
    trap 'remove_lock' EXIT

    local overall_success=true

    for mirror_name in "${!MIRRORS[@]}"; do
        if ! run_mirror "$mirror_name" "${MIRRORS[$mirror_name]}"; then
            overall_success=false
            log "ERROR: Mirror $mirror_name failed with exit code $?"
            send_email "Update failed: $mirror_name" "Mirror update for $mirror_name failed. Check $LOG_FILE for details."
        fi
    done

    if [ "$overall_success" = true ]; then
        log "=== All mirror updates completed successfully ==="
        send_email "All updates completed" "All mirror updates completed successfully. Check $LOG_FILE for details."
    else
        log "=== Some mirror updates failed ==="
        # Уведомление об ошибках уже отправлялись для каждого конкретного сбоя
    fi
}

# Обработка ошибок
set -euo pipefail

# Запуск основной функции
main "$@"


5. Настройка ротации логов:

Создайте файл /etc/logrotate.d/update_mirror с следующим содержимым:

/var/log/mirror_update.log {
weekly
missingok
rotate 26
compress
delaycompress
notifempty
create 644 root root
dateext
dateformat -%Y-%m-%d
}


Объяснение директив:
weekly - ротация происходит раз в неделю;
missingok - пропустить ротацию, если файл отсутствует;
rotate 26 - хранить 26 архивных копий (полгода ≈ 26 недель);
compress - сжимать архивные логи с помощью gzip;
delaycompress - отложить сжатие до следующей ротации (удобно для отладки);
notifempty - не ротировать пустые файлы;
create 644 root root - создать новый лог-файл с правами 644 и владельцем root:root после ротации;
dateext - добавлять дату к имени архивного файла;
dateformat -%Y-%m-%d - формат даты в имени файла (ГГГГ-ММ-ДД).

Проверка конфигурации:
sudo logrotate -d /etc/logrotate.d/update_mirror
Ключ -d включает режим отладки, который покажет потенциальные проблемы без выполнения ротации.

Принудительная ротация для тестирования:
sudo logrotate -vf /etc/logrotate.d/update_mirror
Ключ -v включает подробный вывод, а -f принудительно запускает ротацию.


6. Настройка автоматической синхронизации через cron

Для поддержания зеркала в актуальном состоянии его необходимо регулярно синхронизировать. Рекомендуется делать это не реже 4 раз в сутки.
Создайте задание cron (sudo crontab -e):
Синхронизация каждые 6 часов (в произвольные минуты для равномерной нагрузки):
0 */6 * * * /usr/local/bin/update-mirror.sh

или синхронизация каждые сутки в 2 часа ночи:
0 2 * * * /usr/local/bin/update-mirror.sh

Не синхронизируйте зеркало точно в 3:00, 9:00, 15:00 и 21:00 UTC, так как в это время обновляются главные зеркала. Добавьте случайное смещение в несколько минут.


7. Тестирование и использование зеркала:

Протестируйте свое зеркало, настроив на другой машине sources.list:
sudo nano /etc/apt/sources.list

Добавьте строки:
deb http://your-mirror-ip-or-domain/debian/ trixie main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian/ trixie-updates main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian/ trixie-backports main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian-security/ trixie-security main contrib non-free non-free-firmware


Выполните обновление индексов пакетов:
sudo apt update
sudo apt upgrade


Комментариев нет:

Отправить комментарий