đ Executive Summary
TL;DR: The âapt-key is deprecatedâ warning indicates a shift from a globally trusted keyring to a more secure, per-repository key management system. To resolve this, PPA keys should be moved to the modern âsigned-byâ method, ensuring CI/CD pipelines and server provisioning continue to function on modern Debian and Ubuntu systems.
đŻ Key Takeaways
- The âapt-key is deprecatedâ warning signals a security enhancement, moving from a single global keyring (
/etc/apt/trusted.gpg) to isolated, per-repository keys. - The âRight Wayâ to fix this involves creating a dedicated
/etc/apt/keyrings/directory for GPG keys and explicitly linking them to repository source files using the[signed-by=âŚ]attribute. - While a âQuick Fixâ involves piping dearmored keys to
/etc/apt/trusted.gpg.d/, it maintains a global trust model and is not recommended for long-term production use. - A âNuclear Optionâ script can help migrate existing keys from
trusted.gpgto individual files intrusted.gpg.d, but still requires manual updates tosources.list.dfiles with thesigned-byattribute. - Automating the âRight Wayâ fix in base images, Ansible roles, or CI runners prevents future build failures and enhances infrastructure security.
Fix the notorious âapt-key is deprecatedâ warning by moving your PPA keys to the modern, secure âsigned-byâ method, ensuring your CI/CD pipelines and server provisioning donât break on modern Debian and Ubuntu systems.
So, Your Build is Failing. Letâs Talk About âapt-keyâ.
I remember it vividly. It was 2 AM, and a P1 incident ticket landed in my queue. A critical deployment pipeline for our main monolith, prod-monolith-alpha, was failing. The error? A cryptic warning message that the on-call junior engineer had never seen before: Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead. The build script, which had worked flawlessly for three years, was now halting on a simple apt-get update. A base image had been updated automatically, and suddenly, our entire deployment process was dead in the water.
If youâre reading this, youâve probably just hit the same wall. Your Ansible playbook, your Dockerfile, your trusty server setup scriptâitâs all screaming at you about apt-key. Donât panic. Youâre not alone, and this is a good thing, I promise. Itâs the system forcing us to be more secure. Letâs break it down.
First, The âWhyâ: Whatâs a Keyring and Why Did It Break?
Think of the old apt-key system like a single master key for an entire apartment building. When you used apt-key add some_repo.gpg, you were adding a key to a global, trusted keyring (/etc/apt/trusted.gpg). This meant that the key for the Node.js repository could, in theory, be used to validate packages from the PostgreSQL repository. If any one of those keys were compromised, an attacker could potentially sign malicious packages and get them trusted as if they were official.
The new method is about isolation. Instead of one global keyring, every software repository you add gets its own key, stored in a dedicated place (/etc/apt/keyrings/). Then, in your repository configuration file, you explicitly tell APT: âFor this specific repository, you must use this specific key to verify its packages.â Itâs like giving each apartment its own unique key instead of a master key. Itâs more work, but itâs a hell of a lot more secure.
The Solutions: From âGet Me Out of Hereâ to âBuilt to Lastâ
Iâve seen this problem tackled a few ways in the wild. Here are three approaches, from the quick-and-dirty to the architecturally sound.
Solution 1: The Quick & Dirty Fix (The Band-Aid)
Letâs say your build is on fire and you just need it working right now. This method is the direct descendant of the old way, but it puts the key in the âcorrectâ directory without fully embracing the new system. It still uses a global trust model, but it silences the deprecation warning in many cases.
You probably have a line in your script that looks like this:
# The OLD, broken way
wget -qO - https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
The quick fix is to dearmor the key and dump it into the trusted.gpg.d directory. This directory is for dropping in key files that APT will trust globally.
# The QUICK FIX: Pipe the key to the trusted.gpg.d directory
wget -qO - https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg
Darianâs Take: Look, I get it. Sometimes you just need to stop the bleeding. This will often work and get your pipeline green again. But you havenât actually fixed the underlying security issue. Youâve just moved the key. Donât leave this in a production script long-term. Youâre just kicking the can down the road.
Solution 2: The âRight Wayâ Fix (The Permanent Solution)
This is the method you should be using. It fully embraces the new per-repository key model. Itâs a two-step process: place the key in a dedicated, isolated keyring directory, and then tell the repository source list where to find it.
Step 1: Create the keyrings directory and download the key there.
Weâll create a dedicated directory for our keys. This is best practice to keep things organized and secure.
# Create the directory if it doesn't exist
sudo install -m 0755 -d /etc/apt/keyrings
# Download the key, dearmor it, and save it to the new directory
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Set proper permissions for the key file
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Step 2: Modify your repository source file to use the new key.
Now, we create or edit the repositoryâs .list file in /etc/apt/sources.list.d/. The magic is the [signed-by=...] part. This explicitly tells APT which key to use for this repo.
# Add the repository to your sources list
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Now, update your package list
sudo apt-get update
No warnings. Clean, secure, and future-proof. This is how we do it on all our new server images and CI runners like ci-runner-bionic-04.
Solution 3: The âNuclearâ Option (For Legacy Systems)
What if youâve inherited a server like legacy-prod-db-01 with a dozen old keys in the main trusted.gpg keyring? Migrating them one by one is a pain. This is an advanced approach for cleaning up a messy system. Itâs a script to extract all the keys from the old keyring and move them to the new format.
WARNING: This is a powerful script. It directly manipulates your systemâs trust stores. Test it on a non-critical machine first. I am not responsible if you break your package manager. You have been warned.
#!/bin/bash
# Script to migrate keys from legacy apt-key to the new format
set -e
echo "Starting migration of keys from trusted.gpg..."
# Export all keys from the main keyring to individual files
apt-key exportall | gpg --dearmor > /tmp/temp-trusted-export.gpg
# Split the exported file into individual keys
gpg --enarmor < /tmp/temp-trusted-export.gpg | csplit -z -f /tmp/key- -b "%02d.asc" - "/-----BEGIN PGP PUBLIC KEY BLOCK-----/" "{*}"
# Process each individual key file
for keyfile in /tmp/key-*.asc; do
if [ -s "$keyfile" ]; then
echo "Processing ${keyfile}..."
# Get the fingerprint to use as the filename
fingerprint=$(gpg --show-keys --with-colons "${keyfile}" | grep '^fpr' | cut -d: -f10)
if [ -n "$fingerprint" ]; then
# Dearmor the key and place it in the trusted.gpg.d directory
echo "Moving key with fingerprint ${fingerprint}"
gpg --dearmor < "${keyfile}" > "/etc/apt/trusted.gpg.d/${fingerprint}.gpg"
else
echo "Could not get fingerprint for ${keyfile}"
fi
fi
done
echo "Cleaning up temporary files..."
rm /tmp/temp-trusted-export.gpg /tmp/key-*.asc
echo "Migration complete. You should now audit your source.list files to use [signed-by]."
echo "This script does NOT automatically update your source lists."
This script gets you halfway thereâit moves the keys. You still need to go into your /etc/apt/sources.list.d/ files and add the [signed-by=...] attribute for each repository, pointing to the new key files. Itâs a cleanup tool, not a magic wand.
My Final Two Cents
Itâs tempting to use the quick fix and move on. Weâre all under pressure. But taking the extra ten minutes to implement Solution #2, the âRight Way,â will save your future self (or the next engineer) a massive headache. Itâs a small change that makes your infrastructure more robust and secure.
Automate it, put it in your base images, bake it into your Ansible roles. Stop using apt-key add today. Your future self will thank you when youâre sleeping soundly instead of troubleshooting a broken build at 2 AM.
đ Read the original article on TechResolve.blog
â Support my work
If this article helped you, you can buy me a coffee:

Top comments (0)