DevOps.Academy
CoursesCurriculumPricing

    Loading…

    ↑ ↓ move · ↵ open · Ctrl K anywhere

    ◔My learningSign in
    DevOps.Academy

    Free, hands-on DevOps lessons. Made with care in India.

    Learn

    All coursesLinux roadmapCurriculumMy learning

    Academy

    PricingCertificates

    Legal

    PrivacyTermsContact

    devops.rajeev.pro

    Linux & BashLesson 10 of 16
    Your progress · 0%
    On this page
    1. How a package manager works
    2. Everyday commands
    3. What's installed, and who owns this file?
    4. Repositories and trust
    5. Updating a production server
    6. snap and other installers
    ↖ Course roadmap
    Lesson 10 · Package management

    Packages: install, update and trust software

    How apt and dnf install software with its dependencies, where packages come from, how to update a server safely, find what owns a file, pin versions, and when snap fits.

    30 min read · beginner · hands-on

    By the end of this lesson you'll be able to

    0 of 6 complete

    How a package manager works

    A package is a program bundled with its files, its configuration and a list of what it needs to run. A repository is a server full of packages, published by your distribution or a vendor. The package manager downloads the right packages, installs what they depend on, and remembers every file it put on disk, so it can update or remove them cleanly later.

    update refreshes the catalogue; install picks, downloads, verifies and unpacks.© Diagram: DevOps Academy

    update refreshes the catalogue; install picks, downloads, verifies and unpacks.© Diagram: DevOps Academy

    Two families cover almost every server:

    Debian, UbuntuRHEL, Rocky, Alma, Fedora, Amazon Linux
    Package file.deb.rpm
    High level (repositories, dependencies)apt (apt-get, apt-cache in scripts)dnf (yum on older systems)
    Low level (one package file)dpkgrpm
    Repositories/etc/apt/sources.list.d//etc/yum.repos.d/

    Use the high-level tool almost always. dpkg -i file.deb or rpm -i file.rpm install one file and don't fetch its dependencies, which is how servers end up half-broken.

    Everyday commands

    Taskapt (Debian, Ubuntu)dnf (RHEL family)
    Refresh the listssudo apt update(automatic; sudo dnf makecache)
    Searchapt search nginxdnf search nginx
    Detailsapt show nginxdnf info nginx
    Installsudo apt install nginxsudo dnf install nginx
    Removesudo apt remove nginxsudo dnf remove nginx
    Remove with its configsudo apt purge nginx(config files are kept as .rpmsave)
    Upgrade everythingsudo apt upgradesudo dnf upgrade
    Remove unused dependenciessudo apt autoremovesudo dnf autoremove
    $ apt-cache policy curl                 # installed version, and the version apt would install
    curl:
      Installed: 8.18.0-1ubuntu2.7
      Candidate: 8.18.0-1ubuntu2.7
    $ apt-get -s install tree               # -s: simulate. Shows what would happen, changes nothing
    The following NEW packages will be installed:
      tree
    0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
    $ sudo apt install -y tree              # -y: don't ask (for scripts)
    
    sudo apt install -y tree
    • sudorun the next command as root
    • aptDebian/Ubuntu package manager

    apt is for people: progress bars and colour. In scripts, use apt-get and apt-cache: their output stays stable between versions. Set DEBIAN_FRONTEND=noninteractive so no package stops a script to ask a question.

    What's installed, and who owns this file?

    $ dpkg -l | grep -c '^ii'               # how many packages are installed
    549
    $ dpkg -l curl                          # one package: ii = installed
    ii  curl           8.18.0-1ubuntu2.7 amd64        command line tool for transferring data
    $ dpkg -S /usr/bin/curl                 # which package put this file here?
    curl: /usr/bin/curl
    $ dpkg -L curl                          # every file a package installed
    $ apt list --upgradable                 # what has a newer version waiting
    $ rpm -qa | sort                        # RHEL family: everything installed
    $ rpm -qf /usr/sbin/nginx               # RHEL family: which package owns a file
    
    dpkg -l | grep -c '^ii'
    • |pipe: send output to the next command
    • grepfind lines that match a pattern
    • -ccount matching lines
    apt list --upgradable
    • aptDebian/Ubuntu package manager
    rpm -qa | sort
    • sortsort lines

    dpkg -S and rpm -qf answer the classic question "where did this binary come from?", which matters when two versions of a tool are installed and the wrong one runs.

    Repositories and trust

    Your distribution's repositories have most of what you need. For newer versions of some tools (Docker, PostgreSQL, Node.js, Terraform), vendors publish their own. Adding one is two steps: trust the vendor's signing key, then add the repository and say which key it uses:

    $ sudo install -d -m 0755 /etc/apt/keyrings
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
    $ echo "deb [signed-by=/etc/apt/keyrings/docker.asc] 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
    
    sudo install -d -m 0755 /etc/apt/keyrings
    • sudorun the next command as root
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
    • curlmake an HTTP request
    • |pipe: send output to the next command
    • teewrite input to a file and pass it on
    • >write output to a file, replacing it
    echo "deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
    • echoprint text
    sudo apt update
    • aptDebian/Ubuntu package manager

    signed-by= ties that repository to that key only, so a key you add for Docker can't be used to sign packages pretending to be Ubuntu's. Every package is checked against the key before it's installed.

    Adding a key is adding trust

    A repository can install anything on your server, as root, at every upgrade. Add only vendors you trust, over https, following their official instructions. Never pipe a random script from the internet straight into sudo bash on a production machine.

    Updating a production server

    Updates fix security holes, so servers must get them. They also change software under running apps, so do it on purpose:

    $ sudo apt update && apt list --upgradable     # 1. see what would change
    $ sudo apt-mark hold postgresql-16             # 2. hold anything that needs a planned window
    $ sudo apt upgrade                             # 3. upgrade the rest
    $ ls /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgs   # 4. kernel update?
    $ sudo apt-mark unhold postgresql-16           # when its window comes
    
    sudo apt update && apt list --upgradable
    • sudorun the next command as root
    • aptDebian/Ubuntu package manager
    • &&run the next command only if this one worked
    ls /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgs
    • lslist files
    • catprint a file
    CommandUpgradesRemoves or adds packages
    apt upgradeeverything that can be upgraded safelynever removes
    apt full-upgradealso changes that need adding or removing packagesmay remove
    dnf upgradeeverythingmay replace packages

    Test upgrades on a staging server first, upgrade one production server at a time behind a load balancer, and keep unattended-upgrades for security fixes only, so urgent patches still apply by themselves.

    snap and other installers

    snap packages (Ubuntu) bundle a program with all its dependencies and update themselves. They're convenient for desktop and developer tools (sudo snap install --classic code), and some Ubuntu server tools ship this way. On servers, prefer the distribution's packages or the vendor's repository: they integrate with systemd and your normal update process.

    Some tools ship as a single binary (kubectl, terraform) or a vendor install script. Download them from the official site, check the published checksum (sha256sum -c, from the Text processing lesson), and put them in /usr/local/bin, which is for software the package manager doesn't manage.

    In production

    Write down what you installed and why, or better, install it with code: Ansible, a Dockerfile, or a cloud-init script. A server built by hand from memory can't be rebuilt exactly, and one day it will need to be.

    ⌘
    Mini mission

    Audit a server's packages before a change

    Before upgrading a server, you want to know where its software comes from. Record which repositories it uses, how many packages are installed, what would be upgraded, and which package provides the curl binary. Save it to one report.

    Input: An Ubuntu or Debian serverOutput: ~/packages.txt
    Reveal one safe solution
    $ cat > ~/packages-report.sh <<'EOF'
    #!/bin/bash
    echo "== repositories"; grep -rh "^URIs\|^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null | sort -u
    echo "== installed: $(dpkg -l | grep -c '^ii') packages"
    echo "== upgradable"; apt list --upgradable 2>/dev/null | tail -n +2
    echo "== held"; apt-mark showhold
    echo "== curl comes from"; dpkg -S "$(command -v curl)"
    EOF
    $ bash ~/packages-report.sh > ~/packages.txt
    $ cat ~/packages.txt
    == repositories
    URIs: http://archive.ubuntu.com/ubuntu/
    URIs: http://security.ubuntu.com/ubuntu/
    == installed: 549 packages
    == upgradable
    == held
    == curl comes from
    curl: /usr/bin/curl
    
    cat > ~/packages-report.sh <<'EOF'
    • catprint a file
    • >write output to a file, replacing it

    Newer Ubuntu releases describe repositories in .sources files (URIs: lines); older ones use one-line deb … entries. The script reads both. An empty "upgradable" list right after apt update means the server is current.

    Try it yourself

    0 of 6 steps done

    Run each task in your own account or terminal, then tick it off.

    Knowledge check

    Quick check

    Question 1 of 5

    apt install says "Unable to locate package" for a package you know exists. What do you run first?

    Go deeper

    Official reading for this lesson

    • Docsapt(8) manualUbuntu manpages ↗
    • GuideUbuntu Server: package managementUbuntu ↗
    • DocsDNF command referenceDNF ↗
    • GuideUnattended upgrades on UbuntuUbuntu ↗
    • GuideLPIC-1 objectives 102.4 and 102.5Linux Professional Institute ↗

    Or get every quiz answer right and it completes itself.

    ← PreviousServices with systemd: run, restart, read the logsNext lesson →Disks and filesystems: add, mount, grow and repair