SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Как исправить ошибку дублирования источников в apt

Ошибка apt о многократной настройке целевого репозитория возникает при конфликте файлов .list и .sources. Удалите дубликат, чтобы восстановить корректную работу менеджера пакетов.

Что означает ошибка дублирования источников apt

Ошибка дублирования источников apt означает, что один и тот же репозиторий объявлен дважды в разных файлах, и APT (advanced package tool) обнаружил обе копии. В Ubuntu 24.04 и более новых версиях это почти всегда происходит из-за того, что сторонний скрипт установки создал старый однострочный файл .list, в то время как файл формата deb822 .sources для того же репозитория уже присутствовал на диске. Никаких повреждений нет, и пакеты находятся в безопасности. Удалите одно из двух объявлений, и сообщение исчезнет.

Вот строка, которую пользователи вставляют в поисковую строку:

W: Target Packages (stable/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/docker.list:1 and /etc/apt/sources.list.d/docker.sources:1

Читайте её с конца. Два файла, каждый с указанием номера строки, объявляют одно и то же. Target Packages — это индекс, который apt загружает, чтобы узнать, какие пакеты предлагает репозиторий, а stable/binary-amd64/Packages указывает компонент (stable) и архитектуру (amd64), которые охватывает этот индекс. Таким образом, apt сообщает вам, что индекс amd64 для компонента stable настроен в docker.list в строке 1, а также в docker.sources в строке 1.

В apt 3.0 и более новых версиях, что соответствует Ubuntu 25.04 и Debian 13, то же самое сообщение начинается с Warning: вместо W:. Текст после префикса остается прежним.

Это предупреждение — легкий случай. apt объединяет два объявления, и обновление выполняется, так как оба описания относятся к одному архиву с одним и тем же ключом. Тяжелый случай блокирует всё:

E: Conflicting values set for option Signed-By regarding source https://download.docker.com/linux/ubuntu/ noble: /usr/share/keyrings/docker-archive-keyring.gpg != /etc/apt/keyrings/docker.asc
E: The list of sources could not be read.

В этом случае apt отказывается работать, так как два объявления указывают разные ключи подписи для одного архива. apt объединит два идентичных объявления, но не будет выбирать между двумя значениями Signed-By, так как выбор неверного значения приведет к проверке подписей пакетов ключом, которым владелец архива никогда не подписывал данные. Поэтому apt не считывает источники вовсе. apt update и apt install будут выдавать ошибку с этими двумя строками до тех пор, пока вы не отредактируете файлы вручную.

Как возникает дубликат

Эти два формата хранятся в разных файлах с разными расширениями, поэтому на уровне файловой системы нет препятствий для их одновременного существования. apt обнаруживает конфликт на позднем этапе, когда разворачивает каждый файл источников в список целей для загрузки индексов. До этого момента docker.list и docker.sources являются двумя независимыми файлами.

К появлению этой пары приводят четыре типичных события:

  • Скрипт установки от поставщика или команда, скопированная из старой инструкции, создает файл /etc/apt/sources.list.d/vendor.list с записью tee.
  • Позднее пакет от того же поставщика выпускает /etc/apt/sources.list.d/vendor.sources и устанавливает его в систему.
  • add-apt-repository в Ubuntu 24.04 и более новых версиях создает файлы .sources в формате deb822, поэтому PPA (personal package archive), который вы ранее добавили вручную как .list, возвращается в виде .sources.
  • Обновление дистрибутива перезаписало системные источники в формат deb822, оставив ваш файл .list, созданный вручную, без изменений.

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

Сравнение двух форматов

Старый формат предполагает одну строку на репозиторий, где каждая часть имеет строго определенную позицию.

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable

Порядок фиксирован: тип (deb для бинарных пакетов, deb-src для исходных кодов), затем параметры в квадратных скобках, далее URI (идентификатор ресурса) архива, дистрибутив (suite) и один или несколько компонентов. Поскольку значение определяется позицией, лишний пробел меняет то, как apt считывает строку.

Формат deb822 описывает то же самое в виде блока именованных полей. Название происходит от RFC 822 — стиля заголовков электронной почты, который Debian уже использует для файлов управления пакетами.

Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc

Тот же репозиторий, тот же ключ, ничего лишнего. Соответствие прямое: deb становится Types, адрес архива — URIs, дистрибутив — Suites, компоненты — Components, а каждый параметр в скобках превращается в отдельное поле: signed-by= становится Signed-By:, а arch= — Architectures:.

Названия всех полей даны во множественном числе, так как каждое поле принимает список значений, разделенных пробелами. Одно поле Suites: noble noble-updates noble-backports в блоке заменяет три отдельные строки deb. Пустая строка завершает блок, поэтому один файл .sources может содержать настройки нескольких репозиториев. Формат deb822 также поддерживает параметры, с которыми однострочный формат справляется плохо: Enabled: no для отключения репозитория, Trusted, Check-Valid-Until, а также встроенный ключ, вставленный прямо в Signed-By, где каждая строка имеет отступ в один пробел, а пустые строки обозначаются одной точкой.

Расположение файлов конфигурации

  • /etc/apt/sources.list: исходный единый файл. В Ubuntu 24.04 и более новых версиях он обычно пуст или содержит только комментарий, указывающий на новое расположение.
  • /etc/apt/sources.list.d/*.list: записи в одну строку, обычно по одному файлу на каждый репозиторий.
  • /etc/apt/sources.list.d/*.sources: блоки в формате deb822. В Ubuntu 24.04 и более новых версиях здесь хранятся репозитории самого дистрибутива, в файле ubuntu.sources.
  • /etc/apt/keyrings/: место для ключей, которые вы добавляете самостоятельно. В /usr/share/keyrings/ хранятся ключи, установленные из пакетов.

apt считывает только файлы с расширениями .list или .sources. Имя файла может содержать буквы, цифры, знаки подчёркивания, дефисы и точки. Файлы с любыми другими расширениями игнорируются с выводом уведомления, что важно для описанного ниже исправления.

Поиск дублирующейся пары

Начните с вывода списка файлов в директории:

ls -l /etc/apt/sources.list.d/
-rw-r--r-- 1 root root  195 Aug  3 09:12 docker.list
-rw-r--r-- 1 root root  254 Aug  9 14:40 docker.sources
-rw-r--r-- 1 root root 2683 Jun 11 08:02 ubuntu.sources

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

grep -rn -E '^(deb |deb-src |Types:|URIs:|Suites:|Signed-By:)' /etc/apt/sources.list /etc/apt/sources.list.d/
/etc/apt/sources.list.d/docker.list:1:deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu noble stable
/etc/apt/sources.list.d/docker.sources:1:Types: deb
/etc/apt/sources.list.d/docker.sources:2:URIs: https://download.docker.com/linux/ubuntu
/etc/apt/sources.list.d/docker.sources:3:Suites: noble
/etc/apt/sources.list.d/docker.sources:6:Signed-By: /etc/apt/keyrings/docker.asc

Эта пара — две записи с одинаковым хостом и одинаковым набором (suite). Обе указывают на https://download.docker.com/linux/ubuntu и набор noble, поэтому они представляют собой один и тот же репозиторий, записанный дважды. Их пути Signed-By также не совпадают, что и вызывает ошибку Conflicting values, показанную ранее.

Используйте grep вместо команды apt для этого шага. Поскольку apt останавливается при возникновении конфликта, он не может вывести список ваших источников, поэтому apt-cache policy выводит ту же ошибку вместо нужного вам ответа.

Исправление: оставьте файл deb822, удалите устаревший

Оставьте файл .sources. Это формат, в который сейчас записывает данные инструментарий apt, и именно к нему переходят Debian и Ubuntu. Прежде чем что-либо удалять, проверьте, какой из двух путей к ключу существует на диске:

ls -l /etc/apt/keyrings/ /usr/share/keyrings/ | grep -i docker
-rw-r--r-- 1 root root 4813 Aug  9 14:40 docker.asc

Присутствует только /etc/apt/keyrings/docker.asc, поэтому файл deb822 содержит актуальную информацию, а файл .list указывает на ключ, который был удален. Если окажется, что файл, который вы планируете оставить, ссылается на отсутствующий ключ, сначала скопируйте в него рабочий путь, а затем удалите другой файл.

Переместите устаревший файл из директории, вместо того чтобы сразу удалять его:

sudo mkdir -p /root/apt-sources-backup
sudo mv /etc/apt/sources.list.d/docker.list /root/apt-sources-backup/
sudo apt update

Переименование в docker.list.bak с оставлением на месте также сработает, так как apt игнорирует неизвестные расширения, но тогда при каждом запуске apt будет выводиться следующее:

N: Ignoring file 'docker.list.bak' in directory '/etc/apt/sources.list.d/' as it has an invalid filename extension

Перемещение файла в другое место избавит вас от этого уведомления и сохранит резервную копию. Корректный файл apt update после этого выглядит так, без строк, ссылающихся на два файла:

Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 https://download.docker.com/linux/ubuntu noble InRelease [48.8 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 175 kB in 1s (146 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

Теперь убедитесь, что репозиторий функционирует после внесенных изменений:

apt-cache policy | grep download.docker.com
 500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     origin download.docker.com

Если документация поставщика все еще предполагает использование однострочного файла, вы можете оставить его и удалить файл .sources. Решение принимается на основе одного правила: только один файл может объявлять конкретный архив, дистрибутив (suite) и компонент. Допускаются отдельные записи для разных компонентов или архитектур одного и того же архива, но такие параметры, как Signed-By, применяются к каждой записи с одинаковыми URI и дистрибутивом, поэтому они должны совпадать во всех записях.

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

Сбой в соседнем репозитории выглядит иначе, но имеет ту же причину: сторонний источник, который apt не может использовать. Первый вариант — отсутствие ключа:

Err:5 https://download.docker.com/linux/ubuntu noble InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.

У apt нет подходящего ключа для проверки подписи файла InRelease в архиве. Либо Signed-By указывает на файл, который не является рабочим ключом, либо это поле отсутствует, и ни в одной из связок ключей, которым доверяет apt, нет ключа, которым подписан архив. В этом случае apt отбрасывает весь репозиторий целиком, чтобы не доверять спискам пакетов, которые невозможно проверить. Проверьте сам файл ключа:

ls -l /etc/apt/keyrings/docker.asc
gpg --show-keys /etc/apt/keyrings/docker.asc

Рабочий ключ выводит строку pub с идентификатором ключа и строку uid с указанием поставщика. gpg: no valid OpenPGP data found. означает, что файл вообще не является ключом; обычно это происходит, если при загрузке была сохранена страница с ошибкой из-за того, что URL ключа изменился. Загрузите ключ заново, проверьте файл, а затем выполните apt update.

Второй вариант возникает после обновления релиза:

Err:6 https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky InRelease
  404  Not Found [IP: 10.0.0.80 443]
E: The repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu plucky Release' does not have a Release file.

В PPA нет данных для этого дистрибутива, поэтому путь на сервере отсутствует, и запрос возвращает 404. Остальные репозитории продолжают обновляться, а уже установленные пакеты остаются нетронутыми. Однако команда завершается с ненулевым кодом, поэтому любой скрипт, проверяющий статус выполнения apt update, теперь будет сообщать об ошибке при каждом запуске. Именно поэтому стоит удалять нерабочие источники на серверах, где настроены автоматические обновления безопасности: в ежедневном потоке уведомлений легко пропустить реальный сбой. Скрипты установки от поставщиков часто сталкиваются с обеими этими проблемами, поэтому большинство ошибок при установке Tailscale в Ubuntu сводятся к тому, что скрипт не записал связку ключей или указал кодовое имя релиза, которого нет в архиве.

Отключение одного источника без нарушения работы остальных

Для файла в формате deb822 добавьте одно поле в секцию и сохраните изменения:

Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu
Suites: plucky
Components: main
Signed-By: /etc/apt/keyrings/ondrej-php.asc
Enabled: no

Руководство apt рекомендует этот способ вместо комментирования каждой строки секции, так как его проще отменить. Для однострочного файла добавьте # в начало строки. Для обоих форматов также подходит перемещение файла из /etc/apt/sources.list.d/; этот вариант следует выбирать, если репозиторий больше не будет использоваться.

Снова выполните sudo apt update. Блок Err: для этого репозитория исчезнет, а код завершения вернется к 0, что можно проверить с помощью echo $? на следующей строке.

Никогда не исправляйте поврежденный источник с помощью sudo rm /etc/apt/sources.list.d/*. В Ubuntu 24.04 и более новых версиях это удаляет ubuntu.sources, где хранятся собственные репозитории дистрибутива, из-за чего apt остается без списков пакетов и сообщает E: Unable to locate package curl для программ, которые очевидно существуют. Если вы уже выполнили эту команду, восстановите файл:

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Сохраните его как /etc/apt/sources.list.d/ubuntu.sources, заменив noble на имя вашего релиза из lsb_release -cs, а затем выполните sudo apt update.

Преобразование устаревших файлов .list в формат deb822

Начиная с октября 2026 года, apt версии 3.0 и новее включает конвертер для этой задачи. Он присутствует в Debian 13, Ubuntu 25.04 и всех последующих выпусках, включая 26.04. Проверьте версию, а затем выполните команду:

apt --version
sudo apt modernize-sources

Она преобразует однострочные файлы в каталоге /etc/apt/sources.list.d/ в файлы формата deb822 .sources. Изучите вывод команды, затем самостоятельно просмотрите содержимое каталога и выполните apt update, прежде чем доверять результату. В Ubuntu 24.04 поставляется более старая версия apt без этой подкоманды, поэтому там команда вернет E: Invalid operation modernize-sources. В этом выпуске выполняйте преобразование вручную, используя приведенное выше сопоставление полей.

На данный момент преобразование является необязательным, так как apt по-прежнему поддерживает оба формата. Это стоит сделать на сервере, который вы планируете использовать долго, поскольку add-apt-repository и системные файлы дистрибутива уже используют deb822, а этот формат проще читать и искать. Однако преобразование не предотвращает повторное появление дубликатов такого типа. Некоторые инструменты все еще создают однострочные файлы источников: например, cloud-init записывает /etc/apt/sources.list вместо файла deb822, если предоставленная ему конфигурация не соответствует формату deb822, а скопированные команды установки по-прежнему создают tee .list файлы. Повторяйте проверку grep, описанную выше, каждый раз, когда один из этих инструментов вносил изменения в систему.

Поддерживайте порядок в сторонних репозиториях на сервере

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

  • Добавляйте сторонний репозиторий только в том случае, если стандартного пакета из дистрибутива недостаточно. Для обычного стека LAMP на Ubuntu 24.04 сторонние источники не нужны: в архивах Ubuntu есть все необходимые пакеты, которые получают обновления безопасности на протяжении всего жизненного цикла релиза.
  • Храните ключи в /etc/apt/keyrings/, по одному файлу на каждого поставщика, с правами доступа 644. Загрузку выполняет непривилегированный пользователь _apt, которому нужен доступ к чтению ключа, поэтому файл, доступный только для root, вызовет ошибку прав доступа при каждом обращении к репозиторию.
  • Указывайте путь к конкретному файлу в Signed-By для каждой записи. Ключ, помещенный в /etc/apt/trusted.gpg или /etc/apt/trusted.gpg.d/, считается доверенным для всех репозиториев в системе, что означает, что ключ поставщика, добавленный много лет назад, может подтвердить подлинность пакетов из любого источника.
  • Перед обновлением релиза изучите свои источники и убедитесь, что каждый поставщик уже выпускает пакеты для версии, на которую вы переходите.

Ключ в старой глобальной связке ключей будет вызывать предупреждение при каждом обновлении:

W: https://download.docker.com/linux/ubuntu/dists/noble/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

Экспортируйте этот ключ в отдельный файл, а затем укажите на него в настройках репозитория:

gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --export 7EA0A9C3F273FCD8 | sudo tee /etc/apt/keyrings/docker.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/docker.gpg

Добавьте Signed-By: /etc/apt/keyrings/docker.gpg в запись репозитория и выполните sudo apt update. Предупреждение исчезнет, как только ни один репозиторий не будет зависеть от старой связки ключей, после чего вы сможете удалить запись с помощью sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --delete-key 7EA0A9C3F273FCD8.

Еще одна привычка поможет избежать лишних проблем. do-release-upgrade отключает сторонние источники на время обновления и оставляет их выключенными после завершения. Повторное включение вручную, по одному, — это именно тот момент, когда возникают дублирующиеся записи. Прочитайте руководство по обновлению Ubuntu 24.04 до 26.04 перед началом работы и запишите, какие репозитории вам действительно нужны. На только что настроенной машине проще всего привести источники в порядок во время первых десяти минут работы на новом VPS, пока в системе присутствуют только те записи, которые были установлены вместе с Ubuntu.

FAQ

Почему apt сообщает, что цель настроена несколько раз?

Потому что два файла в /etc/apt/sources.list.d/ объявляют один и тот же репозиторий, дистрибутив и компонент. В сообщении указаны оба файла с номерами строк, например docker.list:1 и docker.sources:1. apt объединяет их и продолжает работу, поэтому само обновление выполняется успешно. Дубликат всё равно стоит удалить: как только в двух файлах будут указаны разные ключи подписи, apt остановится с ошибкой E: Conflicting values set for option Signed-By и откажется читать любые источники, что также заблокирует apt install.

Стоит ли оставить файл .list или файл .sources?

Оставьте файл .sources. Формат deb822 используется add-apt-repository в Ubuntu 24.04 и более новых версиях; он содержит одно именованное поле для каждой настройки вместо позиционного текста в квадратных скобках, и именно к этому формату переходят дистрибутивы. Перед удалением файла .list убедитесь с помощью ls -l /etc/apt/keyrings/, что путь Signed-By внутри файла .sources указывает на существующий ключ. Переместите старый файл из /etc/apt/sources.list.d/, а не переименовывайте его внутри той же директории, так как оставшийся файл с расширением .bak заставит apt выводить уведомление об игнорируемом файле при каждом запуске.

Как отключить один репозиторий apt, не удаляя его?

В файле .sources формата deb822 добавьте Enabled: no в нужную секцию. В однострочном файле .list поставьте # в начале строки. В любом случае после этого выполните sudo apt update, и блок Err: для этого репозитория исчезнет. Это правильное решение, если в стороннем репозитории ещё нет пакетов для вашего релиза Ubuntu, и ошибка 404 заставляет apt update завершаться с ненулевым кодом.

Исчезнет ли однострочный формат sources.list?

Он признан устаревшим, но не удалён. apt по-прежнему читает файлы .list, и в текущем руководстве Debian по apt указано, что формат может быть удалён в будущем, но не ранее 2029 года, поэтому завтра на вашем сервере ничего не сломается. Новые инструменты записывают данные в формате deb822: в Ubuntu 24.04 и новее репозитории дистрибутива хранятся в /etc/apt/sources.list.d/ubuntu.sources, а add-apt-repository создает файлы .sources. В apt версии 3.0 и новее команда sudo apt modernize-sources преобразует имеющиеся у вас файлы.

#apt#ubuntu#deb822#package-management#troubleshooting