Ubuntu’s own repositories don’t always have the version you need. You might want newer PHP, a newer Nginx, or software that isn’t packaged at all. PPAs (Personal Package Archives on Launchpad) and vendor repositories fill the gap. Here’s how to add them properly, and how to remove them when they cause trouble.

Add a PPA

sudo apt install software-properties-common      # provides add-apt-repository
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php8.4-fpm

add-apt-repository downloads the PPA’s signing key, writes a source file to /etc/apt/sources.list.d/ and, on current Ubuntu versions, runs apt update itself.

Well-known PPAs used on servers include:

  • ppa:ondrej/php — current PHP versions. See installing PHP versions.
  • ppa:ondrej/nginx — newer Nginx builds.
  • ppa:deadsnakes/ppa — other Python versions.

PPAs are built for Ubuntu. On Debian, use the equivalent Debian repository the maintainer provides. Ondřej Surý’s packages, for example, are at packages.sury.org.

Add a vendor repository (the modern way)

Many projects, including Docker, PostgreSQL, Node.js, MariaDB, Grafana and Elastic, provide their own apt repositories. The secure pattern stores the vendor key in its own keyring and restricts it to that repository with signed-by:

sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

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

sudo apt update

Why not apt-key?

apt-key add is deprecated and has been removed in newer releases. It also put keys in a global keyring that apt trusted for every repository. With signed-by, a key can only sign packages from its own repository. If you see Key is stored in legacy trusted.gpg keyring warnings, migrate the key to /etc/apt/keyrings/ and add signed-by.

deb822 .sources format

Newer Ubuntu (24.04+) and Debian use a structured format in .sources files:

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

Both .list and .sources work. Ubuntu’s own sources now live in /etc/apt/sources.list.d/ubuntu.sources.

Check where a package will come from

apt policy php8.4-fpm

This shows the installed version, the candidate version and every repository offering it, with priorities. It’s very useful when a PPA and the official archive both provide a package.

Pinning: limit what a repository may replace

A repository can offer newer versions of packages you’d rather keep from Ubuntu. Pin it so only the packages you want come from there:

# /etc/apt/preferences.d/sury
Package: *
Pin: origin ppa.launchpadcontent.net
Pin-Priority: 100

Package: php8.4*
Pin: origin ppa.launchpadcontent.net
Pin-Priority: 600

Priority 100 means packages from that origin are only used when you ask for them explicitly. Priority 600 makes the named packages preferred.

Remove a PPA or repository

sudo add-apt-repository --remove ppa:ondrej/php
# or delete the file
sudo rm /etc/apt/sources.list.d/ondrej-ubuntu-php-*.sources
sudo rm /etc/apt/keyrings/docker.gpg       # and its key, for vendor repos
sudo apt update

To downgrade the packages back to the official versions, use ppa-purge:

sudo apt install ppa-purge
sudo ppa-purge ppa:ondrej/nginx

Before you add a repository

  • Trust: a repository’s packages run as root during installation. Only add sources from the project itself or maintainers you trust.
  • Release upgrades: do-release-upgrade disables third-party sources. Re-enable them (with the new codename) afterwards, once the vendor supports the new release.
  • Support: a PPA may stop publishing for your Ubuntu version. Check before relying on it for production.
  • Fewer is better: each extra source slows apt update and adds a way for things to break.

Common errors

NO_PUBKEY ABCDEF1234567890 — the repository’s key is missing. Download the key into /etc/apt/keyrings/ and reference it with signed-by.

The repository … does not have a Release file — the repository doesn’t support your release (for example a PPA without builds for your Ubuntu version), or the URL is wrong.

Conflicting values set for option Signed-By — the same repository is defined twice with different keys. Remove the duplicate file.

More fixes are in apt update errors.

Quick reference

Task Command
Add PPA sudo add-apt-repository ppa:user/name
Remove PPA sudo add-apt-repository --remove ppa:user/name
Downgrade to official sudo ppa-purge ppa:user/name
Key location /etc/apt/keyrings/*.gpg
Source files /etc/apt/sources.list.d/
Where from? apt policy pkg

Related: apt commands and dpkg.

  • Ubuntu
  • Debian
  • Packages