// Datei: ./praxis/paketkonfiguration-sichern.adoc

// Baustelle: Rohtext

[[paketkonfiguration-sichern]]
== Paketkonfiguration sichern ==

// Stichworte für den Index
(((debconf-get-selections)))
(((debconf-set-selections)))
(((Debianpaket, apt-clone)))
(((Debianpaket, debconf)))
(((Debianpaket, debconf-utils)))
(((Debianpaket, dpkg)))
(((Paketkonfiguration, Klonen einer bestehenden Installation)))
(((Paketkonfiguration, bestehende Installation sichern)))
(((Paketkonfiguration, debconf-get-selections)))
(((Paketkonfiguration, debconf-set-selections)))
(((Paketkonfiguration, gesicherte Konfiguration wieder einspielen)))
(((Paketliste, verstehen)))

Betreuen Sie eine Reihe von Rechnern, die jeweils aktuell und zumindest 
bezogen auf die Paketauswahl identisch bleiben müssen, ist das manuelle 
Sichern, Pflegen und Einspielen einer Paketliste etwas mühselig. Der 
händische Abgleich mit Hilfe von `dpkg` und `diff` braucht einfach zu lange, 
ist zudem fehleranfällig und hält Sie von weitaus spannenderen Aufgaben auf 
ihrem System ab. 

Daher schauen wir uns in diesem Kapitel verschiedene Wege an, um diese Schritte 
möglichst zu automatisieren. Unterteilt haben wir das in das Auslesen der 
Paketkonfiguration und das Einspielen der zuvor gesicherten Paketkonfiguration. 
Zum Einsatz kommen dabei die Werkzeuge `dpkg` (siehe 
<<paketkonfiguration-sichern-mit-dpkg>>), `apt` (siehe
<<paketkonfiguration-sichern-mit-apt>>), `debconf-get-selections` (siehe 
<<paketkonfiguration-sichern-mit-debconf-get-selections>>), 
`debconf-set-selections` (siehe 
<<paketkonfiguration-wieder-einspielen-mit-debconf-set-selections>>) und 
`apt-clone` (siehe <<paketkonfiguration-sichern-mit-apt-clone>> und 
<<paketkonfiguration-wieder-einspielen-mit-apt-clone>>). Zum Schluß reißen wir 
eine Auswahl graphischer Werkzeuge kurz an (siehe 
<<paketkonfiguration-sichern-graphische-werkzeuge>>).

[[paketkonfiguration-auslesen]]
=== Die bestehende Paketkonfiguration auslesen ===

// Stichworte für den Index
(((Paketkonfiguration, auslesen)))
Zunächst gehen wir der Frage nach, wie Sie die bestehende Konfiguration
ihrer installierten Pakete auslesen und sichern. Das nutzen Sie in einem 
späteren Schritt, um diese Pakete wieder einspielen zu können -- sei es auf 
dem gleichen System oder einem neuen Rechner, welcher identisch zum 
erstgenannten werden muss. Alle benötigten Informationen dazu stehen in der 
Debconf-Datenbank.

[[paketkonfiguration-sichern-mit-dpkg]]
==== Mit `dpkg` ====

// Stichworte für den Index
(((Debianpaket, dpkg)))
(((dpkg, -l)))
(((dpkg, --get-selections)))
(((dpkg, --list)))
Wie bereits in <<liste-der-installierten-pakete-anzeigen-und-deuten>> erklärt,
ist `dpkg` das zentrale Werkzeug, um die Paketdatenbank auszulesen und Ihnen 
die derzeit installierten und vollständig konfigurierten Pakete auf der 
Standardausgabe (`stdout`) aufzulisten. Über das nachfolgend gezeigte Kommando 
erhalten Sie eine entsprechende Liste mit den Namen der Pakete. 

`egrep` filtert zunächst nur die Zeilen aus der Ausgabe von `dpkg` heraus, die 
mit `ii` beginnen -- sprich: die installierten und konfigurierten Pakete. Die 
zusätzlichen informationen wie Installationsstatus, Kurzbeschreibung und die 
Version des jeweiligen Pakets werden dann mit Hilfe von `awk` aus jeder 
verbliebenen Zeile herausgefiltert. Anschließend wird die Liste der Paketnamen 
mit Hilfe von `sort` noch alphabetisch aufsteigend sortiert. Die Ausgabe des 
Kommandos landet in der Datei `paketliste` im aktuellen Verzeichnis:

.Liste der installierten Pakete namentlich sortiert in einer Datei ablegen (Version 1)
----
$ dpkg -l | egrep "^ii" | awk ' { print $2 } ' | sort > paketliste
$
---- 

Um den Aufwand zu verringern, ist der Schalter `--get-selections` spannend. 
Dieser sorgt dafür, daß `dpkg` nur den Paketnamen samt Installationsstatus
ausgibt. Kombiniert mit `grep` und `awk` bauen Sie sich daraus eine sortierte
Liste wie folgt:

.Liste der installierten Pakete namentlich sortiert in einer Datei ablegen (Version 2)
----
$ dpkg --get-selections | grep -v deinstall | awk ' { print $1 } ' > paketliste
$
----

Diese soeben erzeugten Liste nutzen Sie als Referenz, um nun andere Systeme 
identisch aufzusetzen. Wie das geht, lesen Sie in 
<<paketkonfiguration-wieder-einspielen-mit-apt-get>> nach.

[[paketkonfiguration-sichern-mit-apt]]
==== Mit `apt` ====

// Stichworte für den Index
(((Debianpaket, apt)))
(((apt, list --installed)))
Die Kombination aus `apt`, `awk` und `tail` liefert Ihnen ebenfalls eine Liste 
der installierten Pakete in alphabetisch aufsteigender Sortierung:

.`apt` zur Erstellung der Paketliste benutzen
----
# apt list --installed | awk -F "/" ' { print $1 } ' | tail -n +2 > paketliste
# cat paketliste
aapt
acl
acpi
adduser
adwaita-icon-theme
alsa-base
alsa-utils
anacron
android-framework-res
...
#
----

Bitte beachten Sie, daß `apt` nur die Namen der Pakete ermittelt. Sämtliche 
Konfiguration bleibt unbeachtet.

[[paketkonfiguration-sichern-mit-debconf-get-selections]]
==== Mit `debconf-get-selections` ====

// Stichworte für den Index
(((Automatisierte Installation, Preseeding)))
(((debconf-get-selections)))
(((Debianpaket, debconf-utils)))
Das Werkzeug `debconf-get-selections` aus dem Paket 'debconf-utils' 
<<Debian-Paket-debconf-utils>> erzeugt eine Liste der Pakete, die installiert 
sind und für die eine weitere Konfiguration durch APT bei der Installation des
Paketes notwendig ist. Das Verfahren kommt im Rahmen des sogenannten 
'preseeding' zum Einsatz, auf Deutsch mit 'Vorbelegen von Konfigurationswerten' 
übersetzbar. 

Die Ausgabe von `debconf-get-selections` umfaßt den Paketnamen und dessen 
Konfiguration, sprich: die Fragen plus die Antworten, aus denen Sie bei der 
Installation des Paketes durch APT wählen können sowie ihre tatsächliche 
Antwort. Der nachfolgende Ausschnitt zeigt das für das Paket 'cups':

.Die Ausgabe von `debconf-get-selections`
----
...
# Backends für die Kommunikation mit dem Drucker:
# Choices: lpd, Socket, USB, SNMP, dnssd
cups	cupsys/backend	multiselect	lpd, socket, usb, snmp, dnssd
...
----

<<fig.dpkg-reconfigure-cups>> zeigt den dazugehörigen Konfigurationsdialog, den
Sie auch stets mit Hilfe von `dpkg-reconfigure cups` erreichen können.

.Fragen zum Paket 'cups'
image::praxis/paketkonfiguration-sichern/dpkg-reconfigure-cups.png[id="fig.dpkg-reconfigure-cups", width="50%"]

Die Ausgabe von `debconf-get-selections` erfolgt auf der Standardausgabe 
(`stdout`). Eine Liste in einer Datei `paketliste`, die lediglich die 
Paketnamen in sortierter Reihenfolge enthält, erzeugen Sie mit Hilfe der 
Kombination aus den fünf Werkzeugen `debconf-get-selection`, `grep`, `awk`, 
`sort` und `uniq` wie folgt:

.Auslesen der bestehenden Paketkonfiguration aus der Debconf-Datenbank
----
$ debconf-get-selections | grep -v "^#" | awk ' { print $1 } ' | sort | uniq > paketliste
$
----

In <<paketkonfiguration-wieder-einspielen-mit-debconf-set-selections>> lesen 
Sie, wie Sie die erzeugte Liste benutzen, um die darin genannten Pakete auf 
einem anderen System wieder einzuspielen.

[[paketkonfiguration-sichern-mit-apt-clone]]
==== Mit `apt-clone` ====

// Stichworte für den Index
(((apt-clone)))
(((apt-clone, clone)))
(((apt-clone, info)))
(((Debianpaket, apt-clone)))
(((Debianpaket, dpkg-repack)))
(((dpkg-repack)))
(((Ubuntupaket, apt-clone)))

Dieses Werkzeug steht über die gleichnamigen Pakete bei Debian und Ubuntu 
bereit (siehe <<Debian-Paket-apt-clone>> und <<Ubuntu-Paket-apt-clone>>).
Es sieht sich selbst als 'helper script', welches das Klonen einer bestehenden
Linuxinstallation vereinfacht. 

Das Debian- bzw. Ubuntupaket beinhaltet das Python-Skript `apt-clone` sowie 
eine passende, gleichnamige Python-Klasse für Python 3. Intern ruft es das 
Werkzeug `dpkg-repack` <<Debian-Paket-dpkg-repack>> auf, welches aus den 
bereits installierten Dateien wieder Binärpakete erstellt, sofern das möglich 
ist.

Es stellt beim Aufruf nach Möglichkeit auf dem Bestandssystem so viele 
Informationen zur zu klonenden Installation zusammen, wie möglich sind. Das 
umfasst: 

* die Paketquellen über die Datei `/etc/apt/sources.list` 
* die Paketquellen über das komplette Verzeichnis `/etc/apt/sources.list.d` 
samt Inhalt
* die hinterlegten Voreinstellungen über das Verzeichnis `/etc/apt/preferences.d/`
* den Debian-Schlüsselring mit den darin hinterlegten GPG-Schlüsseln für die 
verwendeten Paketquellen unter `/etc/apt/trusted.gpg` und dem Verzeichnis 
`/etc/apt/trusted.gpg.d`
* den Paketstatus aus der Paketdatenbank
* die zusätzlichen Pakete, d.h. Pakete, die nicht über die hinterlegten
Paketquellen installiert wurden. Dazu legt es im Archiv ein Verzeichnis
`/var/lib/apt-clone/debs` an.
* die Pakete, die nicht mehr von den Paketquellen heruntergeladen werden können. 
Diese landen ebenfalls unter `/var/lib/apt-clone/debs` im Archiv. Dazu bedient 
sich `apt-clone` des Werkzeugs `dpkg-repack` <<Debian-Paket-dpkg-repack>>. Im 
nachfolgenden Beispiel sehen Sie, dass das nicht immer sauber gelingt und auch 
zu Paketen führen kann, die defekt sind (`broken`) -- d.h. unvollständige 
Abhängigkeiten besitzen -- und nicht ohne weiteres wiedereinspielbar sind.

Bevor Sie `apt-clone clone` ausführen, legen Sie ein (lokales) Verzeichnis 
fest, in dem das Archiv abgelegt werden soll. Im nachfolgenden Beispiel heißt 
das lokale Verzeichnis schlicht und einfach `packagelist`. Ergebnis des 
Aufrufs von `apt-clone` ist ein Archiv im Format `tar.gz`, welches Sie auf 
dem Zielsystem wieder mit Hilfe von `apt-clone` einspielen (siehe
<<paketkonfiguration-wieder-einspielen-mit-apt-clone>>).

`apt-clone` liest alle installierten Pakete auf dem Ursprungsrechner ein. 
Möchten Sie ebenfalls alle zusätzlichen, manuell installierten Pakete mit
erfassen, geben Sie beim Aufruf den Schalter `--with-dpkg-repack` mit an.

.`apt-clone` sammelt Informationen
----
# apt-clone clone --with-dpkg-repack packagelist/.
dpkg-deb: building package 'sge' in './sge_8.1.8_amd64.deb'.
dpkg-deb: building package 'libnccl2' in './libnccl2_2.3.5-2+cuda10.0_amd64.deb'.
dpkg-repack: warning: unknown information field 'Original-Maintainer' in input data in entry in dpkg's status file
dpkg-deb: building package 'lesstif2' in './lesstif2_0.95.2-1_amd64.deb'.
dpkg-repack: warning: unknown information field 'Original-Maintainer' in input data in entry in dpkg's status file
dpkg-deb: building package 'libcudnn7' in './libcudnn7_7.3.1.20-1+cuda10.0_amd64.deb'.
dpkg-deb: building package 'libcudnn7-dev' in './libcudnn7-dev_7.3.1.20-1+cuda10.0_amd64.deb'.
dpkg-deb: error: conffile '/opt/sge/util/install_modules/inst_template.conf' does not appear in package
dpkg-repack: Error running: dpkg-deb --build dpkg-repack.sge-common.3EAu1a .
dpkg-repack: Problems were encountered in processing.
dpkg-repack: The package may be broken.
not installable: sge, libnccl2, lesstif2, libdb5.1, libcudnn7, libcudnn7-dev, sge-common, cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48, libnccl-dev, libxp6, db5.1-util, libdb5.1++
version mismatch: libssl1.1, mdadm, python3-distutils, libitm1, libmagic-mgc, samba-libs, lxd-client, wget, postfix, cpp, 
...
# 
----

Das Archiv wird im vorgenannten Verzeichnis erzeugt. Der Name des Archivs 
setzt sich aus `apt-clone-state-` und dem Hostnamen zusammen, also bspw. 
`apt-clone-state-kiste.tar.gz` für den Computer mit dem Hostnamen `kiste`. 
Mit dem Schalter `info` analysieren Sie das soeben erzeugte Archiv. 
Nachfolgendes Listing stammt von einem Archiv für ein Ubuntu 18 'Bionic', 
welcher den Rechnernamen 'kiste' trägt:

.Informationen zum erzeugten `apt-clone`-Archiv anzeigen
----
$ apt-clone info apt-clone-state-kiste.tar.gz 
Hostname: kiste
Arch: amd64
Distro: bionic
Meta: 
Installed: 1301 pkgs (751 automatic)
Date: Tue Oct 15 14:55:03 2019
$
----

Bitte beachten Sie bei der Verwendung von `apt-clone` noch die folgenden Punkte:

* Das Zielsystem muss das gleiche Betriebssystem und die gleiche Veröffentlichung
wie das Originalsystem besitzen.

* `apt-clone` gleicht den Paketbestand des Originalsystems mit den Paketquellen 
ab. Es merkt an, wenn installierte Pakete nicht mehr aktuell sind und im 
Paketmirror bereits eine neuere Version vorliegt. Um das o.g. erzeugte Archiv 
möglichst klein zu halten, aktualisieren Sie das Originalsystem vor dem Aufruf von 
`apt-clone`, sofern das möglich und auch praktikabel ist (siehe 
<<pakete-aktualisieren>>) und dem Vorgehen nichts entgegenspricht.

* Räumen Sie ihr Originalsystem vor dem Klonen auf. Entfernen Sie nicht mehr 
benötigte Software und auch verwaiste Pakete, bspw. über das Kommando
`apt-get autoremove` (siehe <<umgang-mit-waisen>>).

* `apt-clone` benachrichtigt Sie, wenn Dateien vorliegen, die nicht im 
Originalpaket enthalten sind, bspw. Konfigurationsdateien. Es ist so angelegt,
dass es bestehende, geänderte Dateien übernimmt und somit eine exakte Kopie des
Zustands des installierten Pakets erzeugt.

* `apt-clone` gibt am Ende eine Liste der Pakete aus, die es für nicht 
installierbar hält.

* Führen Sie `apt-clone` später auf dem Zielsystem aus, überschreibt es ihre 
bereits bestehende Paketliste. Es löscht Pakete bzw. installiert fehlende nach
(siehe <<paketkonfiguration-wieder-einspielen-mit-apt-clone>>).

[[paketkonfiguration-einspielen]]
=== Eine gesicherte Paketkonfiguration wieder einspielen ===

// Stichworte für den Index
(((Paketkonfiguration, gesicherte Konfiguration wieder einspielen)))

[[paketkonfiguration-wieder-einspielen-mit-apt-get]]
==== Mit `apt-get` ====

// Stichworte für den Index
(((Debianpaket, apt)))
(((apt-get, install)))
Haben Sie eine Paketliste wie in <<paketkonfiguration-sichern-mit-dpkg>> erzeugt,
ist das Einspielen dieser Liste auf einem neuen System vergleichsweise einfach, 
bspw. mit diesem Aufruf:

.Einspielen der gespeicherten Paketliste mit Hilfe von `apt-get`
----
# apt-get install < paketliste
...
#
----

Bitte beachten Sie, dass in der Paketliste keine Konfigurationsdateien enthalten
sind. Beim Einspielen bzw. Installieren des jeweiligen Pakets werden die Dateien 
daraus extrahiert oder neu erzeugt.

[[paketkonfiguration-wieder-einspielen-mit-debconf-set-selections]]
==== Mit `debconf-set-selections` ====

// Stichworte für den Index
(((Automatisierte Installation, Preseeding)))
(((debconf-set-selections, -c)))
(((debconf-set-selections, -v)))
(((debconf-set-selections, --checkonly)))
(((debconf-set-selections, --verbose)))
(((Debianpaket, debconf-utils)))

Haben Sie zuvor eine Liste der Pakete samt deren Voreinstellung mit Hilfe des 
Werkzeugs `debconf-get-selections` erstellt (siehe 
<<paketkonfiguration-sichern-mit-debconf-get-selections>>), ist 
`debconf-set-selections` das passende Gegenstück dazu. Sie finden es ebenfalls
im Paket 'debconf-utils' <<Debian-Paket-debconf-utils>>. Darüber spielen Sie 
diese Liste auf dem Zielsystem wieder ein. Das Werkzeug bietet Ihnen diese 
hilfreichen Schalter an:

`-c` (Langform `--checkonly`) :: Eingabedatei nur auf Fehler prüfen

`-v` (Langform `--verbose`) :: ausführliche Ausgabe beim Einspielen

Über den folgenden Aufruf spielen Sie die gespeicherte Konfiguration als 
Benutzer mit administrativen Rechten wieder ein:

.Einspielen der gespeicherten Konfiguration mit Hilfe von `debconf-set-selections`
----
# debconf-set-selections paketliste
...
#
----

Verwenden Sie eine Datei, die lediglich aus den Namen der Pakete besteht,
hilft Ihnen dieses Kommando beim Wiedereinspielen:

.Einspielen der gespeicherten Paketliste mit Hilfe von `xargs` und `apt-get`
----
# xargs -a "paketliste" apt-get install -y
...
#
----

[[paketkonfiguration-wieder-einspielen-mit-apt-clone]]
==== Mit `apt-clone` ====

// Stichworte für den Index
(((apt-clone)))
(((apt-clone, restore)))
(((apt-clone, restore-new-distro)))
(((Debianpaket, apt-clone)))
(((Ubuntupaket, apt-clone)))

Haben Sie zuvor ein Archiv wie unter <<paketkonfiguration-sichern-mit-apt-clone>> 
beschrieben erstellt, lernen Sie nun, wie Sie das auf dem Zielsystem einspielen. 
Als erstes übertragen Sie das Archiv auf ihr Zielsystem, bspw. per USB-Stick, 
externe Festplatte oder mit Hilfe des Kommandos `scp`. 

Ist das erfolgt, rufen Sie auf dem Zielsystem `apt-clone` als administrativer 
Benutzer mit dem Schalter `restore` und dem Namen des zuvor erzeugten Archivs 
auf. Daraufhin entpackt `apt-clone` das Archiv und spielt die darin enthaltenen
Pakete samt deren Konfiguration auf wieder dem Zielsystem ein. 

.Mit `apt-clone` erzeugte Paketkonfiguration wieder einspielen
----
# apt-clone restore apt-clone-state-kiste.tar.gz
...
# 
----

Bei der Ausführung greift `apt-clone` auf die Mechanismen der Paketverwaltung 
zurück. Fehlende Pakete werden somit heruntergeladen und eingerichtet und die 
Paketabhängigkeiten sauber aufgelöst. Das funktioniert reibungslos, wenn 
Original- und Zielsystem die gleiche Version bzw. Veröffentlichung der 
Distribution benutzen.

Das Werkzeug `apt-clone` bietet zwei Schalter an:

`restore`:: packe das Archiv aus und spiele den Paketbestand auf dem
Zielsystem ein

`restore-new-distro`:: packe das Archiv aus, spiele den Paketbestand 
auf dem Zielsystem ein und aktualisiere diesen, sofern möglich

Letzteres kann genutzt werden, um das Einspielen und Aktualisieren eines
Systems in einem einzigen Aufruf durchzuführen.

[[paketkonfiguration-sichern-graphische-werkzeuge]]
=== Graphische Werkzeuge ===

==== Aptik ====

// Stichworte für den Index
(((aptik)))
(((aptik-gtk)))
(((Ubuntupaket, aptik)))

Seit einigen Jahren steht Aptik für Ubuntu über die Projektseite <<aptik>> 
bereit. Bislang ist es nur nur als PPA für Ubuntu verfügbar und enthält die 
beiden Werkzeuge `aptik` und `aptik-gtk`. Letzteres ist ein graphisches 
Werkzeug zum Backup und dem Wiedereinspielen von Paketlisten, dem Paketcache 
und der installierten Software. Bislang kostenfrei, wurde inzwischen das
Vertriebsmodell geändert und die aktuelle Version ist kostenpflichtig.

==== Mintbackup ====

// Stichworte für den Index
(((mintbackup)))

Für Linux Mint steht das Werkzeug `mintbackup` bereit <<mintbackup>>. Es ist
ein graphisches Werkzeug, welches Paketlisten sichern und wieder einspielen
kann.

.Sicherungsdialog von Mintbackup
image::praxis/paketkonfiguration-sichern/mintbackup.png[id="fig.mintbackup", width="50%"]

// Datei (Ende): ./praxis/paketkonfiguration-sichern.adoc
