Как создать локальный APT-репозиторий?

Вопрос или проблема

Я хотел бы создать свой собственный локальный репозиторий в своей локальной сети, чтобы машины в локальной сети могли обновляться и устанавливать с него пакеты. Я хочу скачать пакеты и хранить их на своем локальном сервере, чтобы можно было обновлять, устанавливать и т.д. с него без использования интернета.

Из вики помощи Ubuntu:

Существует 4 шага для настройки простого репозитория для себя

  1. Установите dpkg-dev
  2. Поместите пакеты в директорию
  3. Создайте скрипт, который будет сканировать пакеты и создавать файл, который может читать apt-get update
  4. Добавьте строку в sources.list, указывающую на ваш репозиторий

Установка dpkg-dev

Введите в терминале

sudo apt-get install dpkg-dev

Директория

Создайте директорию, в которой вы будете хранить свои пакеты. Для этого примера мы используем /usr/local/mydebs.

sudo mkdir -p /usr/local/mydebs

Теперь переместите ваши пакеты в только что созданную директорию.

Ранее загруженные пакеты обычно хранятся в вашей системе в директории /var/cache/apt/archives. Если вы установили apt-cacher, у вас будут дополнительные пакеты, хранящиеся в его директории /packages.

Скрипт update-mydebs

Это простой трехстрочный скрипт:

#! /bin/bash
cd /usr/local/mydebs
dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

Скопируйте и вставьте вышеуказанное в gedit и сохраните его как update-mydebs в ~/bin. (Тильда ‘~’ обозначает вашу домашнюю директорию. Если ~/bin не существует, создайте его: Ubuntu добавит эту директорию в ваш PATH. Это хорошее место для размещения личных скриптов). Далее сделайте скрипт исполняемым:

chmod u+x ~/bin/update-mydebs

Как работает скрипт:

dpkg-scanpackages просматривает все пакеты в mydebs, и вывод сжимается и записывается в файл (Packages.gz), который может читать apt-get update (см. ниже справка, объясняющая это в исчерпывающих деталях). /dev/null – это пустой файл; он является заменой файла переопределения, который содержит некоторую дополнительную информацию о пакетах, которая в данном случае не нужна. См. deb-override(5), если хотите об этом узнать.

Sources.list

Добавьте строку

deb file:/usr/local/mydebs ./

в ваш файл /etc/apt/sources.list, и вы закончили.

CD Опция

Вы можете записать директорию, содержащую deb-файлы, на CD и использовать его в качестве репозитория (хорошо подходит для обмена между компьютерами). Чтобы использовать CD в качестве репозитория, просто выполните

sudo apt-cdrom add

Использование репозитория

Каждый раз, когда вы помещаете новый deb в директорию mydebs, выполните

sudo update-mydebs
sudo apt-get update

Теперь ваши локальные пакеты могут быть обработаны с помощью Synaptic, aptitude и команд apt: apt-get, apt-cache и т.д. Когда вы пытаетесь apt-get install, любые зависимости будут решены для вас, если они могут быть удовлетворены.

Плохо сделанные пакеты, вероятно, не сработают, но вы не будете страдать от ада dpkg.

*Чтобы создать оффлайн-репозиторий по LAN *

Установите локальный веб-сервер Apache

# apt-get install apache2

По умолчанию пакет Apache для Debian создаст веб-сайт в /var/www на вашей системе. Для наших целей этого достаточно, так что нет причин делать что-либо еще. Вы можете легко протестировать это, указав в вашем любимом браузере http://localhost. Вы должны увидеть стандартную веб-страницу после установки, которая на самом деле хранится в /var/www/index.html

Создайте директорию репозитория Debian

выберите для этого создание директории /var/www/debs. Под ней вы должны создать «архитектурные» директории, по одной для каждой архитектуры, которую вы хотите поддерживать. Если вы используете только один компьютер (или один тип компьютера), то вам потребуется только одна — обычно «i386» для 32-битных систем или «amd64» для 64-битных. Если вы используете какую-либо другую архитектуру, предполагаю, что вы уже знаете об этом.
Теперь просто скопируйте файлы пакетов “.deb” для данной архитектуры в соответствующие директории. Если вы теперь укажете в вашем любимом веб-браузере http://localhost/debs/amd64 (например), вы увидите список пакетов для 64-битных систем.

Создайте файл Packages.gz

Теперь нам нужно создать каталог для использования APT. Это делается с помощью утилиты под названием “dpkg-scanpackages”. Вот команды, которые я использую для обновления пакетов AMD64 в своей локальной сети:

# cd /var/www/debs/

# dpkg-scanpackages amd64 | gzip -9c > amd64/Packages.gz

Сделайте репозиторий известным для APT

Теперь осталось только сообщить APT о вашем репозитории. Вы делаете это, обновляя свой файл /etc/apt/sources.list. Вам нужно, чтобы была такая запись:

deb http://localhost/debs/ amd64/

Я использовал фактическое имя хоста своей системы вместо localhost — таким образом, код одинаков для всех компьютеров в моей локальной сети, но localhost вполне подходит, если у вас только один компьютер.
Теперь обновите APT:

# apt-get update

Создание аутентифицированного репозитория

Я посмотрел на ответы здесь и на других сайтах, и большинство из них имеют (на мой взгляд, большой) недостаток в том, что вы настраиваете неаутентифицированный репозиторий. Это означает, что вам нужно будет запускать apt-get с --allow-unauthenticated, чтобы установить пакеты из него. Это может представлять собой риск безопасности, особенно в скриптах, где пакеты, которые вы устанавливаете, могут быть не все из вашего локального репозитория.

Обратите внимание, что я не рассмотрел здесь, как сделать его доступным через LAN, но это довольно общая конфигурация с использованием Apache или nginx (см. другие ответы здесь).

Настройте директорию репозитория

mkdir /home/srv/packages/local-xenial
cd /home/srv/packages/local-xenial

Затем добавьте строку, подобную этой, в sources.list:

deb file:/home/srv/packages/local-xenial/ ./

Добавление и удаление пакетов

удалите пакеты

rm /home/srv/packages/local-xenial/some_package_idont_like

добавьте пакеты

cp /some/dir/apackage.deb /home/srv/packages/local-xenial

теперь выполните следующий скрипт, который генерирует файлы Packages, Release и InRelease и подписывает их вашим закрытым ключом gpg:

   #!/bin/bash
# настройка простого совместимого с apt репозитория, имеющего один компонент 'main' в директории с использованием большинства рекомендуемых структур директорий из официальной вики Debian (https://wiki.debian.org/DebianRepository/Format)

function rebuild_local_repo
{
    DISTROCODENAME=${1} # Например, noble, если используете Ubuntu Noble 24.04, также называется 'Suite' в вики Debian
    ARCHTOBUILDFOR=${2} # Например, amd64, arm64
    COMPONENTNAME='main' # Большинство репозиториев используют 'main' или 'stable', вероятно, это не имеет значения, что это, но хорошо быть последовательным
    REPODIRECTORY="/srv/packages/localrepos/local-${DISTROCODENAME}"

    if [ ! -d ${REPODIRECTORY} ]; then
        echo "ERROR: директория репозитория ${REPODIRECTORY} не существует"
        exit 1
    fi
    cd ${REPODIRECTORY}

    # Установка необходимых директорий (https://wiki.debian.org/DebianRepository/Format)
    install -d -p -o tim -g tim -m 750 dists/${DISTROCODENAME}
    install -d -p -o tim -g tim -m 750 dists/${DISTROCODENAME}/${COMPONENTNAME}
    install -d -p -o tim -g tim -m 750 dists/${DISTROCODENAME}/${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}
    RELEASEFILEPATH=dists/${DISTROCODENAME}/Release
    INRELEASEFILEPATH=dists/${DISTROCODENAME}/InRelease
    PACKAGESFILEPATH=dists/${DISTROCODENAME}/${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}/Packages

    # Генерация файла Packages
    dpkg-scanpackages . /dev/null > ${PACKAGESFILEPATH}
    gzip --keep --force -9 ${PACKAGESFILEPATH}

    # Генерация файлов Release и InRelease
    # Обязательный заголовок для файла релиза:
    RELEASEFILEHEADER="Origin: Tim_Local_Repo
Label: My_Local_Repo
Codename: ${DISTROCODENAME}
Architectures: amd64 arm64 i386
Components: main
Description: Мой локальный APT репозиторий
SignWith: 12345DEF"
    echo "$RELEASEFILEHEADER" > ${RELEASEFILEPATH} # обратите внимание, что для использования многострочных переменных в bash и сохранения переводов строк вы должны использовать "$VAR", а не ${VAR}
    # Поле Date: имеет такой же формат, как и записи изменений пакетов Debian
    echo -e "Date: `LANG=C date --utc -R`" >> ${RELEASEFILEPATH}
    # Релиз должен содержать MD5 - суммы всех файлов репозитория (в простом репозитории только файлы Packages и Packages.gz)
    echo -e 'MD5Sum:' >> ${RELEASEFILEPATH}
    printf ' '$(md5sum ${PACKAGESFILEPATH}.gz | cut --delimiter=" " --fields=1)' %16d '${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}/Packages.gz $(wc --bytes ${PACKAGESFILEPATH}.gz | cut --delimiter=" " --fields=1) >> ${RELEASEFILEPATH}
    printf '\n '$(md5sum ${PACKAGESFILEPATH} | cut --delimiter=" " --fields=1)' %16d '${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}/Packages $(wc --bytes ${PACKAGESFILEPATH} | cut --delimiter=" " --fields=1) >> ${RELEASEFILEPATH}
    # Релиз должен содержать SHA256 - суммы всех файлов репозитория (в простом репозитории только файлы Packages и Packages.gz)
    echo -e '\nSHA256:' >> ${RELEASEFILEPATH}
    printf ' '$(sha256sum ${PACKAGESFILEPATH}.gz | cut --delimiter=" " --fields=1)' %16d '${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}/Packages.gz $(wc --bytes ${PACKAGESFILEPATH}.gz | cut --delimiter=" " --fields=1) >> ${RELEASEFILEPATH}
    printf '\n '$(sha256sum ${PACKAGESFILEPATH} | cut --delimiter=" " --fields=1)' %16d '${COMPONENTNAME}/binary-${ARCHTOBUILDFOR}/Packages $(wc --bytes ${PACKAGESFILEPATH} | cut --delimiter=" " --fields=1) >> ${RELEASEFILEPATH}

    # ClearSign файл Release (то есть, подпишите его без шифрования)
    gpg --yes --clearsign --digest-algo SHA512 --local-user tim -o ${INRELEASEFILEPATH} ${RELEASEFILEPATH}
    # Release.gpg нужен только для более старых версий apt
    # gpg -abs --digest-algo SHA512 --local-user tim -o Release.gpg Release

    # Установить разрешения
    chmod o+rX ${REPODIRECTORY} -R

    # Заставить apt видеть изменения, --allow-releaseinfo-change на случай, если что-то в RELEASEFILEHEADER изменилось
    sudo apt-get update --allow-releaseinfo-change
}

if [[ ${1} == '-h' || ${1} == '--help' ]]; then
    echo -e "использование: `basename $0` DISTRO ARCH
где DISTRO - это кодовое имя версии Ubuntu (например, 14.04 - это trusty), а ARCH - это архитектура ЦП (amd64, arm64, i386)\n
Способ использования этого скрипта - сначала внести изменения в репозиторий, то есть удалить или скопировать .deb файл в /srv/packages/localrepos/local-DISTRO, а затем запустить этот скрипт\n
Этот скрипт может быть запущен от имени пользователя tim (root не нужен)"
    exit 0
fi

if [ "$#" -ne 2 ]; then
    # если пользователь не указал версию дистрибутива, то попробуйте обновить репозиторий для текущей версии дистрибутива
    DISTROCODENAME=`lsb_release -c | awk '{print $2}'`

    # если пользователь не указал архитектуру, обновите репозиторий для текущей архитектуры
    arch=$(uname -i)
    ARCHITECTURE='amd64' # по умолчанию используем наиболее распространенную архитектуру
    if [[ $arch == x86_64* ]]; then
        ARCHITECTURE='amd64'
    elif [[ $arch == i*86 ]]; then
        ARCHITECTURE='i386'
    elif  [[ $arch == arm* ]]; then
        ARCHITECTURE='arm64'
    fi

    echo -e "\n\nПо умолчанию выполняется повторная сборка локального репозитория для текущей версии дистрибутива, которая является $DISTROCODENAME на $ARCHITECTURE\n"
fi

rebuild_local_repo "$DISTROCODENAME" "$ARCHITECTURE"

Ссылки

https://wiki.debian.org/RepositoryFormat

http://ubuntuforums.org/showthread.php?t=1090731

https://help.ubuntu.com/community/CreateAuthenticatedRepository

Инструкции в @BigSack’s answer и официальном посте в вики Ubuntu не сработали для меня в Ubuntu 18.04, пока я не сделал эти два изменения:

  1. Сгенерируйте простой, несжатый файл Packages (при выполнении этого рабочий каталог должен находиться в том, где находятся все пакеты)

    cd /usr/local/mydebs
    dpkg-scanpackages -m . > Packages
    
  2. Добавьте следующую запись в /etc/apt/sources.list

    deb [trusted=yes] file:/usr/local/mydebs ./
    

Вы также можете настроить локальный сервер источников на nginx и reprepro:

  1. Установите пакеты debian

    sudo apt-get install reprepro nginx 
    
  2. создайте директории для reprepro и отредактируйте их

    sudo mkdir -p /srv/reprepro/ubuntu/{conf,dists,incoming,indices,logs,pool,project,tmp}
    
    $ cd /srv/reprepro/ubuntu/
    $ sudo chown -R `whoami` . # изменяет владельца репозитория на текущего пользователя
    

    /srv/reprepro/ubuntu/conf/distributions

    Origin: Ваше имя
    Label: Имя вашего репозитория
    Codename: karmic
    Architectures: i386 amd64 source
    Components: main
    Description: Описание создаваемого вами репозитория
    SignWith: YOUR-KEY-ID
    

    /srv/reprepro/ubuntu/conf/options

    ask-passphrase
    basedir .
    
  3. Включите его в reprepro, создайте его

    $ reprepro includedeb karmic /path/to/my-package_0.1-1.deb \
    # замените /path/to/my-package_0.1-1.deb на путь к вашему пакету
    
  4. Настройте nginx:

    /etc/nginx/sites-available/vhost-packages.conf

    server {
      listen 80;
      server_name packages.internal;
    
      access_log /var/log/nginx/packages-access.log;
      error_log /var/log/nginx/packages-error.log;
    
      location / {
        root /srv/reprepro;
        index index.html;
      }
    
      location ~ /(.*)/conf {
        deny all;
      }
    
      location ~ /(.*)/db {
        deny all;
      }
    }
    
  5. Оптимизируйте размер хэша:

    /etc/nginx/conf.d/server_names_hash_bucket_size.conf

    server_names_hash_bucket_size 64;
    

Ссылка на Руководство по установке

Существует несколько причин, по которым вы можете захотеть создать локальный репозиторий.
Первая — это то, что вы хотите сэкономить на пропускной способности, если у вас несколько
машин с Ubuntu, которые нужно обновлять. Например, если у вас есть 25 машин с Ubuntu,
которым необходимо обновление хотя бы раз в неделю, вы значительно
сэкономите пропускную способность, потому что сможете сделать все, кроме репозитория, локально.

Большинство организаций имеют хорошую пропускную способность для своих сетевых шлюзов,
но эта пропускная способность — драгоценный товар, который нужно использовать
разумно.

Многие организации по-прежнему имеют маршрутизаторы с ограничениями 10MB или 100MB на
шлюзе, но 1-гигабитные сетевые подключения внутри, так что пропускную способность можно
более эффективно использовать внутри. Вторая причина создания собственного
репозитория в том, что вы можете контролировать, какие приложения загружаются на
ваши внутренние машины с Ubuntu.

Вы можете удалить любые приложения, которые ваша организация не хочет использовать
в локальной сети, из репозитория, который обновляет машины.
Более того, вы можете создать тестовый компьютер и протестировать приложения и
версии, прежде чем разрешить их распространение по вашей сети, обеспечивая
безопасность и стабильность.

Сначала вы должны настроить зеркало, для этого просто нажмите
Ctrl+Alt+T на клавиатуре, чтобы открыть
терминал. Когда он открывается, выполните команду ниже.

apt-get install apt-mirror 

Как только вы настроите apt-mirror, вы можете начать загрузку
репозитория с помощью этой команды.

apt-mirror /etc/apt/mirror.list1

Читать дальше

1Источник:Создание репозитория Ubuntu

Чтобы создать оффлайн-локальный репозиторий
1. создайте директорию, доступную (по крайней мере, для root)

sudo mkdir /var/my-local-repo

  1. скопируйте все deb-файлы в эту директорию.
  2. сканируйте директорию

sudo dpkg-scanpackages /var/my-local-repo /dev/null >
/var/my-local-repo/Packages

  1. добавьте локальный репозиторий в sources

echo “deb file:/var/my-local-repo ./” > /tmp/my-local.list

sudo mv /tmp/my-local.list /etc/apt/sources.list.d/my-local.list

sudo apt-get update

Я попытался использовать apt-rdepends, как в выбранном ответе, но когда я пытался установить пакет из моего локального репозитория, он жаловался на отсутствие зависимостей.

apt-rdepends не перечислял некоторые зависимости моего пакета. Я подозреваю, что это связано с тем, что apt-cache show показывает несколько записей для него.

Вместо этого я использовал apt-cache depends, и это сработало:

Получение рекурсивного списка зависимостей

apt-cache depends <packagename> -i --recurse

-i: только важные зависимости
--recurse: рекурсивно

Преобразование в удобочитаемый список

  • Удаление символов & пробелов: | tr -d "|,<,>, "
  • Удаление Depends: & PreDepends: | sed -e 's/^Depends://g' | sed -e 's/^PreDepends://g'
  • Сортировка списка: | sort
  • Только уникальные значения: | uniq > list.txt

Полная команда:

apt-cache depends <packagename> -i --recurse | tr -d "|,<,>, " | sed -e \
's/^Depends://g' | sed -e 's/^PreDepends://g' | sort | uniq > list.txt

Скачать пакеты

for i in $( cat list.txt ); do apt-get download $i; done;

Сканируйте пакеты и превращайте их в Packages.gz

dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

Как создать репозиторий CD/DVD .ISO?

Следующий скрипт я создал (в Ubuntu 16.04 Xenial xerus) для создания .ISO архива .deb пакетов, которые я собирал со временем. Я привык сохранять копию каждого загруженного .deb пакета, установленного, системных обновлений (каждого .deb в /var/cache/apt/archives до их исчезновения, если они это сделали) и т.д., чтобы моя коллекция имела все пакеты, которые мне когда-либо понадобятся в установке версии Ubuntu, включая их зависимости.

Этот скрипт можно использовать для создания структуры каталогов и необходимых файлов, чтобы использовать файл .iso в качестве APT репозитория. Однако этот скрипт не создает ISO-образ, и могут использоваться инструменты, такие как xfburn. Более подробная помощь о том, что скопировать в корень ISO-образа, может быть получена в помощи скрипта.

Вы можете сохранить следующий скрипт как: deb_cache_pkg_to_repository_image_v0.1.sh.

#!/bin/bash

## v0.1

#  Этот скрипт не делает ничего, кроме как облегчает следующие несколько значительных шагов:
#  ##  Перейдите в директорию, где кэшируются архивы пакетов:
#  cd /usr/local/deb_packages
#  ##  Генерируйте файл 'Packages' и сжимайте его для `apt':
#  dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

declare __SCRIPT_NAME="${0##*/}"

# declare __SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
declare __SCRIPT_INITIAL_WDIR="${PWD}"

declare __SCRIPT_ACTION=""
declare -a __DIR_REPOSITORY
declare __DIR_BASE=""           ##  BASE_DIRECTORY
declare __LABEL_CODENAME=""     ##  UBUNTU_CODENAME
declare __LABEL_BINARY_DIR="binary-i386"
declare __LABEL_SOURCE_DIR="sources_archive"
declare __PACKAGE_DETAIL_FILE="Packages"
declare __PATH_DEFAULT_BASENAME="/tmp/prepare_apt_archive_for_ISO"
declare __DEFAULT_README=""

declare -i __INDEX=0

declare __DIR_TMP="/tmp/.${__SCRIPT_NAME%.sh}"
declare __TMP_PKG_DETAIL="${__DIR_TMP}/Packages"
declare __LOG_DPKG_SCANPKG_MESSAGES="${__DIR_TMP}/dpkg_scanpackages_message.log"
declare __TMP_PRELIM_DEB_LIST="${__DIR_TMP}/all_required_debs_path.list"
declare __TMP_SUFFICIENT_DEB_LIST="${__DIR_TMP}/sufficient_required_debs_path.list"
declare __LOG_SCANNED_DIRS="${__DIR_TMP}/dpkg_scanpackages_directories.log"

function _Msg_Err() {
    echo "${@}" >&2
}

function _Show_Help() {
    while read -r ; do
        echo "${REPLY}"
    done <<-__EOF
СИНТАКСИС:  ${__SCRIPT_NAME} [OPTIONS] ACTION DIRECTORY_1 DIRECTORY_2 ...
    где DIRECTORY_1 DIRECTORY_2 ... DIRECTORY_N - это директории, которые
    вы должны указать для сканирования .deb пакетов. например, '/var/cache/apt/archives/' или
    директории, в которых вы загрузили все эти.

ДЕЙСТВИЕ:
    подготовить
        Создает (временную) структуру директорий, копирует необходимые (из
        среди доступных, как сообщает \`dpkg-scanpackages') пакеты,
        и генерирует правильные файлы 'Packages' и 'Packages.gz' (содержащие
        детали пакетов). (Это команда, которую вы хотите использовать сначала; это
        сканирует перечисленные директории с помощью \`dpkg-scanpackages' и копирует
        необходимые в BASE_DIRECTORY и затем сканирует .deb файлы, чтобы
        подготовить файл 'Packages.xz'.)

    список
        Перечисляет имена пакетов, последние, которые нужно архивировать,
        игнорируя старые пакеты. (Получение "полного списка" здесь и для
        подготовки к резервному копированию зависит от того, содержат ли указанные 
        репозитории как DIRECTORY_1, DIRECTORY_2, DIRECTORY_N пакеты со всеми их
        зависимостями Debian. Этот скрипт не проверяет и не разрешает 
        никакие "недовольные зависимости" и предполагает, что полные репозитории 
        поддерживаются в DIRECTORY_N : ограничение этого скрипта.) 

ОПЦИИ:

    -D <BASE_DIRECTORY> | -
        Используйте это для указания базового <BASE_DIRECTORY>, где будет создана структура
        архива. например: /tmp/prepare_apt_archive_for_ISO, и убедитесь, что
        на дисковом объеме достаточно места, чтобы временно скопировать пакеты. 
        Путь по умолчанию '${__PATH_DEFAULT_BASENAME}'
        будет использоваться, если аргумент - это дефис.

        Эта структура не будет удалена скриптом и должна быть удалена вручную после завершения
        создания образа .iso из репозитория 'apt' читаемого.

        Содержимое этой директории должно находиться в корне DVD; содержимое
        в этой директории - это то, что вы импортируете, скажем, в проект DVD
        'Xfburn', и создаете ISO-образ.

    -l <UBUNTU_CODENAME>
        Метка (имя) для директории <UBUNTU_CODENAME>, которая будет
        помещена в корень ISO-образа. Смотрите СТРУКТУРУ АРХИВА для подробностей.

    -h
        Показать эту справку и выйти.

    Пример использования:
        $ ./deb_cache_pkg_to_repository_image_v0.1.sh -D - \\
            -l xenial_xubuntu1604 \\
            prepare /var/cache/apt/archives/ /opt/backup_deb_repo/

СТРУКТУРА АРХИВА:

    \$BASE_DIRECTORY/
    |
    +--  README.info
    |
    +--  \$UBUNTU_CODENAME/
         |
         +--  binary-i386/
         |    |
         |    +--  ( *.deb )
         |
         +--  Packages
         +--  Packages.gz
         |
         +--  sources_archive/
              |
              +--  ( источники пакетов в соответствующих директориях )

    В вышеприведенной структуре архива \$BASE_DIRECTORY может быть любой временной
    директории, которая будет содержать структуру, начинающуюся с директории \$UBUNTU_CODENAME,
    которая может быть кодовым именем версии Ubuntu, для которой
    пакеты (бинарные и исходники) архивируются или именем дистрибутива
    с номером версии. например:  "bionic" или "xubuntu16.04.4", которые будут находиться в
    корне ISO-образа, который может быть создан с помощью таких инструментов, как Xfburn.
    Если есть какие-либо документы README.info или другие подобные документы, их следует
    вручную скопировать в эту директорию.

    Этот скрипт будет "копировать" все необходимые архивы пакетов Debian (как
    определено с помощью \`dpkg-scanpackages' в директории 'binary/' или 'binary-i386/'.
    Правильные файлы 'Packages' и 'Packages.gz', содержащие детали
    каждого пакета в директории 'binary/', будут размещены рядом в директории
    \$UBUNTU_CODENAME. Также может быть создана поддиректория 'sources_archive/'
    для хранения архивов исходного кода приложений (и их зависимых источников) 
    в соответствующих директориях.

    Использование созданных таким образом CD/DVD носителей:
    АЛЬТЕРНАТИВА 01:
    Добавьте следующую строку в файл '/etc/apt/sources.list':
        deb file:/iso_mount_point ./
            где '/iso_mount_point' - это директория, где смонтирован ISO.
                ( Проверено еще раз, дважды. Это работает хорошо. )

        ## deb file:/${__LABEL_CODENAME} ${__LABEL_BINARY_DIR}
        ##     или
        ## deb file:/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR} ./
        ##     что работает (обратите внимание: первый метод был подтвержден как
        ##     работающий).

    АЛЬТЕРНАТИВА 02:
    Если созданный ISO совместим для использования с \`apt-cdrom', следующие
    шаги потребуются для использования архивированного репозитория на CD/DVD:
        01.  Запишите на CD/DVD; (в противном случае, если можете, смонтируйте образ ISO);
        02.  Отредактируйте файл '/etc/fstab', чтобы добавить следующую строку:
                /dev/cdrom /media/cdrom iso9660 ro 0 0
             где '/dev/cdrom' - это файловое устройство, '/media/cdrom' - точка монтирования
             'iso9660' файловая система CD (udf, если DVD), которую нужно монтировать
             с параметром монтирования 'ro', используйте нули для последних двух. (Иногда
             я мог указать путь к .iso образу вместо '/dev/cdrom' и предложить
             точку монтирования в любом пути вместо '/media/cdrom'. Для получения подробной информации
             по синтаксису проконсультируйтесь со справочной страницей для команды 
             \`mount' или файлом 'fstab'.
        03.  Запустите команду:
                apt-cdrom add
        04.  Теперь вы можете использовать \`apt' для обновления и установки с CD/DVD:
                apt-get update

    Примечание: После добавления репозитория (особенно на оффлайн-компьютере) и
    выполнения \`apt-get update' последующие запросы (в оффлайн системе)
    ограничивались пакетами, доступными в локальных репозиториях; это
    означает, что вы не сможете искать или просматривать описания каких-либо пакетов
    за пределами локально архивированных. (Найдите способ сделать резервную копию этих!!)

    АЛЬТЕРНАТИВА 03:
        Читайте решение на ссылке: https://askubuntu.com/a/1501055/212123
    АВТОР: Avadhesh J. Thapa

__EOF
}

function _Write_Default_Readme() {
    ##  Требуется: __DEFAULT_README , __DIR_BASE переменные должны быть инициализированы
    ##  и соответствующие файлы/директории должны быть созданы.
    ##  Убедитесь, что это выполнено, прежде чем вызывать эту функцию.

    if command touch "${__DEFAULT_README}" ; then
        > "${__DEFAULT_README}"
        while read -r ; do
            echo "${REPLY}" >> "${__DEFAULT_README}"
        done <<-__EOF
Используя этот носитель CD/DVD:
АЛЬТЕРНАТИВА 01:
Добавьте следующую строку в файл '/etc/apt/sources.list':
    deb file:/iso_mount_point ./
        где '/iso_mount_point' - это директория, где смонтирован ISO.
            ( Проверено снова, дважды. Это работает хорошо. )

    ## deb file:/${__LABEL_CODENAME} ${__LABEL_BINARY_DIR}
    ##     или
    ## deb file:/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR} ./
    ##     что работает (обратите внимание: первый метод был подтвержден как
    ##     работающий).

АЛЬТЕРНАТИВА 02:
Если созданный ISO совместим для использования с \`apt-cdrom', следующие
шаги потребуются для использования архивированного репозитория на CD/DVD:
    01.  Запишите на CD/DVD; (в противном случае, если можете, смонтируйте образ ISO);
    02.  Отредактируйте файл '/etc/fstab', чтобы добавить следующую строку:
            /dev/cdrom /media/cdrom iso9660 ro 0 0
         где '/dev/cdrom' - это файловое устройство, '/media/cdrom' - точка монтирования
         'iso9660' файловая система CD (udf, если DVD) для монтирования
         с параметром монтирования 'ro', используйте нули для последних двух. (Иногда
         я мог указать путь к .iso изображению вместо '/dev/cdrom' и предложить
         точку монтирования в любом пути вместо '/media/cdrom'. Для подробной информации 
         по синтаксису проконсультируйтесь со справочной страницей для
         команды `mount' или файла 'fstab'.
    03.  Запустите команду:
            apt-cdrom add
    04.  Теперь вы можете использовать \`apt' для обновления и установки с CD/DVD:
            apt-get update

    АЛЬТЕРНАТИВА 03:
            Читайте решение по ссылке: https://askubuntu.com/a/1501055/212123

__EOF
    fi
}

function _Scan_Packages_Temp() {
    ##  Вход: имя ссылки на массив, содержащий директории для сканирования
    ##  Выход: выводит несколько файлов, из которых основным требуемым файлом является
    ## "${__TMP_SUFFICIENT_DEB_LIST}", содержащий путь всех .deb пакетов,
    ## которые должны быть скопированы в директорию архивирования.

    declare -n deb_repos=${1}   ##  Ссылка на массив переменной, содержащей
                                ##  директории архивов Debian
    declare -i i=0

    ##  Очистите содержимое временного списка деталей пакетов и
    ##  журнала ошибок dpkg-scanpackages.
    > "${__TMP_PKG_DETAIL}"
    > "${__LOG_DPKG_SCANPKG_MESSAGES}"
    > "${__LOG_SCANNED_DIRS}"

    > "${__TMP_PRELIM_DEB_LIST}"
    > "${__TMP_SUFFICIENT_DEB_LIST}"

    echo "Пожалуйста, подождите. Сканирование..."
    echo
    for (( i = 0 ; i < ${#deb_repos[@]} ; i++ )) ; do
        echo "${deb_repos[i]}"
        echo "$( command date +%F_%T ) :: НАЧАЛО СКАНИРОВАНИЯ ДИРЕКТОРИИ ${deb_repos[i]}" >> "${__LOG_DPKG_SCANPKG_MESSAGES}"
        command dpkg-scanpackages "${deb_repos[i]}" /dev/null >> "${__TMP_PKG_DETAIL}" 2>> "${__LOG_DPKG_SCANPKG_MESSAGES}"
        echo "${deb_repos[i]}" >> "${__LOG_SCANNED_DIRS}"
    done

    command egrep '^Filename:[[:space:]]+.*\.deb' "${__TMP_PKG_DETAIL}" \
        | command sed -r 's,^Filename:[[:space:]]+,,;s,[[:space:]]+$,,' \
        > "${__TMP_PRELIM_DEB_LIST}"

    command awk -F"https://askubuntu.com/" ' { __PKG_PATH[$NF]=$0 ; __PKG_PATH_COUNT[$NF]+=1 } \
        END { \
            for ( __W in __PKG_PATH ) { \
                printf "%s\n" , __PKG_PATH[__W] ; \
                if ( __PKG_PATH_COUNT[__W] > 1 ) \
                    printf "Пакет \"%s\" встречается в %d местах, выбирая последнее.\n" , __W , __PKG_PATH_COUNT[__W] > "/dev/stderr" \
            } \
        }' "${__TMP_PRELIM_DEB_LIST}" > "${__TMP_SUFFICIENT_DEB_LIST}"
    echo
    echo "Сканирование завершено."
    echo
}

function _Prepare_Archivable_Disk_Repository(){
    ##  Вход:  Нет входных аргументов, но требуется файл __TMP_SUFFICIENT_DEB_LIST,
    ##          директории __DIR_BASE и __LABEL_CODENAME.
    ##  Выход: Создает дерево директорий и копирует .deb файлы, перечисленные в
    ##          файле __TMP_SUFFICIENT_DEB_LIST в директорию binary-i386/
    ##          в корне архивной структуры.

    declare tmp_word=""

    if [[ ! -e "${__TMP_SUFFICIENT_DEB_LIST}" ]] ; then
        _Msg_Err "Эта функция должна предшествоваться функцией _Scan_Packages_Temp()."
        return 1
    fi

    if [[ -z "${__DIR_BASE}" ]] ; then
        _Msg_Err "Используйте опцию -D, чтобы указать путь к основной директории для создания структуры архива. Смотрите \`${__SCRIPT_NAME} -h'."
        return 1
    fi

    if [[ -z "${__LABEL_CODENAME}" ]] ; then
        _Msg_Err "Используйте опцию -l, чтобы указать идентификацию используемой версии Ubuntu. Смотрите \`${__SCRIPT_NAME} -h'."
        return 1
    fi

    echo
    echo "Пожалуйста, убедитесь, что \"${__DIR_BASE}\""
    echo "очищено от ненужного. Любые ранее созданные"
    echo "файлы/директории в ней (за исключением некоторых) не будут удалены или изменены."
    echo "Любые излишки пакетов, для новых добавленных репозиториев, которые отсутствуют в этой"
    echo "структуре будут скопированы. Единственные файлы, которые будут изменены, это файлы 'Packages'"
    echo "и их сжатые формы (требуемые APT)."
    read -n1 -p"Вы хотите продолжить (копирование пакетов и генерирование файла 'Packages')? ( y/n ; по умолчанию n ): "
    echo
    if [[ "${REPLY}" != @(Y|y) ]] ; then
        return 1
    fi

    if [[ ! -d "${__DIR_BASE}" ]] ; then
        if ! command mkdir -p "${__DIR_BASE}"  ; then
            _Msg_Err "Не удалось создать директорию \"${__DIR_BASE}\"."
            return 1
        else
            echo "Создана директория \"${__DIR_BASE}\"."
        fi
    fi

    for tmp_word in \
    "${__DIR_BASE}/${__LABEL_CODENAME}" \
    "${__DIR_BASE}/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}" \
    "${__DIR_BASE}/${__LABEL_CODENAME}/${__LABEL_SOURCE_DIR}" ; do
        if test ! -d "${tmp_word}" ; then
            if command mkdir -p "${tmp_word}" ; then
                echo "Создана директория \"${tmp_word}\"."
            else
                _Msg_Err "Не удалось создать директорию \"${REPLY}\"."
                return 1
            fi
        fi
    done

    ##  README.info должен быть помещен в корень ISO-образа.
    __DEFAULT_README="${__DIR_BASE}/README.info"
    _Write_Default_Readme

    echo
    echo "Копирование необходимых .deb файлов в '${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}/'"
    ## rsync --stats -h --progress --times --perms --group --owner --ignore-existing --verbose --files-from="${__TMP_SUFFICIENT_DEB_LIST}" "${__DIR_BASE}/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}/"

    while read -r ; do
        command cp --preserve=all --no-clobber --verbose -t "${__DIR_BASE}/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}/" "${REPLY}"
    done <&& echo "Копирование завершено." || {
        _Msg_Err "Произошла какая-то ошибка."
        return 1
    }

    ##  Теперь начните создавать файл "Packages" для `apt':
    ##  СКАНИРОВАНИЕ БУДЕТ ПРОИЗВОДИТЬСЯ С УРОВНЯ КОРНЯ ДЛЯ ISO-ОБРАЗА:
    ## cd "${__DIR_BASE}/${__LABEL_CODENAME}/"  ##  выбирая, вместо этого, чтобы сканировать с корня ISO
    cd "${__DIR_BASE}"
    echo "$( command date +%F_%T ) :: НАЧАЛО СКАНИРОВАНИЯ АРХИВИРОВАННОЙ БИНАРНОЙ ДИРЕКТОРИИ ${deb_repos[i]}" >> "${__LOG_DPKG_SCANPKG_MESSAGES}"
    echo
    echo "Выполнение \`dpkg-scanpackages' и генерация файла 'Packages'..."
    # command dpkg-scanpackages "${__LABEL_BINARY_DIR}" /dev/null > "${__PACKAGE_DETAIL_FILE}" 
    command dpkg-scanpackages "${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}" /dev/null > "${__PACKAGE_DETAIL_FILE}" 
    command gzip -c "${__PACKAGE_DETAIL_FILE}" > "${__PACKAGE_DETAIL_FILE}.gz"
    command xz --suffix=.xz -kfz "${__PACKAGE_DETAIL_FILE}"

    if [[ -e "${__PACKAGE_DETAIL_FILE}".gz && -e "${__PACKAGE_DETAIL_FILE}".xz ]] ; then
        command rm "${__PACKAGE_DETAIL_FILE}"
    fi
    cd "${__SCRIPT_INITIAL_WDIR}"
}

if [[ ${#} -eq 0 ]] ; then
    echo "Смотрите \`${__SCRIPT_NAME} -h'" >&2
    exit 1
fi

declare __SCRIPT_OPTS=""
##  Если строка опций начинается с двоеточия (:), используется тихая отчетность об ошибках.

##  Встроенный `getopts` возвращает значение больше нуля при встрече
##  конца опции и предполагает завершение синтаксического анализа опции, что может быть не всегда случай. 
##  Конец опции - это любая недопустимая опция или свободный операнд.
##  Это можно явно указать с помощью -- на командной строке.
##  Совместно с чтением флагов и аргументов типа опции с их
##  аргументами, getopts также смещает позиционные параметры; прочитанные опции
##  и аргументы вытаскиваются до конца опций. Индекс OPTIND, который хранит
##  индекс следующих параметров командной строки, инициализируется на 1 при каждом новом
##  вызове скрипта, увеличивается для каждого вызова `getopts`, но не
##  сбрасывается и должен быть сброшен вручную (если требуется: повторная обработка
##  позиционных параметров). При встрече конца опции OPTIND устанавливается на позицию 
##  первого непараметрического аргумента, а __SCRIPT_OPTS устанавливается на ?.
while getopts ":D:l:h" __SCRIPT_OPTS ; do
    case "${__SCRIPT_OPTS}" in
        D)
            if [[ "${OPTARG}" == "-" ]] ; then
                __DIR_BASE="${__PATH_DEFAULT_BASENAME%/}"   ##  также удаляет любые завершающие слэши
            else
                __DIR_BASE="${OPTARG}"      ##  также удаляет любые завершающие слэши
            fi
            ;;
        l)
            __LABEL_CODENAME="${OPTARG}"
            if [[ ! "${__LABEL_CODENAME}" =~ ^[^/]+$ ]] ; then
                _Msg_Err "Ошибка. Указанное имя с -l не должно содержать символ пути."
                exit 1
            fi
            ;;
        h)  _Show_Help ; exit 0 ;;
    esac

    ##  Тихая отчетность об ошибках: для ошибок "недопустимая опция" __SCRIPT_OPTS
    ##  устанавливается на знак вопроса (?). Для ошибок "аргумент для опции не найден"
    ##  __SCRIPT_OPTS устанавливается на двоеточие (:). В обоих типах ошибок
    ##  символ опции помещается в переменную OPTARG shell. [ Это
    ##  не должным образом задокументировано в мануале bash Ubuntu 16.04.4 LTS. ]
    if [[ "${__SCRIPT_OPTS}" == "?" ]] ; then
        echo "Опция \"-${OPTARG}\" не распознана."
        echo "Попробуйте \`${0##*/} -h' для справки." >&2
        exit ${__ERR_GENERAL}
    fi
    if [[ "${__SCRIPT_OPTS}" == ":" ]] ; then
        echo "Опция -${OPTARG} требует аргумент."
        echo "Попробуйте \`${0##*/} -h' для справки." >&2
        exit ${__ERR_GENERAL}
    fi
done

##  Ручное смещение позиционных параметров может быть не требуется при
##  `getopts`, так как встроенный делает это сам. 
shift $(( ${OPTIND} - 1 ))
##  Не забывайте сбрасывать OPTIND перед обработкой следующего набора позиционных
##  параметров.
# OPTIND=1

##  Теперь все, что остается в $@, должно быть непараметрическими аргументами. (Помните, что
##  getopts прекратит искать больше опций при первом непараметрическом аргументе, который она встретит.

##  Первый из непараметрических аргументов должен быть спецификацией действия скрипта
##  а остальные все директории (репозитории) пакетов Debian
##  приложений и их зависимостей.

##  Получение действия:
__SCRIPT_ACTION="${1}"
shift || {
    _Msg_Err "Действие скрипта не указано. Это должно быть первым непараметрическим аргументом. Смотрите \`${__SCRIPT_NAME} -h'."
    exit 1
}

##  Присвоить остальное как директории репозитория:
__DIR_REPOSITORY=( "$@" )

##  Достигнув здесь, содержимое __SCRIPT_ACTION и __DIR_REPOSITORY является
##  обязательным:
case "${__SCRIPT_ACTION}" in
    prepare) ;;
    list) ;;
    *)
        _Msg_Err "Ошибка. Первый непараметрический аргумент должен указывать действие. \"${__SCRIPT_ACTION}\" не является допустимым действием."
        exit 1
        ;;
esac

if [[ ! -d "${__DIR_TMP}" ]] ; then
    mkdir "${__DIR_TMP}"
fi

##  Проверьте допустимость __DIR_REPOSITORY
if [[ ${#__DIR_REPOSITORY[@]} -eq 0 ]] ; then
    _Msg_Err "Ошибка. Директория репозитория, содержащая пакеты Debian, которые необходимо архивировать, должна быть указана."
    exit 1
else
    for (( __INDEX = 0 ; __INDEX < ${#__DIR_REPOSITORY[@]} ; __INDEX++ )) ; do
        if [[ ! -d "${__DIR_REPOSITORY[${__INDEX}]}" ]] ; then
            _Msg_Err "Директория \"${__DIR_REPOSITORY[${__INDEX}]}\" не существует. (Все опции должны предшествовать непараметрическим операндам.)."
            exit 1
        fi
    done
fi

##  Код, чтобы обрабатывать команды:
case "${__SCRIPT_ACTION}" in
    list)
        if [[ -e "${__TMP_SUFFICIENT_DEB_LIST}" ]] ; then
            echo "Существует список из предыдущего сканирования. Следующие директории были просканированы:"
            command cat "${__LOG_SCANNED_DIRS}"
            echo
            echo "Выберите n, чтобы увидеть предыдущий список."
            read -n1 -p"Выполнить новое сканирование ( y/n ; по умолчанию n ): "
            echo
            if [[ "${REPLY}" == @(Y|y) ]] ; then
                _Scan_Packages_Temp __DIR_REPOSITORY
                echo "Следующие пакеты должны быть достаточными для архивации:"
                command cat "${__TMP_SUFFICIENT_DEB_LIST}"
                echo
                echo "Необходимое свободное пространство: $( echo "scale=6; $( command cat "${__TMP_SUFFICIENT_DEB_LIST}" | command xargs -I{} du -b {} | command sed -r 's,^([[:digit:]]+)[[:space:]]+.*,\1,' | command paste -sd+ | command bc ) / 1024 ^ 3" | command bc ) GiB"
            else
                echo "Следующие пакеты должны быть достаточными для архивации:"
                command cat "${__TMP_SUFFICIENT_DEB_LIST}"
                echo
                echo "Необходимое свободное пространство: $( echo "scale=6; $( command cat "${__TMP_SUFFICIENT_DEB_LIST}" | command xargs -I{} du -b {} | command sed -r 's,^([[:digit:]]+)[[:space:]]+.*,\1,' | command paste -sd+ | command bc ) / 1024 ^ 3" | command bc ) GiB"
            fi
            echo
        fi
        ;;
    prepare)
        if [[ -z "${__DIR_BASE}" ]] ; then
            _Msg_Err "Используйте опцию -D, чтобы указать путь к основной директории для создания структуры архива. Смотрите \`${__SCRIPT_NAME} -h'."
            exit 1
        fi

        if [[ -z "${__LABEL_CODENAME}" ]] ; then
            _Msg_Err "Используйте опцию -l, чтобы указать идентификацию используемой версии Ubuntu. Смотрите \`${__SCRIPT_NAME} -h'."
            exit 1
        fi

        if [[ -e "${__TMP_SUFFICIENT_DEB_LIST}" ]] ; then
            echo "Существует список из предыдущего сканирования. Следующие директории были просканированы:"
            command cat "${__LOG_SCANNED_DIRS}"
            echo
            echo "Выберите Y, если вы добавили больше директорий сканирования в командной строке. (Если"
            echo "это совершенно новый список, вам СЛЕДУЕТ очистить содержимое "
            echo "\"${__DIR_BASE}/${__LABEL_CODENAME}/${__LABEL_BINARY_DIR}/\" директории;"
            echo "в этом случае выберите E, очистите директорию и начните заново.)"
            echo
            read -n1 -p"Выполнить новое сканирование ( y/n/e/* ; по умолчанию e ; E и любой другой выходят ): "
            echo
            if [[ "${REPLY}" == @(Y|y) ]] ; then
                _Scan_Packages_Temp __DIR_REPOSITORY
                # echo "Следующее — это список достаточных пакетов для архивации:"
                # command cat "${__TMP_SUFFICIENT_DEB_LIST}"
            elif [[ "${REPLY}" == @(N|n) ]] ; then
                true    ##  no-op
            else
                exit 0
            fi
        else
            _Scan_Packages_Temp __DIR_REPOSITORY
        fi
        echo
        echo "Общий размер .deb пакетов для копирования: $( echo "scale=6; $( command cat "${__TMP_SUFFICIENT_DEB_LIST}" | command xargs -I{} du -b {} | command sed -r 's,^([[:digit:]]+)[[:space:]]+.*,\1,' | command paste -sd+ | command bc ) / 1024 ^ 3" | command bc ) GiB."
        echo "Убедитесь, что у вас достаточно места на диске для этого."
        echo
        _Prepare_Archivable_Disk_Repository
        ;;
esac
## Конец кодов скрипта.

Шаги для создания файла образа .ISO архива с использованием xfburn:

  • Запустите приложение xfburn.
  • Выберите Файлы -> Новая составная часть данных
  • Нажмите кнопку Добавить, перейдите в BASE_DIRECTORY, выберите директорию репозитория, Packages.gz, Packages.xz и README.info, а затем внизу диалогового окна нажмите кнопку Добавить.
  • В нижней части окна подходящий размер и тип диска CD/DVD будут автоматически выбраны. Я вручную указал DVD на 4.3 ГБ.
  • Нажмите Продолжить запись, появится диалоговое окно записи композиции. В опциях установите флажок на Создать только ISO, а затем нажмите кнопку Записать композицию.

Пример – Создание репозитория CD/DVD с boot-repair и несколькими другими приложениями:

cd /tmp ; mkdir download_liveCD_essential_packages
cd download_liveCD_essential_packages
sudo add-apt-repository ppa:yannubuntu/boot-repair && sudo apt update
apt-get -y --print-uris install boot-repair clamav curl dos2unix extundelete fdupes foremost gnome-disk-utility gsmartcontrol iftop iotop konsole linkchecker links2 lynx nmap p7zip samba synaptic traceroute tree unrar vim whois | grep -o '\'http.*\' | tr "\'" " " >> packages_download.list
wget -i packages_download.list -c
wget -i packages_download.list -c  ## подтвердите все загрузки
bash ~/deb_cache_pkg_to_repository_image_v0.1.sh -D - -l lunar prepare /tmp/download_liveCD_essential_packages/  ## Предполагаем, что скрипт в домашнем каталоге
cd /tmp/prepare_apt_archive_for_ISO/
ls ## Это файлы и директории, которые вам нужно скопировать в корень вашего .iso файла. Далее используйте Xfburn или другие приложения для создания .iso файла

Теперь вы можете скопировать необходимые содержимое в корень каталога ISO, используя графические приложения, такие как xfburn (рекомендуется) или с помощью следующей команды:

genisoimage -allow-leading-dots -allow-lowercase -allow-multidot -iso-level 4 -max-iso9660-filenames -o /tmp/genisoimage__Ubuntu23.04_repo.iso -V "Ubuntu23.04_Repo" -R -uid 1000 -no-iso-translate /tmp/prepare_apt_archive_for_ISO/

или просто,

genisoimage -o /tmp/genisoimage__Ubuntu23.04_repo.iso -V "Ubuntu23.04_Repo" -R /tmp/prepare_apt_archive_for_ISO/

(Используя формат Rock Ridge в genisoimage. Оба этих команд, похоже, работают для создания образа CD, однако для больших файлов, которые не помещаются в образ CD, вы также должны использовать инструменты, такие как xfburn.)


Ссылки:

Посмотрите OpenRepo (https://github.com/openkilt/openrepo)

Этот проект с открытым исходным кодом работает как веб-сервер. Вы можете загружать пакеты на него, и он будет размещать их в вашей локальной сети для других серверов, чтобы они могли обновляться.

Ответ или решение

Создание локального репозитория APT на вашем локальном сервере — это отличный способ экономить интернет-трафик и управлять программным обеспечением для нескольких компьютеров в вашей локальной сети. В этом руководстве я подробно опишу необходимые шаги для настройки собственного APT-репозитория.

Шаг 1: Установка dpkg-dev

Для начала необходимо установить пакет dpkg-dev, который содержит утилиты для работы с пакетами Debian. Введите в терминале следующую команду:

sudo apt-get install dpkg-dev

Шаг 2: Создание каталога для пакетов

Создайте каталог, в который вы будете помещать все .deb файлы. В данном примере мы используем /usr/local/mydebs:

sudo mkdir -p /usr/local/mydebs

Перемещение загруженных пакетов

Загруженные пакеты обычно находятся в каталоге /var/cache/apt/archives. Переместите необходимые .deb файлы в каталог, который вы только что создали:

sudo cp /var/cache/apt/archives/*.deb /usr/local/mydebs/

Шаг 3: Сканирование пакетов и создание каталога

Создайте простой сценарий, который будет сканировать каталог с пакетами и генерировать файл Packages.gz, использующийся APT. Создайте файл сценария, например, update-mydebs:

echo '#! /bin/bash' > ~/bin/update-mydebs
echo 'cd /usr/local/mydebs' >> ~/bin/update-mydebs
echo 'dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz' >> ~/bin/update-mydebs

Затем сделайте сценарий исполняемым:

chmod u+x ~/bin/update-mydebs

Шаг 4: Обновление файла sources.list

Теперь вам необходимо добавить новый репозиторий в ваш файл /etc/apt/sources.list. Откройте его с помощью любого текстового редактора и добавьте следующую строку:

deb file:/usr/local/mydebs ./

Для автоматического обновления списка пакетов выполните следующие команды:

sudo update-mydebs
sudo apt-get update

Теперь вы можете использовать команды apt-get, apt-cache и другие утилиты APT для установки программного обеспечения из вашего локального репозитория.

Дополнительные опции: использование Apache для доступа по LAN

Если вы хотите, чтобы ваш репозиторий был доступен другим компьютерам в локальной сети, вам следует рассмотреть возможность использования веб-сервера Apache для хостинга ваших пакетов:

  1. Установка Apache:

    sudo apt-get install apache2
  2. Создание директории для репозитория:

    sudo mkdir -p /var/www/debs/amd64
  3. Копирование .deb файлов в соответствующие директории:

    sudo cp /usr/local/mydebs/*.deb /var/www/debs/amd64/
  4. Создание файла Packages.gz:

    cd /var/www/debs/amd64
    dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
  5. Добавление нового источника в файл sources.list на клиентах:
    Убедитесь, что вы добавили на клиентских машинах следующую строку:

    deb http://<ваш_IP_адрес>/debs/ amd64/

Создание аутентифицированного репозитория

Если безопасность является приоритетом, вы можете создать аутентифицированный репозиторий, используя GPG-ключи для подписки пакетов. Это обеспечит защиту от потенциальной подмены пакетов.

  1. Создайте GPG-ключ и экспортируйте его.
  2. Добавьте в файл Release информацию о ключе и подпишите его.

Рекомендации

  • Проверка зависимостей: Перед добавлением новых пакетов убедитесь, что все зависимости удовлетворены, иначе установка может завершиться неудачей.
  • Регулярное обновление: Настройте регулярные задачи для обновления вашего локального репозитория с использованием cron или другого планировщика задач, чтобы поддерживать его в актуальном состоянии.

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

Оцените материал
Добавить комментарий

Капча загружается...