28.6 /etc/apt/sources.list and sources.list.d: Repository Configuration
Right, let’s talk about the file that tells your machine where to go shopping for software. It’s called /etc/apt/sources.list, and it’s the VIP guest list for your package manager. Think of it as the directory of every single store (deb) and library (deb-src) apt is allowed to visit to get your packages. Mess this up, and you’re either getting nothing, the wrong thing, or something that will spectacularly break your system. No pressure.
The original sources.list file works perfectly fine, but managing all your repositories in one giant file is like trying to cook a five-course meal in a single pot—messy and prone to disaster. That’s why the brilliant (and frankly, obvious) idea of /etc/apt/sources.list.d/ was born. This directory lets you drop in individual .list files, one for each repository you want to add. This is the modern, sane way to do things. It keeps your system’s default sources pristine and makes it trivial to add or remove repositories without editing a monolithic file. If you need to nuke a sketchy PPA, you just delete its file in sources.list.d/ instead of hunting through a thousand lines of text.
Anatomy of a sources.list entry
Every line in these files that isn’t a comment (starting with #) follows a specific format. Get it wrong, and apt update will throw a fit. It looks deceptively simple:
deb [option1=value1 option2=value2] URI suite component [component2 ...]
Let’s break that down because it’s actually important:
deb: This is for binary packages, the pre-compiled programs you actually want to install. Usedeb-srcif you’re the type who likes to download the source code to read it or compile it yourself (bless you).[options]: This is usually where you specify signed-by to pin a repository’s GPG key. More on that security nightmare later.URI: The base URL. This is the address of the repository, likehttp://archive.ubuntu.com/ubuntu/orhttps://ppa.launchpadcontent.net/someuser/ppa/ubuntu/.suite: This is… confusing. For standard Ubuntu repositories, this is your release name or its alias, likejammy,focal, orstable. For other repos, it might be a path likedists/stable.component: These are the categories of software within the suite. For the main Ubuntu repos, these aremain,restricted,universe, andmultiverse.
So a standard entry for the main Ubuntu repository looks like this:
deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse
And adding a popular PPA would create a file in sources.list.d/ with a line like:
deb https://ppa.launchpadcontent.net/php/ppa/ubuntu/ jammy main
The GPG Key Circus
Here’s the part the designers absolutely fumbled: security. APT will refuse to use a repository unless it trusts it, and trust is established by having the repository’s GPG signing key in your keyring. The apt-key command was the old way to manage these, and it was a dumpster fire because it added keys to a trusted global keyring. A malicious repo could use a key signed by any other trusted key! Thankfully, apt-key is deprecated.
The modern, secure way is to use the signed-by option inside your .list file. You download the key to a specific location like /usr/share/keyrings/ and then reference it directly. This pins the key to that specific repository and no other.
# First, download the key to a sane location. Note the '.asc' extension.
sudo curl -fsSL https://ppa.launchpadcontent.net/php/ppa/ubuntu/key.asc | sudo gpg --dearmor -o /usr/share/keyrings/php-ppa-archive-keyring.gpg
# Then, create your .list file using the 'signed-by' option.
echo "deb [signed-by=/usr/share/keyrings/php-ppa-archive-keyring.gpg] https://ppa.launchpadcontent.net/php/ppa/ubuntu/ jammy main" | sudo tee /etc/apt/sources.list.d/php-ppa.list
This is more work, but it’s correct. It means if some other repo somehow gets ahold of that same key, it won’t be trusted by default.
Best Practices and Glaring Pitfalls
- Don’t Touch the Default File: Seriously, leave
/etc/apt/sources.listalone. Your future self will thank you when an upgrade doesn’t mysteriously fail because you commented out theuniverserepo three years ago and forgot. - Use
sources.list.d/: Add all your third-party repositories as individual.listfiles in/etc/apt/sources.list.d/. Name them something sensible, like<repository-name>.list. - Never Mix Releases: This is the classic “oops, I borked my system” move. If you’re running Jammy (22.04), your entries must say
jammy(or22.04), notfocal, notimpish, and certainly notsid. You’re asking for a dependency apocalypse. - Prefer HTTPS: If a repository offers an
https://URI, use it. It’s 2024; there’s no excuse for unencrypted http for package downloads anymore. It prevents nosy networks from seeing what you’re installing or, worse, serving you malicious packages. - Clean Up Your Mess: When you stop using a repository, remove its
.listfile fromsources.list.d/and delete its GPG key from/usr/share/keyrings/. A cluttered sources list slows downapt updateand is just poor hygiene.
The bottom line is this: these files are the foundation of everything apt does for you. A little discipline here—using the .d directory, using signed-by, and not mixing releases—saves you from a world of pain later. Now go forth and configure without causing chaos.