Terug naar hoofdinhoud

Linux commando: apt

19 augustus 2026

Elke Debian- of Ubuntu-server die je ooit beheerd hebt, is met een commando gebouwd, bijgewerkt en gerepareerd. apt installeert je webserver, dicht het beveiligingslek waarover je vanochtend las, en verwijdert stilletjes de bibliotheek die niemand meer nodig heeft. De meeste mensen leren drie subcommando's en houden daar op, en dat is jammer, want juist de delen die ze overslaan verklaren waarom een server soms weigert een pakket bij te werken, waarom de schijf volliep, en waarom hetzelfde commando verschillende resultaten opleverde op twee machines die identiek zouden moeten zijn.

1. De basis

De taak van apt is software op je systeem krijgen en actueel houden, zonder dat jij hoeft uit te zoeken wat die software verder nodig heeft. Je vraagt om een pakket; apt zoekt uit welke twintig andere daarvoor nodig zijn, downloadt ze allemaal, en installeert ze in de juiste volgorde.

$ sudo apt update
$ sudo apt install nginx

Die twee regels zijn de hele dagelijkse werkwijze, en de volgorde doet ertoe. Ze doen totaal verschillende dingen, en ze door elkaar halen is de meest gemaakte beginnersfout met apt:

  • apt update ververst de catalogus. Het downloadt de actuele lijst van beschikbare pakketten en versies uit de repositories die je ingesteld hebt. Het installeert niets.
  • apt install en apt upgrade werken op die catalogus. Zij downloaden en installeren daadwerkelijk software.

Zie update als het lezen van de nieuwste prijslijst en install als het plaatsen van de bestelling. Bestel uit de lijst van vorig jaar en je krijgt te horen dat het artikel niet bestaat.

Onderhuids is apt niet het programma dat bestanden op je schijf uitpakt. Dat is dpkg, het Debian-pakketgereedschap, en dat bestond al lang voor apt. dpkg installeert een .deb-bestand en klaagt als er iets ontbreekt. apt zit erbovenop, zoekt uit welke bestanden nodig zijn, haalt ze over het netwerk op, en geeft ze in een werkbare volgorde aan dpkg door.

you  ->  apt        decides what is needed, downloads it
         |
         v
         dpkg       unpacks and configures individual .deb files
         |
         v
         your filesystem

Het commando dat "installeer een webserver" verandert in een opgeloste afhankelijkhedengraaf. Achter twee subcommando's zitten repositories, cryptografische handtekeningen, pinning, gefaseerde uitrol, en een pakketdatabase met 3.000 vermeldingen op een gewone desktop.

Dit artikel begint met software installeren en verwijderen en bouwt op naar repositoryconfiguratie, ondertekeningssleutels, vastgezette pakketten, en de redenen waarom apt soms weigert te doen wat je vroeg.

Het juiste denkmodel: apt is een oplosser van afhankelijkheden met een downloader eraan vast. dpkg doet het installeren. Bijna elke verwarrende apt-melding is apt dat je vertelt dat de graaf die het moest oplossen geen acceptabele oplossing heeft.

Naar boven

2. Waar komt de naam vandaan?

APT staat voor Advanced Package Tool.

apt  =  Advanced Package Tool

"Advanced" was een uitspraak over zijn voorganger en geen marketing. Voor APT betekende software installeren op Debian: dpkg (Debian PacKaGe) voor losse bestanden en een menugestuurde schil genaamd dselect waar mensen zich zonder genegenheid aan herinneren. De vooruitgang was automatische afhankelijkheidsoplossing over een netwerk.

Het verwarrende is niet de naam maar de familie. Meerdere commando's delen hem, en het zijn echt verschillende programma's:

CommandoWat het isWanneer je het gebruikt
dpkg Het laag-niveau gereedschap dat een .deb installeert en bijhoudt wat er geinstalleerd is Een gedownloade .deb installeren, of opvragen welk pakket een bestand bezit
apt-get De oorspronkelijke APT-commandoregel, met een bewust stabiele interface Scripts, Dockerfiles, automatisering
apt-cache De opvraaghelft van de oorspronkelijke interface Zoeken en metadata inspecteren in scripts
apt Een vriendelijkere schil die de meestgebruikte delen van beide combineert, toegevoegd in 2014 Typen in een terminal, interactief
aptitude Een aparte, krachtigere schil met een schermvullende interface Hardnekkige afhankelijkheidsconflicten ontwarren; standaard niet geinstalleerd

Het zijn geen aliassen van elkaar. apt en apt-get zijn losse programma's met verschillende groottes en verschillend gedrag, en paragraaf 7.1 laat een verschil zien dat je zelf kunt zien.

De korte versie van wanneer je wat gebruikt: typ apt, script apt-get. De reden achter die regel is een van de interessantere dingen aan het gereedschap, en paragraaf 7.1 legt hem uit.

Naar boven

3. Een korte geschiedenis

APT is jonger dan Debian en jonger dan dpkg. Debians releasemanager, Brian White, gaf in 1997 opdracht voor het werk omdat software installeren het zwakste punt van de distributie was. De eerste werkende code was een testprogramma genaamd dpkg-get, en een groot deel van de vroege ontwikkeling gebeurde op IRC, wat verklaart waarom de vastlegging rommelig is.

De Debian-changelog bevat de allereerste vermelding nog steeds, en die is ontroerend klein:

apt (0.0.1) unstable; urgency=low

  * Initial Release.

 -- Scott K. Ellis <Dit e-mailadres wordt beveiligd tegen spambots. JavaScript dient ingeschakeld te zijn om het te bekijken.>  Tue, 31 Mar 1998 12:49:28 -0500

De volgende vermelding, drie dagen later, meldt dat 0.0.1 "was released only on IRC". APT bereikte gebruikers voor het eerst in Debian 2.1, uitgebracht op 9 maart 1999, en het veranderde hoe de distributie aanvoelde.

De zestien jaar daarna was het commando dat je typte apt-get. Het kale commando apt kwam pas in april 2014, en de release die het introduceerde is naar het jubileum vernoemd:

apt (1.0) unstable; urgency=low

  The "Happy birthday and 10000b years in the making" release
  ...
  [ Michael Vogt ]
  * install apt binary
  * add apt.8.xml manpage

 -- Michael Vogt <Dit e-mailadres wordt beveiligd tegen spambots. JavaScript dient ingeschakeld te zijn om het te bekijken.>  Tue, 01 Apr 2014 15:48:46 +0200

10000b is binair voor 16. De eerste release was 31 maart 1998; versie 1.0 landde op 1 april 2014, zestien jaar en een dag later. Dat is de hele reden dat er een tweede commando bestaat: na zestien jaar apt-get en apt-cache voegden de ontwikkelaars een commando toe dat de delen combineerde die mensen daadwerkelijk gebruikten, met voortgangsbalken en kleur.

PeriodeMijlpaal
vanaf 1993 dpkg behandelt losse pakketten op Debian; afhankelijkheden zijn het probleem van de gebruiker
1997 Brian White geeft opdracht voor een betere schil; het prototype heet dpkg-get
31 maart 1998 apt 0.0.1, "alleen op IRC" uitgebracht door Scott K. Ellis
9 maart 1999 APT bereikt gebruikers in Debian 2.1
1 april 2014 apt 1.0 installeert het programma apt, "10000b years in the making"
2020 apt 2.0 voegt zoekpatronen toe (apt-patterns), ter vervanging van losse regex-matching
2021 apt 2.1.16 voegt gefaseerde updates toe en verwijdert ongebruikte kernels automatisch bij full-upgrade
2021 apt 2.3.12 weigert essentiele pakketten nog te verwijderen, na een beroemd ongeluk
2024 Ubuntu 24.04 verhuist zijn repositoryconfiguratie naar het deb822-formaat .sources

Achter die vermelding uit 2021 zit een verhaal, en paragraaf 7.3 vertelt het.

Naar boven

4. Eenvoudige toepassingen

4.1 De catalogus verversen

Bijna elke apt-sessie begint hier. apt update benadert elke ingestelde repository en downloadt de actuele pakketlijsten.

$ sudo apt update
Get:1 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Get:2 http://archive.ubuntu.com/ubuntu noble InRelease [256 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages [1522 kB]
...
Reading package lists...
Building dependency tree...
Reading state information...
3 packages can be upgraded. Run 'apt list --upgradable' to see them.

Twee woorden in die uitvoer zijn het kennen waard. Get: betekent dat apt een lijst gedownload heeft omdat die veranderd was. Hit:, dat je bij een tweede keer ziet, betekent dat de lijst al actueel was en er niets overgestuurd is.

De laatste regel nodigt uit om beter te kijken, en het commando dat hij voorstelt is het nuttige:

$ apt list --upgradable
Listing...
libssl3t64/noble-updates,noble-security 3.0.13-0ubuntu3.12 amd64 [upgradable from: 3.0.13-0ubuntu3.11]
libsystemd0/noble-updates,noble-security 255.4-1ubuntu8.17 amd64 [upgradable from: 255.4-1ubuntu8.16]
libudev1/noble-updates,noble-security 255.4-1ubuntu8.17 amd64 [upgradable from: 255.4-1ubuntu8.16]

Elke regel geeft het pakket, uit welke repository de nieuwe versie komt, de nieuwe versie, en de versie die jij hebt. Zie je noble-security in die lijst, dan is de upgrade een beveiligingsfix, en dat is meestal genoeg om te besluiten dat hij niet kan wachten.

4.2 Waarom "Unable to locate package" bijna nooit betekent wat er staat

Dit is de fout die nieuwe gebruikers naar een andere pakketnaam doet zoeken, en dat is vrijwel altijd de verkeerde conclusie. Hier is een volstrekt vers Ubuntu-systeem dat nog geen pakketlijsten heeft:

$ ls /var/lib/apt/lists/ | wc -l
0

$ sudo apt-get install -y tree
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package tree

Het pakket tree bestaat en heeft altijd bestaan. apt heeft alleen geen catalogus om in te kijken, dus voor zover het weet bestaan er helemaal geen pakketten. Een apt update lost het op.

Daarom voegt elke Dockerfile die je ooit gelezen hebt de twee commando's samen. In een container zijn de pakketlijsten bewust leeg om de image klein te houden, dus de update is niet optioneel:

RUN apt-get update && apt-get install -y --no-install-recommends nginx \
    && rm -rf /var/lib/apt/lists/*

Er is een tweede reden voor die && waar mensen later over struikelen. Docker bewaart elke RUN als een laag. Verdeeld over twee instructies kan de update-laag weken later uit de cache hergebruikt worden terwijl de install-laag opnieuw draait, waardoor je de pakketten van vandaag tegen een verouderde catalogus installeert en fouten krijgt over versies die niet meer bestaan. Samengevoegd in een instructie worden ze samen bewaard en samen ongeldig verklaard. De afsluitende rm -rf gooit de catalogus weer weg, want honderden megabytes pakketlijsten meesturen in een image dient niemand.

4.3 Software installeren

Geef apt een pakketnaam. Voordat het iets doet drukt het een samenvatting af en wacht het, en die samenvatting is het lezen waard in plaats van reflexmatig op Enter te drukken:

$ sudo apt install tree
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
  tree
0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded.
Need to get 47.4 kB of archives.
After this operation, 111 kB of additional disk space will be used.

Lees die samenvattingsregel als vier losse tellingen. Upgraded en newly installed zijn wat je gevraagd hebt. To remove is degene om te controleren, want een pakket dat je niet genoemd hebt en daar toch opduikt, betekent dat apt besloten heeft dat er iets weg moet om je verzoek te kunnen inwilligen. Not upgraded telt pakketten waarvoor nieuwere versies beschikbaar zijn die dit commando met rust laat.

Voeg -y toe om de bevestiging automatisch te beantwoorden, wat scripts doen. Maak er voor interactief gebruik geen gewoonte van, want die bevestigingsvraag is je laatste kans om een onverwachte verwijdering op te merken.

4.4 Software vinden

apt search doorzoekt pakketnamen en beschrijvingen, en apt show drukt de details af:

$ apt search '^nginx'          # anchored, or you get hundreds of matches
$ apt show tree
Package: tree
Version: 2.1.1-2ubuntu3.24.04.2
Priority: optional
Section: universe/utils
Origin: Ubuntu
Installed-Size: 111 kB
Depends: libc6 (>= 2.38)
Homepage: http://oldmanprogrammer.net/source.php?dir=projects/tree
Download-Size: 47.4 kB

Twee velden daar beantwoorden echte vragen. Section: universe/utils vertelt je dat het pakket uit Ubuntu's door de gemeenschap onderhouden universe komt en niet uit het officieel ondersteunde main, wat op een server uitmaakt voor de garanties op beveiligingsupdates. Installed-Size is wat het na installatie op schijf kost, in tegenstelling tot Download-Size.

4.5 Software verwijderen

Er zijn twee verwijdercommando's en het verschil betrapt vrijwel iedereen. Kijk naar de pakketstatus voor en na, met de eigen lijst van dpkg:

$ dpkg -l wget
ii  wget  1.21.4-1ubuntu4.4  amd64  retrieves files from the web

$ sudo apt remove wget
$ dpkg -l wget
rc  wget  1.21.4-1ubuntu4.4  amd64  retrieves files from the web

De status veranderde van ii in rc. Die twee letters zijn niet willekeurig, en dpkg drukt zijn eigen legenda af als je hem de kans geeft:

$ dpkg -l bash
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name  Version          Architecture Description
+++-=====-================-============-===========================
ii  bash  5.2.21-2ubuntu4  amd64        GNU Bourne Again SHell

De eerste letter is wat je wilt en de tweede is wat er is. Dus ii betekent "install, installed", en rc betekent "remove, config-files": je vroeg om verwijdering, en wat overblijft is configuratie. Dezelfde legenda verklaart iU (uitgepakt maar niet geconfigureerd) en iF (half geconfigureerd), de toestanden die een onderbroken installatie achterlaat. Een hoofdletter betekent altijd dat er aandacht nodig is.

In het geval van rc staat het overblijfsel er echt nog:

$ ls /etc/wgetrc
/etc/wgetrc

Dat is opzettelijk en meestal handig, want later opnieuw installeren herstelt je instellingen. Het is onhandig wanneer je het pakket juist verwijderde om met een schone configuratie opnieuw te beginnen. purge neemt de configuratie ook mee:

$ sudo apt purge wget
Purging configuration files for wget (1.21.4-1ubuntu4.4) ...

$ dpkg -l wget
dpkg-query: no packages found matching wget

Een nuttige gewoonte op een server: gebruik remove als je de software misschien terug wilt, en purge als je iets weghaalt dat je verkeerd geconfigureerd hebt.

Naar boven

5. Gemiddelde toepassingen

5.1 upgrade versus full-upgrade

Beide installeren nieuwere versies van wat je al hebt. Het verschil zit in wat ze daarvoor over hebben.

CommandoInstalleert nieuwe pakketten?Verwijdert pakketten?
apt upgrade Ja, als een upgrade ze nodig heeft Nee, nooit
apt full-upgrade Ja Ja, als dat de enige weg is
apt-get upgrade Nee Nee
apt-get dist-upgrade Ja Ja

full-upgrade en dist-upgrade zijn dezelfde bewerking onder twee namen. De veiligheidseigenschap van het kale upgrade is dat het nooit iets verwijdert, dus als de enige route naar een nieuwer pakket het weghalen van een ander is, ziet het ervan af en laat het dat pakket met rust. En als het dat doet, zegt het dat duidelijk.

5.2 "The following packages have been kept back"

Deze melding verontrust mensen, en meestal doet apt gewoon zijn werk goed. Je kunt hem bewust oproepen door een pakket vast te zetten, wat apt vertelt het nooit te veranderen:

$ sudo apt-mark hold libssl3t64
libssl3t64 set on hold.

$ sudo apt upgrade
The following packages have been kept back:
  libssl3t64
The following packages will be upgraded:
  libsystemd0 libudev1
2 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.

Zo'n hold overleeft herstarts en elke toekomstige upgrade totdat je hem opheft:

$ apt-mark showhold          # what is currently held
libssl3t64

$ sudo apt-mark unhold libssl3t64
Canceled hold on libssl3t64.

Holds zijn echt nuttig op een server waar een onderdeel op een bekende versie moet blijven, zoals een database waarvan de upgrade een onderhoudsvenster nodig heeft. Ze zijn ook makkelijk te vergeten, dus apt-mark showhold hoort in je checklist wanneer een machine op mysterieuze wijze geen updates meer krijgt.

Een hold is echter niet de enige oorzaak van een tegengehouden pakket. Op Ubuntu is de meest voorkomende oorzaak iets heel anders, en paragraaf 7.2 behandelt dat.

5.3 Opruimen wat niemand meer nodig heeft

Als apt een pakket installeert, legt het vast of jij erom vroeg of dat het als afhankelijkheid meekwam. Verwijder het ding waar je om vroeg, en de afhankelijkheden blijven staan, gemarkeerd als automatisch geinstalleerd en niet langer nodig.

Het effect is groter dan mensen verwachten. git installeren op een minimaal systeem trekt 46 pakketten mee; git daarna verwijderen laat er 42 verweesd achter:

$ sudo apt autoremove
0 upgraded, 0 newly installed, 42 to remove and 2 not upgraded.
Remv git-man
Remv krb5-locales
Remv less
Remv libcurl3t64-gnutls
...

Lees die lijst voordat je akkoord gaat. autoremove is het apt-commando dat je het snelst verrast, want "niets hangt hiervan af" is niet hetzelfde als "je wilt dit niet". Heb je iets met de hand geinstalleerd en denkt apt dat het als afhankelijkheid binnenkwam, dan biedt autoremove aan het te wissen. Je kunt de mening van apt corrigeren:

$ sudo apt-mark manual less      # I want this even if nothing depends on it
$ apt-mark showauto | wc -l      # how many packages are marked automatic

Twee verwante commando's maken schijfruimte vrij zonder software te verwijderen. apt clean leegt de cache met gedownloade .deb-bestanden, en apt autoclean verwijdert alleen de bestanden die niet meer te downloaden zijn:

$ du -sh /var/cache/apt/archives/     # downloaded .deb files
3.5M    /var/cache/apt/archives/
$ du -sh /var/lib/apt/lists/          # the package catalogue itself
345M    /var/lib/apt/lists/

Dat tweede getal verrast mensen op kleine servers. De catalogus is groot omdat hij elk pakket in elke ingestelde repository beschrijft, en hij groeit met elke repository die je toevoegt.

5.4 Wat heb ik vorige week veranderd?

apt houdt een logboek bij van elke transactie, en dat is de eerste plek om te kijken als een server zich anders gaat gedragen en niemand toegeeft eraan gezeten te hebben:

$ less /var/log/apt/history.log

Start-Date: 2026-08-11  09:48:42
Commandline: /usr/bin/unattended-upgrade
Upgrade: libsystemd0:amd64 (255.4-1ubuntu8.16, 255.4-1ubuntu8.17), ...
End-Date: 2026-08-11  09:48:52

Elke vermelding legt de datum vast, de exacte commandoregel, en elke pakketversie voor en na. Het veld Commandline is het waardevolle: het vertelt je of een mens de verandering doorvoerde of dat automatische updates het deden. Oudere logboeken worden ernaast geroteerd en gecomprimeerd, dus zless /var/log/apt/history.log.1.gz reikt verder terug.

Het achtervoegsel :amd64 bij die pakketnamen is multiarch, Debians ondersteuning voor het naast elkaar installeren van pakketten voor meer dan een architectuur. Het doet ertoe als je 32-bits bibliotheken op een 64-bits machine nodig hebt, of als een afhankelijkheid alleen door een specifieke architectuur vervuld kan worden:

$ dpkg --print-architecture              # the machine's native architecture
amd64
$ dpkg --print-foreign-architectures      # extra architectures enabled, if any

Op de meeste servers staat er niets in die tweede lijst, en dan is het achtervoegsel enkel ruis in de uitvoer. Zodra er een vreemde architectuur ingeschakeld is, zijn pakketnaam en versie niet meer genoeg om een pakket te identificeren en ga je pakket:architectuur in foutmeldingen tegenkomen.

Naar boven

6. Gevorderde toepassingen

6.1 Waar pakketten vandaan komen

apt kent alleen de repositories die je ingesteld hebt. Historisch betekende dat een bestand, /etc/apt/sources.list, met een repository per regel. Op Ubuntu 24.04 is dat bestand nu vrijwel leeg en zegt het dat ook:

$ cat /etc/apt/sources.list
# Ubuntu sources have moved to /etc/apt/sources.list.d/ubuntu.sources

De vervanging is het deb822-formaat: een blok met benoemde velden per repository, wat veel makkelijker te lezen en met configuratiegereedschap te beheren is.

$ cat /etc/apt/sources.list.d/ubuntu.sources
Types: deb
URIs: http://nl.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

Beide formaten werken nog, en een echte machine heeft er meestal een mengeling van, omdat installatieprogramma's van derden schrijven waarvoor ze gebouwd zijn. De oude vorm op een regel propt dezelfde informatie in een enkele regel:

$ cat /etc/apt/sources.list.d/docker.list
deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu focal stable

De velden zijn het kennen waard omdat ze veel gedrag verklaren. Suites noemt de release en zijn updatekanalen, dus noble-security is waar beveiligingsfixes binnenkomen. Components kiest de secties: op Ubuntu is main officieel ondersteund, is universe door de gemeenschap onderhouden, en bevatten restricted en multiverse stuurprogramma's en software met licentiebeperkingen. Als een pakket "niet bestaat", is de gebruikelijke oorzaak dat zijn component niet ingeschakeld is.

6.2 Ondertekeningssleutels en de apt-key-valkuil

apt vertrouwt een repository niet omdat jij het adres getypt hebt. Elke repository is cryptografisch ondertekend, en apt controleert de handtekening tegen een sleutel die jij geinstalleerd hebt. Dit is de beveiligingsgrens van het hele systeem: een aanvaller die het verkeer naar je mirror kan wijzigen, kan je nog steeds niet zijn pakket laten installeren.

De manier waarop je die sleutels installeert is veranderd, en heel veel gepubliceerd advies is nu ronduit schadelijk. De oude manier was apt-key, dat een sleutel toevoegt die voor elke repository op het systeem vertrouwd wordt:

$ apt-key list
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

Het probleem is de reikwijdte. Een sleutel die met apt-key add toegevoegd is, kan pakketten ondertekenen die beweren van alles te zijn, inclusief een vervanging voor je kernel of je SSH-server. Een repository van derden voor een teksteditor hoort dat niet te kunnen.

Het moderne patroon zet de sleutel in een eigen bestand en bindt hem met Signed-By aan een repository:

$ curl -fsSL https://example.com/key.gpg | sudo tee /etc/apt/keyrings/example.asc > /dev/null
$ echo "Types: deb
URIs: https://example.com/apt/
Suites: stable
Components: main
Signed-By: /etc/apt/keyrings/example.asc" | sudo tee /etc/apt/sources.list.d/example.sources

Nu wordt die sleutel voor die repository vertrouwd en voor niets anders. Kom je instructies tegen die je een sleutel in apt-key add laten pipen, dan dateren ze van voor 2022 en horen ze naar bovenstaande vorm vertaald te worden.

6.3 Wat er werkelijk in een pakket zit

Handtekeningen doen er meer toe dan ze op het eerste gezicht lijken, en de reden wordt duidelijk zodra je in een .deb kijkt. Je kunt er een downloaden zonder te installeren:

$ apt-get download tree
$ ls
tree_2.1.1-2ubuntu3.24.04.2_amd64.deb

Een .deb is een archief met twee helften: de bestanden die geinstalleerd worden, en een controlearchief dat het pakket beschrijft. dpkg-deb -I toont die tweede helft:

$ dpkg-deb -I tree_2.1.1-2ubuntu3.24.04.2_amd64.deb
 new Debian package, version 2.0.
 size 47360 bytes: control archive=746 bytes.
     595 bytes,    14 lines      control
     367 bytes,     6 lines      md5sums
 Package: tree
 Version: 2.1.1-2ubuntu3.24.04.2
 Architecture: amd64
 Installed-Size: 108
 Depends: libc6 (>= 2.38)

En dpkg-deb -c somt de bestanden op, met de paden die ze gaan innemen:

$ dpkg-deb -c tree_2.1.1-2ubuntu3.24.04.2_amd64.deb
drwxr-xr-x root/root         0 ./usr/bin/
-rwxr-xr-x root/root     85400 ./usr/bin/tree

Dat pakket is onschuldig. Kijk nu naar een pakket dat niet alleen uit bestanden bestaat. Het controlearchief van ca-certificates bevat drie uitvoerbare scripts, gemarkeerd met een sterretje:

$ dpkg-deb -I ca-certificates_20260601~24.04.1_all.deb
 size 139430 bytes: control archive=16630 bytes.
    9029 bytes,   163 lines   *  config               #!/bin/sh
     880 bytes,    21 lines      control
   13789 bytes,   138 lines      md5sums
    5817 bytes,   187 lines   *  postinst             #!/bin/sh
    1629 bytes,    65 lines   *  postrm               #!/bin/sh

Dit zijn maintainer-scripts, en er zijn vier mogelijke namen: preinst en postinst draaien voor en na het uitpakken van de bestanden, prerm en postrm voor en na het verwijderen. Het zijn gewone shellscripts, en dpkg draait ze als root.

Een pakket installeren is geen archief uitpakken. Het is andermans shellscripts draaien met volledige rechten op jouw machine. Dat is de hele reden dat apt weigert uit een niet-ondertekende repository te installeren, en de reden dat een repository van derden een echte vertrouwensbeslissing is en geen gemak.

Die scripts verklaren ook een regel die iedereen voorbij heeft zien scrollen en niemand leest. Debian-pakketten kunnen triggers registreren, die gedeeld werk uitstellen tot het einde van een transactie in plaats van het voor elk pakket te herhalen:

Processing triggers for libc-bin (2.39-0ubuntu8.8) ...
Processing triggers for man-db (2.12.0-4build2) ...

De index van handleidingen een keer opbouwen na het installeren van twintig pakketten is veel sneller dan hem twintig keer opbouwen. Als een installatie aan het einde lijkt te blijven hangen terwijl hij ogenschijnlijk klaar is, is dit meestal wat er gebeurt.

6.4 Welke versie krijg ik eigenlijk?

Als meerdere repositories hetzelfde pakket aanbieden, kiest apt op prioriteit. apt policy toont het hele plaatje, en met een pakketnaam beantwoordt het de specifieke vraag:

$ apt-cache policy bash
bash:
  Installed: 5.2.21-2ubuntu4
  Candidate: 5.2.21-2ubuntu4
  Version table:
 *** 5.2.21-2ubuntu4 500
        500 http://nl.archive.ubuntu.com/ubuntu noble/main amd64 Packages
        100 /var/lib/dpkg/status

Installed is wat je hebt, Candidate is wat een upgrade je zou geven, en de getallen zijn prioriteiten. De standaard is 500 voor een normale repository en 100 voor de al geinstalleerde versie, en daarom geeft apt de voorkeur aan een repositoryversie boven wat er op schijf staat, maar zet het je niet zomaar terug naar een oudere versie.

Dit commando is de snelste manier om "waarom installeert het die versie?" en "komt dit pakket wel uit de repository die ik denk?" te beantwoorden, wat ertoe doet als een repository van derden een distributiepakket overschaduwt.

Die versienummers zijn gestructureerd en niet willekeurig, en ze kunnen lezen is een nuttige vaardigheid:

[epoch:]upstream_version[-debian_revision]

1:2.43.0-1ubuntu7.3
|  |       |
|  |       +-- packaging revision: changes to the packaging, not the software
|  +---------- upstream version: what the software's own authors released
+------------- epoch: rarely present, and it overrides everything else

De epoch is de interessante. Versievergelijking is normaal gesproken mechanisch, maar af en toe wijzigt de oorspronkelijke maker zijn nummering zo dat de nieuwe release lager sorteert dan de oude. Een epoch is een handmatige overschrijving die zegt "geloof me, dit is nieuwer". Zodra een pakket een epoch heeft, houdt het die voor altijd, en daarom is git op Ubuntu versie 1:2.43.0-1ubuntu7.3 en niet 2.43.0-1ubuntu7.3.

Als de standaardprioriteiten niet zijn wat je wilt, kun je ze veranderen. Pinning woont in /etc/apt/preferences.d/ en past de prioriteit van een repository of een pakket aan, en zo gebruik je een pakket uit een nieuwere suite zonder het hele systeem mee te slepen:

$ cat /etc/apt/preferences.d/99-backports
Package: *
Pin: release a=noble-backports
Pin-Priority: 100

Pinning is krachtig en subtiel makkelijk verkeerd te doen, want de prioriteitsgetallen dragen specifieke betekenissen en zijn geen simpele rangorde. Controleer het resultaat altijd met apt-cache policy voordat je erop vertrouwt, en kies de kleinste regel die je probleem oplost.

6.5 Recommends: de reden dat installaties groter zijn dan je verwacht

Debian-pakketten drukken drie sterktes van verband uit. Depends is verplicht. Recommends is "bijna iedereen wil dit er ook bij", en apt installeert het standaard. Suggests is een hint, en apt negeert het.

Dat zijn de drie die je dagelijks tegenkomt, maar het pakketformaat kent er meer, en die zijn de reden dat afhankelijkheidsoplossing een solver is en geen boodschappenlijstje. Pre-Depends dwingt een volgorde af en eist dat een ander pakket eerst volledig geconfigureerd is. Conflicts en Breaks zeggen dat twee pakketten niet samen kunnen bestaan, of dat dit pakket een versie van een ander breekt. Replaces laat een pakket bestanden van een ander overnemen, en Provides laat meerdere pakketten een generieke naam vervullen, en zo kan een systeem een keuze uit mailservers of Java-runtimes bieden. apt moet een set versies vinden die aan al die verbanden tegelijk voldoet.

$ apt-cache show git | grep -E '^(Recommends|Suggests):'
Recommends: ca-certificates, patch, less, ssh-client
Suggests: gettext-base, git-daemon-run | git-daemon-sysvinit, git-doc, git-email, ...

Recommends zijn de reden dat een klein pakket een lange lijst mee kan trekken. Het effect is makkelijk te meten met -s (simuleren), dat laat zien wat er zou gebeuren zonder het te doen:

$ apt-get install -s git | grep 'newly installed'
1 upgraded, 46 newly installed, 0 to remove and 2 not upgraded.

$ apt-get install -s --no-install-recommends git | grep 'newly installed'
0 upgraded, 23 newly installed, 0 to remove and 3 not upgraded.

Precies de helft. Op een container-image of een kleine server is dat verschil de moeite waard, en daarom staat --no-install-recommends in vrijwel elke Dockerfile. Laat op een desktop de recommends aan staan: ze worden niet voor niets aanbevolen, en ze systeembreed uitzetten levert software op die stilletjes functies mist.

Die vlag -s verdient sowieso een plek in je gewoontes. Hij beantwoordt "wat zou dit doen?" voor elk apt-commando, volstrekt risicoloos.

6.6 Bijwerken zonder erbij te zijn

Een server die alleen gepatcht wordt als iemand eraan denkt, is een server die niet gepatcht wordt. Debian en Ubuntu leveren daarvoor unattended-upgrades, en op Ubuntu staat het meestal al geinstalleerd en aan, wat je in het logboek kunt bevestigen:

$ grep -c 'unattended-upgrade' /var/log/apt/history.log
$ cat /etc/apt/apt.conf.d/50unattended-upgrades      # what it is allowed to install
$ sudo unattended-upgrade --dry-run --debug          # what it would do right now

Het standaardbeleid installeert alleen beveiligingsupdates, en dat is voor de meeste servers de juiste ruil: echte bescherming, minimale kans dat een gedragsverandering om drie uur 's nachts iets breekt. De instelling die je bewust moet kiezen is Unattended-Upgrade::Automatic-Reboot, want een beveiligingsfix in de kernel doet niets tot de machine herstart, en een ongeplande herstart is zijn eigen soort storing.

Naar boven

7. Iets wat de meeste gebruikers niet weten

7.1 apt weet of je een mens bent

Hier is een waarschuwing die duizenden mensen in een CI-logboek gezien hebben en nog nooit in hun eigen terminal:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Het lijkt of hij willekeurig verschijnt. Dat doet hij niet. apt controleert of zijn uitvoer naar een terminal gaat of een pipe in, en waarschuwt alleen in het tweede geval. Je kunt het in twee commando's bewijzen:

$ apt list --installed | grep -c 'stable CLI interface'
1                      # output piped: warned

# same command with output going to the terminal: no warning at all

De waarschuwing richt zich precies op de situatie waarin het uitmaakt. Als jij interactief apt typt, is de formulering van de uitvoer drie seconden lang jouw probleem. Als iets die uitvoer uitleest, is de formulering een afhankelijkheid, en de apt-ontwikkelaars weigeren uitdrukkelijk te beloven dat die tussen releases niet verandert.

Dat is het echte verschil tussen de twee commando's, en het is een belofte en geen functielijst. apt-get heeft een stabiele interface waar scripts op mogen bouwen; apt mag zijn uitvoer wijzigen zodra er een mooiere opmaak langskomt. Vandaar: typ apt, script apt-get.

Die terminalcontrole duikt elders ook op. Sinds apt 1.9.11 gedraagt de vergrendeling zich anders afhankelijk van wie er meekijkt:

apt(8) now waits for the lock indefinitely if connected to a tty, or
for 120 seconds if not.

Een interactieve apt wacht dus geduldig terwijl unattended-upgrades klaar is, en een gescripte geeft na twee minuten op in plaats van een deployment eindeloos te laten hangen.

7.2 Twee identieke servers, verschillende updates

Je patcht twee servers die op dezelfde dag uit dezelfde image gebouwd zijn. De ene werkt een pakket bij, de andere meldt dat het tegengehouden is. Er staat niets op hold, er is niets gepind, en de machines zijn verder identiek. Dit is geen fout; het zijn gefaseerde updates die werken zoals bedoeld.

Ubuntu rolt updates geleidelijk uit om regressies op te sporen voordat ze iedereen bereiken. Een pakket kan een veld dragen dat zegt welk deel van de machines het al mag nemen:

Phased-Update-Percentage: 10

Het slimme zit in hoe een machine bepaalt of hij in die tien procent zit, en de handleiding apt_preferences schrijft het uit:

A system's eligibility to a phased update is determined by seeding
random number generator with the package source name, the version
number, and /etc/machine-id, and then calculating an integer in the
range [0, 100].  If this integer is larger than the
Phased-Update-Percentage, the version is pinned to 1, and thus held
back.

De identiteit van jouw machine zit in de startwaarde. Daarom zijn twee servers het oneens, en dat is opzettelijk: de beslissing ligt vast, zodat een machine niet bij elke keer wisselt tussen wel en niet aanbieden, maar hij verschilt per machine en per pakket, zodat de uitrol zich gelijkmatig spreidt.

Het betekent ook dat je er invloed op hebt. Wil je dat een vloot samen faseert, geef de machines dan dezelfde APT::Machine-ID. Wil je het wachten overslaan, bijvoorbeeld op een testmachine waar je de updates van morgen vandaag wilt:

$ sudo apt-get -o APT::Get::Always-Include-Phased-Updates=true upgrade

Voordat je daar op productie naar grijpt: bedenk wat die vertraging je oplevert, namelijk dat iemand anders de regressie als eerste ontdekt.

7.3 Het ongeluk dat apt veranderde

apt beschermde essentiele pakketten vroeger met een vraag. Als een verzoek iets zou verwijderen zonder welk het systeem niet kan functioneren, eiste het dat je een specifieke zin intypte:

You are about to do something potentially harmful.
To continue type in the phrase 'Yes, do as I say!'

In november 2021 liet een veelbekeken video precies zien wat die prompt waard is. Tijdens een uitdaging rond software-installatie probeerde de presentator van Linus Tech Tips, Steam te installeren op een Pop!_OS-systeem. Vanwege een onderliggend afhankelijkheidsconflict stelde de pakketbeheerder een ingrijpende oplossing voor: het verwijderen van de volledige desktopomgeving.

Ondanks een waarschuwingsvenster waarin de exacte zin "Ja, doe wat ik zeg!" moest worden ingevoerd, voerde de presentator het commando uit zonder zich bewust te zijn van de gevolgen. Na het opnieuw opstarten was de grafische interface verdwenen en bleef er alleen een kale tekstconsole over. Dit veelbesproken incident bewees dat bevestigingsvensters vaak slechts als een soort verkeersdrempels fungeren, wat ontwikkelaars ertoe aanzette de software bij te werken om het verwijderen van essentiële systeempakketten volledig te blokkeren.

apt is hierdoor gewijzigd, en in de release-opmerkingen op je eigen schijf wordt dit zonder veel ophef vermeld:

apt (2.3.12) unstable; urgency=medium

  The solver will no longer try to remove Essential or Protected packages,
  any dependency problem that would need such a solution will have to be
  resolved manually.

  The "Yes, do as I say" prompt for removing essential packages has been
  replaced by an error message.

  Thank you to Linus Tech Tips and System76 for bringing this issue
  to our attention.

De ontwerples is meer waard dan de anekdote. Een bevestigingsvraag waar een vastberaden gebruiker langs kan komen, is geen veiligheidsmechanisme, het is een drempel met papierwerk. De oplossing was de gevaarlijke bewerking standaard onmogelijk te maken en er een bewuste commandoregeloptie voor te eisen. Je kunt die vermelding zelf lezen met zless /usr/share/doc/apt/NEWS.Debian.gz, en dat is op elk systeem de moeite waard: het is een korte lijst van precies de gedragsveranderingen die je het meest kunnen verrassen.

7.4 Weten waar apt ophoudt

apt beheert software die je distributie verpakt. Veel van wat op een moderne server draait, is dat niet.

BehoefteGebruikWaarom
Een gedownloade .deb installeren apt install ./file.deb Let op: de ./ laat apt de afhankelijkheden oplossen, wat het kale dpkg -i niet doet
Uitzoeken welk pakket een bestand bezit dpkg -S Beantwoordt "wat heeft /usr/bin/x geinstalleerd?" direct
Nieuwere software dan je release levert backports, een leveranciersrepository of een container Een stabiele release bevriest versies bewust; vecht daar niet ter plekke tegen
Bibliotheken van programmeertalen pip, npm, composer Versies per project die apt niet kan uitdrukken; houd ze buiten systeemmappen
Een uitzichtloos conflict ontwarren aptitude Biedt interactief alternatieve oplossingen aan waar apt simpelweg weigert
Dezelfde opzet op veel servers Ansible, of een container-image Legt vast wat er geinstalleerd hoort te zijn in plaats van te vertrouwen op wat iemand ooit typte

Ik heb jarenlang .deb-pakketten geïnstalleerd met behulp van sudo dpkg -i package.deb Tijdens het schrijven van dit artikel ontdekte ik sudo apt install ./package.deb. Dit doet dezelfde lokale pakketinstallatie, maar met één belangrijk voordeel: apt kan ontbrekende afhankelijkheden automatisch ophalen en installeren.

Naar boven

8. Best practices

  • Draai altijd update voor install of upgrade. Handelen op een verouderde catalogus levert zowel "pakket niet gevonden" op als downloads van versies die niet meer bestaan.
  • Lees de samenvattingsregel voordat je op Enter drukt. Vooral de telling bij "to remove". Daar wonen de ongelukken.
  • Typ apt, script apt-get. Slechts een van beide belooft dat de uitvoer er volgend jaar hetzelfde uitziet.
  • Simuleer alles waar je niet zeker van bent. -s (of --simulate, of --dry-run) werkt op zowel apt als apt-get, drukt het hele plan af, en verandert niets.
  • Zet onbeheerde beveiligingsupdates op elke server aan. Kies daarna bewust het herstartbeleid in plaats van de standaard te laten staan.
  • Bind sleutels van derden aan hun eigen repository met Signed-By en een bestand in /etc/apt/keyrings/. Nooit apt-key add.
  • Controleer apt-mark showhold als een machine stopt met bijwerken. Een hold die maanden geleden tijdens een incident gezet is, is een klassieke oorzaak.
  • Gebruik --no-install-recommends voor containers en minimale servers, en laat recommends op desktops aan staan.
  • Lees de lijsten van autoremove voordat je akkoord gaat. "Niets hangt hiervan af" is niet hetzelfde als "je hebt het niet nodig".
  • Grijp naar de documentatie. De handleidingen zijn ongewoon goed, en NEWS.Debian.gz vertelt je welk gedrag veranderd is.
$ man apt                                 # the friendly command
$ man apt-get                             # the scripting interface
$ man sources.list                        # repository configuration, both formats
$ man apt_preferences                     # priorities, pinning, phased updates
$ man apt-patterns                        # the search syntax, since apt 2.0
$ zless /usr/share/doc/apt/NEWS.Debian.gz # behaviour changes worth knowing
Naar boven

9. Veelgemaakte fouten

9.1 Veelvoorkomende mythes

MytheWerkelijkheid
"apt update werkt mijn software bij." Het werkt alleen de catalogus bij. apt upgrade werkt software bij.
"apt is gewoon een kortere alias voor apt-get." Losse programma's met verschillend gedrag. Alleen apt-get belooft een stabiele interface voor scripts.
"'Unable to locate package' betekent dat het niet verpakt is." Meestal betekent het geen apt update, of dat de component (universe) niet ingeschakeld is.
"apt remove verwijdert een pakket volledig." Configuratiebestanden blijven staan, en dpkg noteert het als rc. apt purge haalt die ook weg.
"Tegengehouden pakketten betekenen dat er iets stuk is." Meestal een hold, of Ubuntu's gefaseerde uitrol die besluit dat deze machine nog niet aan de beurt is.
"apt-key add is hoe je een repository vertrouwt." Verouderd, en het vertrouwt die sleutel voor elke repository. Gebruik Signed-By met een bestand in /etc/apt/keyrings/.

9.2 Valkuilen om te vermijden

  • autoremove draaien zonder de lijst te lezen. Het verwijdert vrolijk een kernel, een stuurprogramma, of het zelfgebouwde gereedschap waarvan apt denkt dat het een afhankelijkheid was.
  • dpkg -i voor een gedownload pakket. Het kan geen afhankelijkheden ophalen en laat het pakket half geconfigureerd achter. Gebruik apt install ./file.deb, of apt --fix-broken install om te herstellen.
  • Een repository toevoegen die voor een andere release gebouwd is. Een focal-repository op een noble-machine installeert pakketten die tegen de verkeerde bibliotheken gelinkt zijn, en de schade komt later aan het licht.
  • apt midden in een transactie afbreken. Je houdt een lockbestand en een half geconfigureerd pakket over. sudo dpkg --configure -a is meestal de weg terug; lockbestanden met de hand verwijderen terwijl apt draait niet.
  • Aannemen dat upgrade alles dekt. Het verwijdert nooit pakketten, dus sommige upgrades wachten eeuwig. Controleer periodiek met full-upgrade --dry-run.
  • /boot vergeten. Kernelpakketten stapelen zich op en een kleine /boot-partitie loopt vol, waarna upgrades verwarrend mislukken. Moderne apt verwijdert ongebruikte kernels bij full-upgrade, maar alleen bij dat commando.
  • Uitvoer van apt een script in pipen. De formulering ligt niet vast, en apt waarschuwt je daar precies voor.
  • pip of npm door systeemmappen heen mengen. Installeren over bestanden die apt bezit levert schade op die geen enkel apt-commando kan verklaren. Gebruik virtuele omgevingen of installaties per project.
Naar boven

10. Samenvatting

apt lijkt op twee commando's die je op je eerste dag uit je hoofd leert. In werkelijkheid is het de afhankelijkhedenoplosser, downloader en vertrouwenssysteem waar al het andere op een Debian- of Ubuntu-machine op gebouwd is.

  • APT betekent Advanced Package Tool. Het lost afhankelijkheden op en downloadt pakketten; dpkg eronder doet het daadwerkelijke installeren.
  • apt update ververst de catalogus, apt upgrade installeert nieuwere versies, en full-upgrade doet hetzelfde maar mag pakketten verwijderen om er te komen.
  • Het begon als apt 0.0.1 op 31 maart 1998, "alleen op IRC uitgebracht", en kwam in 1999 mee in Debian 2.1. Het commando apt zelf kwam pas in april 2014, "10000b years in the making".
  • "Unable to locate package" betekent vrijwel altijd een ontbrekende apt update of een uitgeschakelde component, niet een ontbrekend pakket.
  • remove laat configuratiebestanden staan en dpkg markeert het pakket als rc; purge haalt die ook weg.
  • Recommends worden standaard geinstalleerd en verklaren grote installaties. --no-install-recommends bracht een git-installatie terug van 46 naar 23 pakketten.
  • apt-mark hold zet een pakket vast en levert "kept back" op; apt-mark showhold is het eerste om te controleren als een machine stopt met bijwerken.
  • Repositories staan in /etc/apt/sources.list.d/, steeds vaker in het deb822-formaat .sources, en elk hoort met Signed-By aan zijn eigen sleutel gebonden te worden.
  • apt drukt zijn waarschuwing over de niet-stabiele CLI alleen af als de uitvoer niet naar een terminal gaat. Typ apt, script apt-get.
  • Ubuntu's gefaseerde updates gebruiken het pakket, de versie en /etc/machine-id als startwaarde, en daarom krijgen twee identieke servers terecht verschillende updates.
  • Sinds apt 2.3.12 weigert de solver essentiele pakketten nog te verwijderen, nadat een publiek ongeluk liet zien dat een bevestigingsvraag geen veiligheidsmechanisme is.
  • Een pakket installeren draait zijn preinst- en postinst-scripts als root, en daarom zijn repositoryhandtekeningen en het afbakenen met Signed-By de echte beveiligingsgrens.
  • Versienummers zijn [epoch:]upstream-revision; de zeldzame 1: ervoor is een epoch die de normale versievolgorde overschrijft, en pinning in /etc/apt/preferences.d/ overschrijft repositoryprioriteiten.
  • Twijfel je, simuleer dan: apt-get install -s en apt upgrade --dry-run drukken het hele plan af en veranderen niets.

Dit is het overzicht dat je het beste kunt bewaren:

apt update                     refresh the catalogue (installs nothing)
apt upgrade                    install newer versions, never removing anything
apt full-upgrade               as above, but may remove packages to succeed
apt install PKG                install a package
apt install ./file.deb         install a downloaded .deb WITH dependencies
apt remove PKG                 uninstall, keeping configuration files
apt purge PKG                  uninstall, including configuration files
apt autoremove                 delete orphaned dependencies (read the list!)

apt search TEXT                search names and descriptions
apt show PKG                   version, size, dependencies, origin
apt list -a PKG                every version apt knows about
apt list --upgradable          what an upgrade would change
apt-cache policy PKG           which version, from which repository, and why
apt-get install -s PKG         simulate: print the plan, change nothing
apt-get download PKG           fetch the .deb without installing it
apt-config dump                apt's effective configuration
dpkg-deb -I file.deb           a package's control data and maintainer scripts
dpkg-deb -c file.deb           the files a package would install

apt-mark hold PKG              freeze a package at its current version
apt-mark showhold              list frozen packages
apt-mark manual PKG            "I want this", protect it from autoremove
dpkg -l PKG                    package state: ii installed, rc removed-but-config
dpkg -S /path/to/file          which package owns this file
dpkg --configure -a            recover from an interrupted transaction

Pakketbeheer is waar de meeste serverellende ofwel begint ofwel opgelost wordt: de upgrade die nooit is toegepast, de repository van derden die niemand gedocumenteerd heeft, de schijf die volliep met oude kernels.

Naar boven
Linux commando: apt
Peter Martin
Peter Martin
Joomla Specialist

Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.

Gerelateerde artikelen