📑 Содержание статьи
В данной статье, мы поделим на две части процесс. В первой части мы создадим структуру для репозитория, отзеркалируем действующий репозиторий Astra Linux 1.8.6. Во второй части мы создадим свой, локальный репозиторий, в который загрузим пакеты, не входящие в основной репозиторий Astra Linux и применим установку этих пакетов на втором сервере используя наш репозиторий.
Для чего создавать свой репозиторий (вместе с зеркалом)? Во-первых, вы перестанете зависеть от интернета, от багов в Latest версиях обновлений, от удаления старых версий репозиториев. Во-вторых, вы сами будете решать, обновлять ваш парк машин на новую версию или нет. В-третьих, вы сами можете добавлять и обновлять пакеты, которые отсутствуют в интернет-репозитории. Предположим у Вас есть парк из 30 машин, вам нужно обновить каждую до новой версии. Все 30 машин пойдут загружать в интернет пакеты для обновления, особенно если вы запустите массовое обновление скриптом/ansible/puppet, это сразу удар поддых вашему каналу связи. Да, можно настроить cron на обновление рандомной датой и временем или же в часы наименьшей нагрузки или постепенное (партиями) обновления. Локальный репозиторий все равно не панацея и он не сделает безболезненным обновлением сразу 30 машин за раз, но уже с локального репозитория. Тут так же нужно планировать порционную подачу. В случае с интернетом, вы дадите хорошую нагрузку на интернет канал, а в случае с локальным, вы скорее всего упретесь в характеристики вашего железа (опять же, если у вас есть гигабитная сетка). Но грамотный подход в лице: гигабитная сеть, apt-cacher, cron и вы с легкостью обновите все 30 машин. Можно настроить свой сервер не как зеркало интернет-репозитория, а как кэширующий прокси-сервер, а уже с него производить обновления. Это так же существенно снизит нагрузку на интернет канал, но не решит проблему, когда интернет отсутствует.
Второй пример все с этими же 30 машинами. Захотели вы установить пакет, которого нет в репозитории. Вы его скачиваете с просторов интернета, загружаете на свою репу и с помощью скриптов/ansible или же puppet - осуществляете его установку на все 30 машин и в дальнейшем можете обновлять и подкидывать новые версии пакетов программ. Это лишь пару примеров из большинства плюсов своего сервера репозитория.
Приступим. Для своего репозитория, я рекомендую при установке Astra Linux создать отдельный раздел и назвать его - /repo. Как размечать диски есть тут.
- Стенд:
- Сервер 1 (astraops-repo) - 192.168.31.81
- Сервер 2 (astraops-grafana) - 192.168.31.214
Часть 1. Сервер с зеркалом
0. Обновим индексы пакетов
sudo apt update
1. Установим пакеты для зеркала и локального репозитория
sudo apt install -y nginx gnupg reprepro dpkg-dev ca-certificates apt-mirror2
2. Создадим структуру для зеркалирования и локального репозитория
sudo mkdir -p /repo/{mirror,repo,preload}

Приватный GPG-ключ - вне /repo!
sudo mkdir -p /root/.gnupg
sudo chmod 700 /root/.gnupg
sudo chown -R root:root /repo
sudo chmod -R 755 /repo

/repo/mirror/ -- зеркало официальных репозиториев Astra Linux
/repo/repo -- локальный репозиторий, база reprepro
/repo/preload -- входящие .deb-файлы перед добавлением в репозиторий
/root/.gnupg -- отдельный GNUPGHOME для ключа локального репозитория
3. Настройка /etc/apt/mirror.list
sudo vim /etc/apt/mirror.list
Нужно изменить два блока: параметры (config) и список репозиториев.
Изменяем base_path на свой, это корневой каталог, внутри которого создастся структура (mirror/, skel/, var/) с помощью apt-mirror2.
apt-mirror2 создаст внутри base_path подкаталог mirror. То есть фактические файлы репозитория окажутся в /repo/mirror/mirror/. Именно этот вложенный каталог впоследствии нужно будет раздавать через nginx как DocumentRoot.отредактируйте две вещи:
Находим строку:
set base_path /var/spool/apt-mirror
Приводим ее в такой вид:
set base_path /repo/mirror


Остальные пути (mirror_path, skel_path, var_path) уже используют $base_path , трогать их не нужно.
Находим в самом низу файла, репозитории, они будут у нас в качестве источника, откуда будем зеркалировать.

Удалим эти строчки, так как они не актуальны, а возьмем актуальные из sources.list или же из интернета. Я взял и адаптировал их под apt-mirror2 из sources.list.
Копируем эти строчки и вставляем в /etc/apt/mirror.list
Получилось вот так:

http2-disable https://dl.astralinux.ru/astra/stable/1.8_x86-64/main-repository
deb https://dl.astralinux.ru/astra/stable/1.8_x86-64/main-repository 1.8_x86-64 main contrib non-free non-free-firmware
http2-disable https://dl.astralinux.ru/astra/stable/1.8_x86-64/extended-repository
deb https://dl.astralinux.ru/astra/stable/1.8_x86-64/extended-repository 1.8_x86-64 main contrib non-free non-free-firmware
clean https://dl.astralinux.ru/astra/stable/1.8_x86-64/main-repository
clean https://dl.astralinux.ru/astra/stable/1.8_x86-64/extended-repository
Для удобства, я добавил комментарий «Источники зеркалирования».
- http2-disable <URL>
- Эта директива отключает использование HTTP/2 при обращении к указанному репозиторию.
apt-mirror2в этом случае будет работать с ним по HTTP/1.1 (или HTTPS с HTTP/1.1).
- Эта директива отключает использование HTTP/2 при обращении к указанному репозиторию.
- clean <URL>
- Эта директива разрешает автоматическую очистку устаревших файлов в зеркале указанного репозитория.
- При каждом запуске
apt-mirror2скачивает новые версии пакетов и метаданных.Старые версии .deb-файлов, которые уже удалены из внешнего репозитория, остаются в зеркале и занимают место. По умолчанию (без clean)apt-mirror2не удаляет такие файлы, а только создает скрипт $var_path/clean.sh, который можно запустить вручную. - Если указать clean <URL>,
apt-mirror2сам выполнит очистку для этого репозитория в конце синхронизации и не нужно запускать скрипт вручную.
Чтобы зеркало не «обнулилось» из-за сбоя на стороне внешнего сервера, есть два предохранителя (закомментированы в дефолтном конфиге):
# set wipe_size_ratio 0.4 - не чистить, если удаляется > 40% объема;
# set wipe_count_ratio 0.4 - не чистить, если удаляется > 40% файлов.
Если суммарный объем или количество удаляемых файлов превышает эти параметры от общего размера/количества, очистка не выполняется. Это защита от ситуации, когда внешний сервер временно отдал пустой или неполный репозиторий.
Накидываем права для учетной записи apt-mirror - запуск будем осуществлять от ее имени.
sudo chown -R apt-mirror:apt-mirror /repo/mirror
4. Запускаем зеркалирование интернет-репозиториев к себе в хранилище
sudo -u apt-mirror apt-mirror

Объем зеркала main - 2.9 GiB
Это размер только main-repository без extended. Полное зеркало Astra Linux 1.8 с обоими репозиториями занимает значительно больше.

После зеркалирования, можно посмотреть, что 1.8.6 я загрузил к себе на сервер.

Видно, что конфиг Release лежит как раз в том месте, куда мы зеркалировали.
5. Настройка Nginx.
Ну вот и все, репозиторий мы отзеркалировали, теперь у нас локально имеется своя репа 1.8.6, но нужно сделать ее доступной для других машин. На помощь нам придет любой веб-сервер (Apache2, Nginx). Всю свою практику я видел репозитории на apache2, но вот на nginx не видел ни разу (я не говорю что их нет, просто я не видел вживую, а так же в статьях никто не использовал nginx). Я привык работать с nginx, да и он более современней, чем apache2, а так же написал его наш соотечественник, по этому будем использовать его в качестве веб-сервера.
Так как мы установили nginx на шаге 1, то сразу перейдем к его настройке.
Создадим отдельную директорию для отображения в браузере
sudo mkdir -p /repo/html
Сделаем симлинк зеркала в эту директорию
sudo ln -s /repo/mirror/mirror/download.astralinux.ru/astra/stable/1.8_x86-64 /repo/html/astra_1.8.6
Накинем права www-data (чтобы nginx имел туда доступ) на директорию
sudo chown -R www-data:www-data /repo/html
Альтернатива, можно создать симлинк через MC (Midnight Commander).
sudo mc
Если ошибка и ее нет, то установите (sudo apt install mc)

Слева директория /repo/html где будут лежать симлинки, а справа директория с репозиторием которые мы отзеркалировали на 4-ом шаге. Сейчас я покажу, как можно создать симлинки.
Выбираем справа директорию на которую хотите сделать симлинк, потом «Файл» и «Символическая ссылка»

Изменяем «Имя символической ссылки» на astra_1.8.6


Получилось так

Забегая немного вперед (еще не настроили nginx, по этому у вас так отображаться не будет)



То есть мы создаем симлинк директории 1.8_x86-64! Так как astra_1.8.6 уже есть в моем случае, то я создам astra_1.8.6_stable

Получилось так:

Если перейти в astra_1.8.6_stable то увидим ветки main и extended

Возвращаемся к Nginx.
Создадим новый конфиг для nginx
sudo vim /etc/nginx/sites-available/astraops-repo
и содержимое:
server {
listen 80;
server_name _;
root /repo/html;
autoindex on;
disable_symlinks off;
autoindex_exact_size off;
autoindex_localtime on;
location / {
try_files $uri $uri/ =404;
}
}

Что тут у нас есть:
- listen 80 - работает по 80 порту
- server_name - можно указать ip/имя машины или оставить _.
- root /repo/html; - Корневая директория для поиска файлов
- autoindex on; - Включает вывод списка файлов
- disable_symlinks off; - ВАЖНО: Разрешаем nginx следовать по символическим ссылкам
- autoindex_exact_size off; autoindex_localtime on; -- улучшаем вид листинга
- location / { - Пытаемся отдать файл, если его нет - показываем листинг
Создаем симлинк конфига в действующие конфиги nginx.
sudo ln -s /etc/nginx/sites-available/astraops-repo /etc/nginx/sites-enabled/

Перезапускаем службу nginx
sudo systemctl restart nginx
Теперь можно идти в браузер и проверять что показывает сервер. Я уже показал на примере создания симлинка через MC. Но вставлю еще раз.

Как видим, в браузере при заходе по ip адресу сервера 192.168.31.81 сразу открывается репозиторий, в котором мы создали симлинк на 1.8.6 (в данном примере я сначала создал astra_1.8.6, так как я не качал extended-repository).
6. Настройка клиента (сервер 2 (astraops-grafana))
Идем на второй сервер (клиент) (astraops-grafana) и прописываем sources.list.
sudo vim /etc/apt/sources.list
Здесь прописан интернет-репозиторий

Заменяем на

Запись получается такого рода
deb http://192.168.31.81/astra_1.8.6/main-repository 1.8_x86-64 main contrib non-free non-free-firmware
deb http://192.168.31.81/astra_1.8.6/extended-repository 1.8_x86-64 main contrib non-free non-free-firmware
Если вы делали симлинк с помощью команды или не делали название симлинка astra_1.8.6_stable.
Что мы видим, ip адрес сервера 1 (astraops-repo), далее директория astra_1.8.6 в которую если зайти, есть две поддиректории: main-repository и extended-repository
Далее запускаем обновление индексов
sudo apt update

Это нормальное поведение, так как у меня extended-repository пустой, говорил об этом ранее. То я просто закомментирую его в /etc/apt/sources.list и прогоню apt update еще раз.

Отлично, ошибка ушла и новых нет. Теперь я могу загружать пакеты со своего локального сервера и даже если пропадет интернет, то доступ к репозиторию у меня всегда будет. Так как у меня 1.8.6 сервер 2, то обновлять соответственно нечего.
Можно так же переписать под astra_1.8.6 который я создал для чисто main-repository.


Как видим, я вообще не указывал main-repository, а лишь astra_1.8.6 (это симлинк, который ведет на зеркало в main-repository).
Release
Release.gpg
InRelease
Packages
Packages.gz
Sources
pool/
то клиентские машины будут проверять подпись оригинальным ключом Astra Linux, а не вашим ключом. Не нужно переподписывать официальное зеркало своим ключом, если только вы не собираете полностью собственный репозиторий-сборку
На этом часть 1 завершена. Мы с Вами создали создали на чистом сервере, локальный репозиторий, в который отзеркалировали интернет-репозиторий версии Astra Linux 1.8.6.39 и теперь можем быть суверенными от интернет репозитория и от свежих версий. Во второй части, мы создадим свой репозиторий, со своим набором пакетов.
Часть 2. Создаем локальный репозиторий
0. Создание ключей
Начнем мы с создания ключей.
Репозиторий должен быть подписан, чтобы apt на клиентских машинах мог проверить его подлинность. Создадим GPG-ключ от имени пользователя, который будет управлять репозиторием (в нашем случае - root).
sudo gpg --gen-key
Вводим имя, почту.

Создаем «фраза-пароль»

Повторяем ввод:

После генерации получила основной ключ и подключ.

Теперь нужно узнать ID (отпечаток) ключа, он понадобится для конфигурации в дальнейшем:
sudo gpg --list-secret-keys --keyid-format LONG
Вывод будет примерно таким:
/root/.gnupg/pubring.kbx
------------------------
sec rsa3072/BB6221A5A24B3EAD 2026-10-09 [SC] [ годен до: 2028-10-08]
AE84190B326A5EB17B8E4946BB6221A5A24B3EAD
uid [ абсолютно ] Andrew <astraops@local.ru>
ssb rsa3072/FDDCAC6CEB813028 2026-10-09 [E] [ годен до: 2028-10-08]
sec - основной ключ. Он используется для подписи (флаг [SC] = Sign + Certify). Именно его нужно указывать в reprepro.
ssb - подключ. Он используется для шифрования (флаг [E]). Для подписи репозитория он не подходит.
В данном примере ID ключа - BB6221A5A24B3EAD (или полный отпечаток AE84190B326A5EB17B8E4946BB6221A5A24B3EAD).
В conf/distributions в директиве SignWith указывайте полный отпечаток основного ключа:
SignWith: AE84190B326A5EB17B8E4946BB6221A5A24B3EAD
В редких случаях, короткий может совпасть с другим ключом.
1. Настройка reprepro
Создадим директорию для настроек
sudo mkdir -p /repo/repo/conf/
Создадим конфиг distributions
sudo vim /repo/repo/conf/distributions
Скопируйте содержимое, заменив <ваш-отпечаток> на ID ключа из предыдущего пункта:
Origin: Astra Local Repository
Label: Astra Local
Codename: 1.8_x86-64
Suite: stable
Version: 1.8
Architectures: amd64
Components: main contrib non-free non-free-firmware
UDebComponents: main
Contents:
SignWith: <ваш-отпечаток>

Сохраняем и выходим.
Codename: 1.8_x86-64- это кодовая строка, которая будет использоваться в sources.list на клиентах. Можно задать любое, удобное имя (например, astra-custom).Components:здесь можно перечислить компоненты, которые планируете использовать. main - для ваших собственных пакетов.SignWith:указываем ID GPG-ключа.
2. Инициализация репозитория
Вводим команду ниже, чтобы reprepro создал базовую структуру (dists, pool и т.д.):
sudo reprepro --ask-passphrase -b /repo/repo export
![]()
Нас просят ввести пароль от GPG-ключа.


3. Экспорт публичного ключа для клиентов
Клиентам нужен наш публичный ключ, чтобы доверять репозиторию. Экспортируем его в файл:
создадим директорию для публичного ключа
sudo mkdir -p /repo/repo/keys
экспортируем публичный ключ
sudo gpg --armor --output /repo/repo/keys/repo.gpg --export <ваш-отпечаток>
Этот файл (repo.gpg) нужно будет скопировать на каждую клиентскую машину.
![]()
Скопируем ключ в /tmp и перенес на сервер 2 (astraops-grafana).


Вернемся к ключу на клиенте чуть позже.
4. Настройка Nginx
Назовем свою ветку репозитория /repo.
Чтобы репозиторий был доступен по адресу http://192.168.31.81/repo/, нужно либо создать симлинк, либо настроить alias в nginx. Рекомендую симлинк - это проще и надежнее.
Создаем симлинк в корне html-директории
sudo ln -s /repo/repo /repo/html/repo

Проверяем, что симлинк ведет куда надо
ls -la /repo/html/repo
Перезапускаем nginx (на всякий случай).
sudo systemctl reload nginx
Проверяем в браузере

5. Настройка клиента
На клиентской машине нужно сделать две вещи:
- Скопировать и импортировать публичный ключ репозитория;
- Добавить /repo в sources.list
Возвращаемся к ключу, который мы уже закинули на сервер 2. Импортируем ключ на сервере 2 (astraops-grafana).
Первый метод:
![]()
Теперь необходимо прописать в sources.list новый репозиторий.
Открываем sources.list
sudo vim /etc/apt/sources.list
Вставляем
deb [signed-by=/usr/share/keyrings/astra-local.gpg] http://192.168.31.81/repo 1.8_x86-64 main contrib non-free non-free-firmware
Важные замечания:
В sources.list на клиентах вы указываете Codename (1.8_x86-64), который задали в conf/distributions. Он не обязан совпадать с версией Astra Linux.
указываем путь до ключа gpg
[signed-by=/usr/share/keyrings/astra-local.gpg]
| Часть | Значение |
| deb | Бинарный репозиторий |
| [signed-by=...] | Указывает, каким ключом проверять подпись |
| http://192.168.31.81/repo | URL вашего репозитория (через симлинк в nginx) |
| 1.8_x86-64 | Codename из conf/distributions |
| main contrib non-free non-free-firmware | Компоненты |
Если не указать [signed-by=...], то получим следующее.

Если укажем

То теперь при sudo apt update, ошибок нет.

Второй метод:
Если у вас ключ лежит локально уже на машине, то можно добавить его одной командой, но запускаем рядом с ключом.
sudo gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/repo.gpg --import repo.gpg
Накидываем права
sudo chmod 644 /etc/apt/trusted.gpg.d/repo.gpg

Теперь необходимо прописать в sources.list новый репозиторий.
Открываем sources.list
sudo vim /etc/apt/sources.list
Вставляем
deb http://192.168.31.81/repo 1.8_x86-64 main contrib non-free non-free-firmware
Теперь убираем [signed-by=/usr/share/keyrings/astra-local.gpg]
если вы делали на первом методе.


Проверяем, что все работает.
sudo apt update

Рассмотрим вариант, если ключ у вас на репе лежит в html. Это все еще ко второму методу относится.
Сделаем симлинк ключа на веб-сервере.

Видим, что ключ теперь доступен для загрузки всем.
Теперь можно загрузить и установить одной командой на любой машине:
sudo curl -s http://192.168.31.81/repo.gpg | sudo gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/repo.gpg --import && sudo chmod 644 /etc/apt/trusted.gpg.d/repo.gpg
Данная команда загрузит с репы ключ, сразу передаст его на импорт в хранилище ключей и накинет нужные права.
Далее запускаем sudo apt update

Я думаю такой метод проще и лучше, чем прописывать в sources.list путь до ключа.
Теперь у нас два локальных репозитория подключено: 1 - main-repository (зеркало интернет-репозитория Astra Linux 1.8.6.39); 2 - repo (локальный наш main репозиторий с нашими пакетами).
6. Добавление deb пакетов в свой репозиторий
Давайте добавим в наш созданный репозиторий, хотя бы один пакет, для теста. Пробежавшись по загрузкам, я нашел недавно загруженный LM-Studio.deb
![]()
Супер, его точно нету в репозиториях астры))
Закидываем его на сервер 1 (astraops-repo).
![]()
Теперь копируем его в директорию /repo/preload
Данную директорию мы создали специально, чтобы из нее загружать новые пакеты в наш репозиторий.
![]()
Теперь загрузим все пакеты из /repo/preload в наш репозиторий.
sudo reprepro --ask-passphrase -b /repo/repo includedeb 1.8_x86-64 /repo/preload/*.deb
- 1.8_x86-64 - это Codename из файла distributions.
- includedeb - команда для добавления бинарного пакета.
После добавления reprepro автоматически обновит индексы.
![]()
Если зайти в браузер и перейти в /repo/pool/main/l/lm-studio, то увидим наш добавленный пакет

Идем на машину сервер 2 (astraopfs-grafana), обновляем индексы пакетов и проверяем, доступен ли lm-studio для загрузки из репозитория repo.


Отлично! Нам доступен для установки lm-studio с нашего локального репозитория. Теперь мы можем загружать любые пакеты, а так же свои сборки deb пакетов. Осталось распространить свой локальный репозиторий с ключом на условные 30 машин. Можно сделать вручную, можно написать скрипт, можно через Ansible, Puppet, Kaspersky. Как фантазия сработает! Я надеюсь, что данная статья была для Вас полезна! Увидимся в следующих статьях, удачи!