MAATRIX / Блог / Прокси-кэш для apt и yum: страховка от недоступности и экономия трафика

Прокси-кэш для apt и yum: страховка от недоступности и экономия трафика

MAATRIX

Репозитории apt и yum пока открываются — но «пока» тут ключевое слово: за последние пару лет каждый, кто держит инфраструктуру в России, хоть раз ловил момент, когда apt update на десятке серверов одновременно упирался в таймаут. Прокси-кэш для пакетных менеджеров — это не панацея и не замена полноценному зеркалу, а простой промежуточный шаг: один сервер в вашей сети запоминает то, что уже скачивали, и отдаёт это остальным машинам напрямую, без похода наружу. Ниже — зачем это нужно даже при полностью рабочих репозиториях, и как поднять такой узел за вечер, а не за неделю.

Зачем прокси-кэш, если репозитории и так работают

Соблазн отложить эту задачу понятен: если apt-get update сегодня отрабатывает без ошибок, кажется, что проблемы нет. Но у прокси-кэша есть три причины существовать независимо от текущей доступности апстрима.

Первая — трафик. Если у вас десять, двадцать, пятьдесят серверов на одной ОС, каждый из них при обновлении тянет одни и те же пакеты заново. Ядро, systemd, openssl, библиотеки — это мегабайты, которые физически идентичны на всех машинах, но скачиваются N раз с внешнего канала. С кэширующим узлом внутри сети первый сервер качает пакет из интернета один раз, все последующие получают его из локального кэша на скорости внутренней сети — обычно это на порядок быстрее и не расходует внешний трафик вообще.

Вторая — устойчивость. Зеркала apt/yum не падают часто, но и не гарантируют аптайм 100%: техработы у мейнтейнеров, сетевые проблемы на маршруте, временная перегрузка конкретного зеркала при массовом релизе. Если у вас в этот момент запланирован деплой новой партии серверов или критичное обновление безопасности — недоступность репозитория на 20 минут превращается в простой команды. Локальный кэш с уже скачанными пакетами эту зависимость снимает: то, что один раз прошло через прокси, остаётся доступным даже если апстрим временно лёг.

Третья — скорость развёртывания. Разворачивая новый сервер с нуля, вы обычно ставите пакетов на несколько сотен мегабайт: базовый набор, веб-сервер, зависимости приложения. Если это идёт через прогретый локальный кэш, установка занимает секунды вместо минут — особенно заметно, когда серверы поднимаются пачками через Ansible или Terraform.

Прокси-кэш и полное зеркало — в чём разница

Это два разных инструмента для соседних, но не одинаковых задач, и путать их не стоит.

Прокси-кэшПолное зеркало
Что хранитТолько то, что реально запрашивалиВесь репозиторий целиком
Место на дискеЕдиницы — десятки гигабайтСотни гигабайт — единицы терабайт
Первый запрос нового пакетаИдёт наружу, кэшируется на будущееНе нужен — пакет уже локально
Работа при недоступном апстримеОтдаёт только то, что уже кэшированоРаботает полностью автономно
СинхронизацияНе нужна, кэш наполняется самНужен регулярный rsync/reposync
Время на запуск15–30 минутЧасы на первую синхронизацию, дальше — обслуживание

Прокси-кэш — это решение для ситуации «репозитории обычно доступны, но я хочу не платить за трафик дважды и иметь запас на случай кратковременного сбоя». Полное зеркало — для ситуации «мне нужна гарантированная автономность независимо от апстрима», например при жёстких требованиях к изоляции или при регулярной недоступности конкретного репозитория. Если вы уже сталкивались с ситуацией, когда репозиторий пакетов был недоступен и нужно было поднимать зеркало в срочном порядке — прокси-кэш как раз тот инструмент, который снижает шанс попасть в такую ситуацию заново, не требуя держать полную копию репозитория.

Здравый подход — начинать с прокси-кэша: он дешевле по ресурсам, проще в обслуживании и уже закрывает две из трёх типичных болей (трафик и скорость деплоя). К зеркалу имеет смысл переходить, если кэш регулярно не спасает — например, апстрим падает на часы, а не на минуты, или вам нужна полная работоспособность без интернета вообще. По той же логике «свой узел вместо похода наружу» уже строят собственные кеширующие узлы вместо коммерческого CDN — экономика там похожая: один прогретый локальный узел вместо повторных запросов к внешнему сервису с каждого клиента.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Кэширующий прокси для apt (Debian/Ubuntu): apt-cacher-ng

Для мира Debian/Ubuntu стандартный и проверенный вариант — apt-cacher-ng. Ставится на выделенный сервер или в отдельный контейнер внутри вашей сети.

apt-get update
apt-get install -y apt-cacher-ng

По умолчанию сервис слушает порт 3142 и хранит кэш в /var/cache/apt-cacher-ng. Базовая конфигурация лежит в /etc/apt-cacher-ng/acng.conf — большинству сценариев достаточно значений по умолчанию, но стоит явно проверить и при необходимости поправить два параметра:

# /etc/apt-cacher-ng/acng.conf
CacheDir: /var/cache/apt-cacher-ng
LogDir: /var/log/apt-cacher-ng
# Сколько места отдать под кэш (в МБ), иначе он будет расти неконтролируемо
ExThreshold: 4

После установки перезапустите сервис и проверьте, что порт слушается:

systemctl restart apt-cacher-ng
systemctl status apt-cacher-ng
ss -tlnp | grep 3142

На клиентских серверах (тех, что будут ходить за пакетами через кэш) правится не список репозиториев, а настройка прокси для apt — это важное отличие: адреса в sources.list остаются теми же, apt-cacher-ng сам разбирает URL и проксирует нужный upstream.

cat > /etc/apt/apt.conf.d/02proxy << 'EOF'
Acquire::http::Proxy "http://10.0.0.5:3142";
EOF

Замените 10.0.0.5 на реальный внутренний адрес сервера с кэшем. Дальше всё работает прозрачно:

apt-get update
apt-get install -y nginx

Первый такой запрос на новом клиенте пойдёт через прокси наружу и осядет в кэше, все последующие — с любого другого сервера в сети — будут обслуживаться локально. Проверить, что кэш действительно работает, можно через веб-интерфейс статистики apt-cacher-ng, который по умолчанию доступен на http://10.0.0.5:3142/acng-report.html — там видно объём отданных из кэша данных и промахи.

Кэширующий прокси для yum/dnf (RHEL-семейство, включая РЕД ОС и AlmaLinux)

Для RPM-дистрибутивов готового «единого» инструмента уровня apt-cacher-ng не сложилось — чаще используют либо связку nginx в роли обратного прокси с кэшированием, либо yum-utils/dnf с локальным репозиторием на другом сервере. Практичный вариант, который работает и для yum, и для dnf — прокси-кэш на nginx.

На сервере, который станет кэширующим узлом:

dnf install -y nginx

Конфиг nginx как кэширующего прокси перед реальными зеркалами дистрибутива:

# /etc/nginx/conf.d/pkgcache.conf
proxy_cache_path /var/cache/nginx/pkgs levels=1:2 keys_zone=pkgcache:50m
                  max_size=20g inactive=60d use_temp_path=off;

server {
    listen 8080;

    location / {
        resolver 8.8.8.8;
        proxy_pass https://$upstream_host$request_uri;
        proxy_cache pkgcache;
        proxy_cache_valid 200 302 30d;
        proxy_cache_key $uri;
        proxy_ssl_server_name on;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

Такой конфиг требует доработки под конкретное зеркало (нужно подставить реальный upstream-хост через map или отдельный server на каждое зеркало) — общий шаблон здесь дан как отправная точка, а не готовый к копированию файл: у РЕД ОС, AlmaLinux и Astra Linux разная структура репозиториев, и адрес upstream должен быть прописан явно, а не подставляться динамически из заголовка запроса клиента, иначе прокси превратится в открытый релей. Если конкретного пакета в репозитории РЕД ОС вообще не находится — это уже отдельная проблема, не решаемая кэшем, и здесь пригодится опыт из статьи о том, как собрать свой RPM, когда пакета нет в репозитории.

Более простой и предсказуемый путь для yum/dnf — направить трафик пакетного менеджера на локальный прокси через переменную окружения или параметр в /etc/yum.conf (или /etc/dnf/dnf.conf):

# /etc/yum.conf или /etc/dnf/dnf.conf
proxy=http://10.0.0.5:8080

После этого yum update и dnf install на клиентских серверах пойдут через локальный узел, а он уже сам кэширует ответы согласно proxy_cache_valid. Проверить, что кэш реально используется, можно по заголовку ответа:

curl -I http://10.0.0.5:8080/some/package.rpm
# X-Cache-Status: HIT   — отдано из кэша
# X-Cache-Status: MISS  — забрано с апстрима и закэшировано

Практические нюансы, которые легко упустить

Инвалидация и TTL. proxy_cache_valid 200 302 30d в примере выше — разумный дефолт для immutable-пакетов (версия пакета не меняется задним числом), но метаданные репозитория (Packages.gz, repodata) обновляются чаще самих пакетов. Их стоит кэшировать на существенно меньший срок — иначе клиенты будут видеть устаревший список версий и не найдут свежий пакет, хотя он уже вышел. Для apt-cacher-ng это решается автоматически (он различает индексные файлы и сами пакеты), для nginx-варианта под yum нужно явно развести location для repodata/* (короткий TTL, минуты-часы) и для *.rpm (длинный TTL).

Диск не резиновый. Параметр max_size в конфиге nginx и ExThreshold-подобные настройки в apt-cacher-ng существуют не просто так — без лимита кэш будет расти, пока не забьёт диск целиком. Закладывайте реалистичный объём: для однородного парка серверов на одной ОС и одном наборе пакетов обычно достаточно 10–30 ГБ, для разнородной инфраструктуры с несколькими дистрибутивами — больше. Мониторьте занятое место отдельно, это не тот случай, где «настроил и забыл» работает безопасно.

HTTPS-репозитории. Современные зеркала Debian/Ubuntu и большинства RPM-дистрибутивов ходят по HTTPS. apt-cacher-ng умеет проксировать HTTPS через CONNECT, но по умолчанию не кэширует содержимое зашифрованных ответов, если не включена соответствующая опция (PassThroughPattern для туннелирования или переключение репозиториев на http, где это возможно и безопасно для целостности пакетов — она всё равно проверяется подписями). Для связки nginx проще: там прокси сам терминирует TLS до апстрима (proxy_pass https://...) и кэширует расшифрованный ответ, отдавая клиенту уже без шифрования — это штатно для внутренней сети, но не подходит, если политика требует HTTPS до клиента включительно.

Не забудьте про безопасность самого прокси. Кэширующий узел не должен быть доступен из интернета — иначе это открытый релей, которым может воспользоваться кто угодно. Ограничьте доступ фаерволом до внутренней сети:

# ufw
ufw allow from 10.0.0.0/24 to any port 3142
ufw deny 3142

# firewalld
firewall-cmd --permanent --zone=internal --add-port=3142/tcp --add-source=10.0.0.0/24
firewall-cmd --reload

Единая точка отказа. Если весь парк серверов зависит от одного кэширующего узла, а этот узел упал — обновления встанут у всех разом, даже если апстрим доступен. На практике это не такой уж риск (сервис простой, падает редко), но стоит либо держать резервный узел, либо настроить клиентов на fallback без прокси при недоступности локального кэша — в apt это делается через Acquire::http::Proxy::DIRECT "true"; для конкретных хостов в конфиге прокси.

Пример: связка Ansible для массового переключения серверов на кэш

Когда серверов десятки, руками прописывать прокси на каждом неэффективно. Минимальный playbook для apt-парка:

---
- hosts: all
  become: true
  tasks:
    - name: Настроить прокси apt-cacher-ng
      copy:
        dest: /etc/apt/apt.conf.d/02proxy
        content: |
          Acquire::http::Proxy "http://10.0.0.5:3142";
        owner: root
        mode: '0644'

    - name: Обновить список пакетов через кэш
      apt:
        update_cache: yes

Для yum/dnf аналогично — модулем lineinfile дописывается строка proxy= в /etc/yum.conf на всех хостах группы. Такой подход особенно оправдан, если новые серверы разворачиваются регулярно: прокси прописывается сразу в базовом образе или в первом же playbook при настройке машины, и все последующие установки уже идут через кэш с первого пакета.

Когда прокси-кэша уже недостаточно

Есть сценарии, где кэш не закрывает потребность и нужно смотреть в сторону полного зеркала:

  • Инфраструктура должна работать полностью автономно, без доступа в интернет вообще (изолированные контуры, требования по безопасности).
  • Апстрим-репозиторий недоступен не эпизодически, а систематически — кэш в таком случае бесполезен для пакетов, которые ни разу не были запрошены до сбоя.
  • Нужна воспроизводимая версия репозитория на конкретную дату (для аудита, для тестовых стендов, для соответствия production-окружению) — кэш этого не гарантирует, он хранит то, что запросили, а не полный слепок на момент времени.

Для этих случаев логичный следующий шаг — развернуть reposync/rsync-зеркало с полной копией нужных разделов репозитория и регулярной синхронизацией по расписанию. Это больше по объёму диска и требует обслуживания, зато не зависит от того, что именно уже было запрошено ранее. Практика регулярного обслуживания пакетной системы на этом не заканчивается — базовые принципы разобраны в статье про обновление и обслуживание AlmaLinux 9 с нуля, они применимы и при работе через кэширующий прокси.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нужен ли отдельный сервер под прокси-кэш или можно разместить на существующем?

Можно на существующем — сервис лёгкий по CPU и памяти, основная нагрузка на диск. Если сервер уже держит другую нагрузку с интенсивным I/O, лучше вынести кэш отдельно, чтобы не конкурировать за диск.

Что будет, если кэширующий узел недоступен, а апстрим — доступен?

Зависит от настройки. Без fallback-конфигурации клиенты получат ошибку подключения к прокси и не смогут обновиться, даже если реальный репозиторий работает. Настройте DIRECT-фallback для apt или предусмотрите второй узел для критичных серверов.

Можно ли использовать один кэширующий узел сразу для apt и yum?

Да, это разные сервисы (apt-cacher-ng и nginx-кэш) на разных портах одного и того же сервера — конфликтов нет, ресурсы делятся штатно.

Стоит ли включать прокси-кэш, если серверов всего два-три?

Экономия трафика будет минимальной, но страховка от кратковременной недоступности репозитория и ускорение повторных установок остаются полезными даже при небольшом парке. Решение скорее «зачем нет», чем «обязательно нужно» — здесь можно ориентироваться на то, насколько критичны простои при обновлениях.

Как понять, что кэш реально экономит трафик, а не просто стоит без дела?

По логам (acng-report.html у apt-cacher-ng, заголовок X-Cache-Status у nginx) и по счётчику исходящего трафика с сервера, где раньше пакеты качались напрямую — падение внешнего трафика после включения кэша обычно заметно уже в первую неделю.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →