SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor

Sửa lỗi apt source bị khai báo trùng lặp

Gặp lỗi “Target is configured multiple times”? Tìm cặp file .list và .sources cho cùng repository, giữ một file để apt update chạy sạch trở lại.

Lỗi nguồn apt trùng lặp có nghĩa là gì

Nguồn apt trùng lặp nghĩa là một repository được khai báo hai lần trong hai file khác nhau và APT (advanced package tool) đã phát hiện cả hai bản. Trên Ubuntu 24.04 trở lên, nguyên nhân gần như luôn là một script cài đặt của bên thứ ba đã ghi một file một dòng cũ .list trong khi file deb822 .sources cho cùng repository đã tồn tại trên máy. Không có dữ liệu nào bị hỏng và không có package nào gặp rủi ro. Xóa một trong hai khai báo là thông báo sẽ biến mất.

Đây là dòng mà nhiều người dán vào ô tìm kiếm:

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

Đọc từ cuối lên. Hai file, mỗi file có một số dòng, khai báo cùng một nội dung. Target Packages là index mà apt tải xuống để biết repository cung cấp những package nào, còn stable/binary-amd64/Packages chỉ component (stable) và architecture (amd64) mà index đó áp dụng. Vì vậy, apt đang báo rằng index amd64 cho component stable được cấu hình trong docker.list ở dòng 1, rồi được khai báo lại trong docker.sources ở dòng 1.

Trên apt 3.0 trở lên, tức Ubuntu 25.04 trở đi và Debian 13, thông báo tương tự bắt đầu bằng Warning: thay vì W:. Phần văn bản sau prefix không thay đổi.

Cảnh báo này là trường hợp nhẹ. apt gộp hai khai báo và lệnh update vẫn chạy vì cả hai đều mô tả cùng một archive với cùng một key. Trường hợp nghiêm trọng sẽ dừng toàn bộ quá trình:

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 từ chối tiếp tục trong trường hợp này vì hai khai báo chỉ ra các signing key khác nhau cho cùng một archive. apt sẽ gộp hai khai báo giống hệt nhau, nhưng sẽ không chọn giữa hai giá trị Signed-By vì chọn nhầm có nghĩa là kiểm tra chữ ký package bằng một key mà chủ archive chưa từng dùng để ký. Vì vậy, apt không đọc source nào cả. apt updateapt install đều thất bại với cùng hai dòng đó cho đến khi bạn chỉnh sửa các file thủ công.

Cách file trùng lặp xuất hiện

Hai định dạng này nằm trong các file riêng biệt với phần mở rộng khác nhau, nên không có cơ chế nào trên disk ngăn cả hai cùng tồn tại. apt chỉ phát hiện chúng trùng nhau ở bước muộn, khi mở rộng từng source file thành danh sách các index target mà nó dự định tải xuống. Cho đến lúc đó, docker.listdocker.sources là hai file không liên quan.

Bốn sự kiện thông thường có thể tạo ra cặp file này:

  • Một vendor install script, hoặc một command được sao chép từ bài viết cũ, ghi /etc/apt/sources.list.d/vendor.list với một dòng tee.
  • Package của chính vendor sau đó ship /etc/apt/sources.list.d/vendor.sources và tự cài đặt file này cho bạn.
  • add-apt-repository trên Ubuntu 24.04 trở lên ghi các file deb822 .sources, nên một PPA (personal package archive) mà trước đây bạn đã thêm thủ công dưới dạng .list sẽ xuất hiện lại dưới dạng .sources.
  • Một lần release upgrade chuyển các source của distribution sang deb822 nhưng để nguyên file .list do bạn tự viết bên cạnh chúng.

Mỗi trường hợp đều hợp lý nếu xét riêng. File trùng lặp xuất hiện khi hai trường hợp xảy ra trên cùng một máy, thường cách nhau vài tháng.

Hai định dạng, đặt cạnh nhau

Định dạng cũ dùng một dòng cho mỗi repository, và mọi thành phần đều được xác định theo vị trí.

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

Thứ tự là cố định: loại (deb cho binary package, deb-src cho source package), tiếp theo là các tùy chọn trong dấu ngoặc vuông, rồi URI (uniform resource identifier) của archive, suite và một hoặc nhiều component. Vì ý nghĩa phụ thuộc vào vị trí, chỉ cần đặt sai một khoảng trắng là apt sẽ đọc khác đi.

deb822 biểu diễn cùng thông tin dưới dạng một stanza gồm các field có tên. Tên này bắt nguồn từ RFC 822, kiểu header của mail mà Debian đã dùng cho các file control của package.

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

Cùng repository, cùng key, không thêm gì. Việc ánh xạ là trực tiếp: deb trở thành Types, địa chỉ archive trở thành URIs, suite trở thành Suites, các component trở thành Components, còn mỗi tùy chọn trong ngoặc vuông trở thành một field riêng. Vì vậy, signed-by= trở thành Signed-By:arch= trở thành Architectures:.

Tên mọi field đều ở dạng số nhiều vì mỗi field nhận một danh sách được phân tách bằng khoảng trắng. Suites: noble noble-updates noble-backports trong một stanza thay thế cho ba dòng deb riêng biệt. Một dòng trống kết thúc một stanza, nên một file .sources có thể chứa nhiều repository. deb822 cũng hỗ trợ các thiết lập mà định dạng một dòng xử lý không tốt: Enabled: no để tắt repository, Trusted, Check-Valid-Until và một key được chèn trực tiếp vào Signed-By, trong đó mỗi dòng được thụt vào một khoảng trắng và các dòng trống được ghi bằng một dấu chấm đơn.

Vị trí của từng file

  • /etc/apt/sources.list: file đơn ban đầu. Trên Ubuntu 24.04 trở lên, file này thường rỗng hoặc chỉ có comment trỏ đến vị trí mới.
  • /etc/apt/sources.list.d/*.list: các dòng khai báo đơn, thường mỗi repository dùng một file.
  • /etc/apt/sources.list.d/*.sources: các khối khai báo deb822. Ubuntu 24.04 trở lên lưu các repository riêng của bản phân phối tại đây, trong ubuntu.sources.
  • /etc/apt/keyrings/: nơi lưu các key bạn thêm vào. /usr/share/keyrings/ chứa các key do package cung cấp.

apt chỉ đọc các file kết thúc bằng .list hoặc .sources, và tên file chỉ được chứa chữ cái, chữ số, dấu gạch dưới, dấu gạch ngang và dấu chấm. File có phần mở rộng khác sẽ bị bỏ qua kèm thông báo. Điều này quan trọng đối với cách khắc phục bên dưới.

Tìm cặp bị trùng

Bắt đầu bằng cách liệt kê thư mục:

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

Hai file có cùng tên gốc nhưng khác phần mở rộng thường là cặp bị trùng, nhưng không được chỉ dựa vào tên. Hãy đọc nội dung, vì bản ghi trùng có thể nằm trong một file mang bất kỳ tên nào:

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

Cặp đó là hai mục có cùng host và cùng suite. Cả hai đều trỏ đến https://download.docker.com/linux/ubuntu và suite noble, nên chúng là cùng một repository được khai báo hai lần. Các đường dẫn Signed-By của chúng cũng khác nhau. Đây là nguyên nhân tạo ra lỗi Conflicting values đã hiển thị trước đó.

Ở bước này, hãy dùng grep thay vì lệnh apt. Khi apt đã dừng vì xung đột, nó cũng không thể liệt kê các source của bạn. Vì vậy, apt-cache policy chỉ in lại cùng lỗi đó thay vì kết quả bạn cần.

Sửa lỗi: giữ file deb822, xóa file cũ

Giữ file .sources. Đây là định dạng mà công cụ apt hiện ghi ra, và Debian cũng như Ubuntu đều đang chuyển sang định dạng này. Trước khi xóa bất kỳ thứ gì, kiểm tra xem hai path chính nào tồn tại trên disk:

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

Chỉ có /etc/apt/keyrings/docker.asc tồn tại, nên file deb822 là file chứa thông tin đúng còn file .list trỏ đến một key đã bị xóa. Nếu file bạn định giữ lại khai báo key bị thiếu, trước tiên hãy chép path đang hoạt động vào file đó, rồi xóa file còn lại.

Di chuyển file cũ ra khỏi thư mục thay vì xóa ngay:

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

Đổi tên file thành docker.list.bak và để nguyên trong thư mục cũng được vì apt bỏ qua các extension không xác định, nhưng khi đó mỗi lần apt chạy sẽ in thông báo này:

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

Di chuyển file sang nơi khác sẽ không còn thông báo đó trên màn hình mà vẫn giữ được bản sao lưu. Sau đó, file apt update hợp lệ sẽ có dạng như sau, không có dòng nào khai báo hai file:

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.

Bây giờ xác nhận repository vẫn hoạt động sau khi chỉnh sửa:

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

Nếu tài liệu của vendor vẫn giả định dùng file một dòng, bạn có thể giữ file đó và xóa file .sources thay thế. Dù chọn cách nào, chỉ có một quy tắc: mỗi archive và suite chỉ được đúng một file khai báo.

Tại sao một source bên thứ ba bị hỏng lại làm apt update thất bại hoàn toàn

Lỗi gần đó trông khác nhưng có cùng nguyên nhân: một source bên thứ ba mà apt không thể sử dụng. Trường hợp đầu tiên là thiếu key:

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.

Trường Signed-By bị thiếu hoặc trỏ đến một file không chứa key hợp lệ, nên apt không thể xác minh chữ ký trong file InRelease của archive. Khi đó apt loại bỏ toàn bộ repository thay vì tin vào các package list mà nó không thể kiểm tra. Hãy xem trực tiếp file key:

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

Key hợp lệ sẽ in một dòng pub chứa key id và một dòng uid ghi tên vendor. gpg: no valid OpenPGP data found. nghĩa là file đó hoàn toàn không phải key. Nguyên nhân thường là lệnh download đã lưu một trang lỗi vì URL của key đã thay đổi. Hãy tải lại key, kiểm tra file, rồi chạy apt update.

Trường hợp thứ hai xảy ra sau khi nâng cấp release:

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 chưa publish nội dung nào cho suite đó, nên path không tồn tại trên server và request trả về lỗi 404. Các repository khác vẫn update bình thường, còn các package đã cài vẫn không bị ảnh hưởng. Tuy nhiên, tiến trình vẫn kết thúc với mã khác 0. Vì vậy, mọi script kiểm tra exit status của apt update sẽ báo lỗi mỗi lần chạy. Đây là lý do nên xóa source đã chết trên máy đang cấu hình tự động nâng cấp bản vá bảo mật: các cảnh báo hằng ngày có thể che khuất một lỗi thật sự.

Vô hiệu hóa một source mà không làm hỏng các source khác

Với file deb822, thêm một field vào stanza rồi lưu lại:

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 manual khuyến nghị cách này thay vì comment từng dòng trong stanza, và cách này cũng dễ hoàn tác hơn. Với file một dòng, đặt # ở đầu dòng. Với cả hai định dạng, bạn cũng có thể chuyển file ra khỏi /etc/apt/sources.list.d/. Hãy chọn cách này khi repository đã bị gỡ vĩnh viễn.

Chạy lại sudo apt update. Block Err: của repository đó sẽ biến mất, và exit status trở về 0. Bạn có thể kiểm tra bằng echo $? ở dòng tiếp theo.

Không bao giờ sửa một source bị hỏng bằng sudo rm /etc/apt/sources.list.d/*. Trên Ubuntu 24.04 trở lên, lệnh này xóa ubuntu.sources. File này chứa các repository của chính distribution, khiến apt không còn package list nào và báo E: Unable to locate package curl cho những phần mềm rõ ràng đang tồn tại. Nếu bạn đã chạy lệnh đó, hãy ghi lại file:

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

Lưu file đó thành /etc/apt/sources.list.d/ubuntu.sources, thay noble bằng tên release của bạn lấy từ lsb_release -cs, rồi chạy sudo apt update.

Chuyển các file .list cũ sang deb822

Từ tháng 8 năm 2026, apt 3.0 trở lên có sẵn công cụ chuyển đổi cho việc này. Debian 13 có công cụ này, Ubuntu 25.04 và mọi bản phát hành sau đó, bao gồm 26.04, cũng vậy. Kiểm tra phiên bản, rồi chạy:

apt --version
sudo apt modernize-sources

Công cụ này viết lại các file chỉ có một dòng trong /etc/apt/sources.list.d/ thành các file deb822 trong .sources. Đọc nội dung được in ra, sau đó tự liệt kê thư mục và chạy apt update trước khi tin tưởng kết quả. Ubuntu 24.04 đi kèm apt cũ hơn, không có subcommand này, nên lệnh sẽ trả về E: Invalid operation modernize-sources. Trên bản phát hành đó, hãy chuyển đổi thủ công theo bảng ánh xạ trường ở trên.

Hiện tại, việc chuyển đổi là tùy chọn vì apt vẫn đọc được cả hai định dạng. Tuy nhiên, nên thực hiện trên server bạn dự định tiếp tục sử dụng, vì mọi tool ghi cấu hình source hiện đều ghi theo định dạng deb822. Một máy chỉ có các file .sources sẽ không thể phát sinh thêm loại duplicate này.

Giữ source của bên thứ ba gọn gàng trên server

Repository của bên thứ ba là phần trên server xuống cấp nhanh nhất theo thời gian. Mỗi repository là một cam kết của bên khác rằng họ sẽ tiếp tục publish package cho bản Ubuntu của bạn. Mỗi lần nâng cấp release sẽ kiểm tra tất cả các cam kết đó cùng lúc.

  • Chỉ thêm repository của bên thứ ba khi package của distribution không đáp ứng được nhu cầu. Một LAMP stack trên Ubuntu 24.04 thông thường không cần repository nào: Ubuntu archive đã có mọi package mà stack này sử dụng, cùng các bản cập nhật bảo mật trong suốt vòng đời của release.
  • Lưu key trong /etc/apt/keyrings/, mỗi vendor một file, mode 644. User không đặc quyền _apt thực hiện việc download và phải đọc được key. Vì vậy, file key chỉ cho root đọc sẽ gây lỗi permission mỗi lần fetch từ repository đó.
  • Trỏ Signed-By đến đúng file đó trong từng stanza. Một key nằm trong /etc/apt/trusted.gpg hoặc /etc/apt/trusted.gpg.d/ sẽ được tin cậy cho mọi repository trên máy. Điều này có nghĩa là key của một vendor được thêm từ nhiều năm trước có thể xác thực package từ bất kỳ nguồn nào.
  • Trước khi nâng cấp release, hãy đọc các source và kiểm tra xem từng vendor đã publish cho suite mà bạn sắp chuyển sang chưa.

Key trong keyring global cũ sẽ xuất hiện trong mỗi lần update:

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.

Export riêng key đó vào một file riêng, rồi trỏ stanza đến file này:

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

Thêm Signed-By: /etc/apt/keyrings/docker.gpg vào stanza của repository rồi chạy sudo apt update. Cảnh báo sẽ dừng khi không còn repository nào phụ thuộc vào keyring cũ. Sau đó, bạn có thể xóa entry bằng sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --delete-key 7EA0A9C3F273FCD8.

Một thói quen khác giúp tránh phần lớn sự cố. do-release-upgrade sẽ disable các source của bên thứ ba trong quá trình nâng cấp và tiếp tục để chúng ở trạng thái tắt sau đó. Việc bật lại thủ công từng source một chính là lúc các khai báo trùng lặp thường được tạo ra. Hãy đọc hướng dẫn nâng cấp Ubuntu 24.04 lên 26.04 trước khi bắt đầu và ghi lại những repository bạn vẫn cần. Trên một máy vừa được build xong, thời điểm ít tốn công nhất để chỉnh source là trong 10 phút đầu tiên trên một VPS mới, khi các entry duy nhất trên máy vẫn là những entry do Ubuntu cung cấp.

FAQ

Vì sao apt báo một target được cấu hình nhiều lần?

Vì có hai file trong /etc/apt/sources.list.d/ khai báo cùng repository, suite và component. Thông báo này nêu tên cả hai file kèm số dòng, chẳng hạn docker.list:1docker.sources:1. apt gộp các khai báo đó rồi tiếp tục, nên thao tác update vẫn hoạt động. Tuy nhiên, bạn vẫn nên xóa bản trùng: ngay khi hai file chỉ định các signing key khác nhau, apt sẽ dừng với E: Conflicting values set for option Signed-By và từ chối đọc toàn bộ source, khiến apt install cũng bị chặn.

Tôi nên giữ file .list hay file .sources?

Giữ file .sources. deb822 là định dạng mà add-apt-repository ghi trên Ubuntu 24.04 trở lên. Định dạng này dùng một field có tên cho mỗi thiết lập thay vì văn bản theo vị trí trong dấu ngoặc vuông, và đây là hướng phát triển của các bản phân phối. Trước khi xóa file .list, hãy xác nhận path Signed-By bên trong file .sources trỏ đến một key đang tồn tại bằng ls -l /etc/apt/keyrings/. Hãy chuyển file cũ ra khỏi /etc/apt/sources.list.d/ thay vì đổi tên nó ngay trong thư mục, vì tên .bak còn sót lại sẽ khiến apt in thông báo bỏ qua file ở mỗi lần chạy.

Làm thế nào để tắt một apt repository mà không xóa nó?

Trong file .sources dạng deb822, thêm Enabled: no vào stanza. Trong file .list dạng một dòng, đặt # ở đầu dòng. Dù dùng cách nào, hãy chạy sudo apt update sau đó; khối Err: của repository đó sẽ biến mất. Đây là cách phù hợp khi một repository của bên thứ ba chưa có package cho bản Ubuntu release của bạn và lỗi 404 của nó khiến apt update thoát với mã khác 0.

Định dạng sources.list một dòng có bị loại bỏ không?

Định dạng này đã deprecated nhưng chưa bị loại bỏ. apt vẫn đọc các file .list và sẽ còn hỗ trợ trong thời gian dài, nên server của bạn sẽ không hỏng ngay ngày mai. Tool mới ghi theo deb822: Ubuntu 24.04 trở lên lưu các distribution repository trong /etc/apt/sources.list.d/ubuntu.sources, còn add-apt-repository ghi các file .sources. Trên apt 3.0 trở lên, sudo apt modernize-sources chuyển đổi các file mà bạn vẫn còn.

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