Nicht nur bei Systemen die vom Internet abgeschottet sind macht das anlegen eines lokalen mirrors (spiegeln) eines CentOS (RedHat) oder Ubuntu repositories Sinn. Man kann dann z.B. auch einzelne Versionsstände „einfrieren“, so dass diese während einem Zeitraum immer dieselben Paket haben und dann etwa quartalsweise aktualisieren.
In diesem Beitrag lernt ihr alles was es zum spiegeln der beiden repositories braucht, wie ihr Repositories einzelner Pakte anlegt und wie ihr unterschiedliche Versionsstände verwalten könnt.
Grundsätzlich braucht es für RPM und DEB basierte repositories unterschiedliche tools, da diese verschieden aufgebaut sind.
Inhalt
Mirror eines RPM (Redhat) repositories
Ein RPM repository kann mit rsync synchronisiert werden. Danach muss noch der GPG Public Key mit wget heruntergleaden werden:
rsync -avSHP --delete rsync://linuxsoft.cern.ch/centos/8 "/srv/repository/centos/8/"
wget -P /srv/repository/centos/8/ wget https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official
Nachfolgend ein Script, welches das aktuelle CentOS und EPEL repository synchronisiert und zudem noch z.B. die ISOs ausschliesst und täglich per cronjob aufgerufen werden kann:
mirror-sync-centos.sh
#!/bin/bash
set -euo pipefail
### CentOS
centosdir=/srv/repository/current/centos
rsync_lock_prefix=/var/run/rsync_updates_centos
rsync_url=rsync://linuxsoft.cern.ch/centos
if [ -f ${rsync_lock_prefix} ]; then
logger -i -t "$0" -p INFO "Updates via rsync for CentOS already running."
else
if [ -d ${centosdir} ] ; then
logger -i -t "$0" -p INFO "touch ${rsync_lock_prefix}";
touch ${rsync_lock_prefix};
if [ $? != 0 ]; then
logger -i -t "$0" -p INFO "exit 1"
exit 1
fi
logger -i -t "$0" -p INFO "/usr/bin/rsync --bwlimit=4m -avSHP --delete --exclude \"local*\" --exclude \"isos\" ${rsync_url}/ ${centosdir}/;";
/usr/bin/rsync --exclude="local*" --exclude="isos" --exclude="altarch" --exclude="*aarch64*" --exclude="playground" -avSHP --delete ${rsync_url}/ ${centosdir}/;
logger -i -t "$0" -p INFO "/bin/rm -f ${rsync_lock_prefix}";
/bin/rm -f ${rsync_lock_prefix};
else
logger -i -t "$0" -p INFO "Target directory ${centosdir} not present."
fi
fi
### EPEL
epeldir=/srv/repository/current/epel
epel_rsync_lock_prefix=/var/run/rsync_updates_epel
epel_rsync_url=rsync://linuxsoft.cern.ch/epel
if [ -f ${epel_rsync_lock_prefix} ]; then
logger -i -t "$0" -p INFO "Updates via rsync for EPEL already running."
else
if [ -d ${epeldir} ] ; then
logger -i -t "$0" -p INFO "touch ${epel_rsync_lock_prefix}";
touch ${epel_rsync_lock_prefix};
if [ $? != 0 ]; then
logger -i -t "$0" -p INFO "exit 1"
exit 1
fi
logger -i -t "$0" -p INFO "/usr/bin/rsync --bwlimit=4m -avSHP --delete --exclude \"local*\" --exclude \"isos\" ${epel_rsync_url}/ ${epeldir}/;";
/usr/bin/rsync --exclude="local*" --exclude="isos" --exclude="playground" -avSHP --delete ${epel_rsync_url}/ ${epeldir}/;
logger -i -t "$0" -p INFO "/bin/rm -f ${epel_rsync_lock_prefix}";
/bin/rm -f ${epel_rsync_lock_prefix};
else
logger -i -t "$0" -p INFO "Target directory ${epeldir} not present."
fi
fi
Mirror eines RPM Paket repositories
Repositories einzelner Pakete (z.B. icinga2) kann man mit dem Tool reposync
mirroren.
Das tool setze ein installiertes yum
voraus; der Paketmanager „yum“ kann jedoch auch auf Debian/Ubuntu installiert werden (apt install yum
).
Dann kann man anhand der in yum konfigurierten Repositories ein Paket spiegeln:
/etc/yum.repos.d/icinga2.repo
[icinga-stable-release-8]
name=ICINGA (stable release)
baseurl=https://packages.icinga.com/epel/$releasever/release/
enabled=1
gpgcheck=1
gpgkey=https://packages.icinga.com/icinga.key
repo-sync
reposync -q --config=/etc/yum/yum.conf --repoid=icinga-stable-release --plugins --newest-only --downloadcomps --download-metadata --norepopath --download_path=/srv/repos/icinga2/epel/8/release
createrepo -q /srv/repos/icinga2/centos/8/release
wget -N -q 'https://packages.icinga.com/icinga.key' -O /srv/repos/icinga2/icinga.key
Da man dies dann regelmässig aufruft empfihelt es sich ein kleines Script dafür zu erstellen:
mirror-sync-icinga2.sh
#!/bin/bash
SOFTWARE="icinga2"
REPO_BASE=/srv/repos/${SOFTWARE}
mkdir -p ${REPO_BASE}/epel
ln -sv ${REPO_BASE}/epel ${REPO_BASE}/centos
wget -N -q 'https://packages.icinga.com/icinga.key' -O $REPO_BASE/icinga.key
for REPOID in $(grep -oP '\[\K[^][]*(?=])' /etc/yum.repos.d/${SOFTWARE}.repo); do
REPO_VERSION=$(echo $REPOID | egrep -o '[[:digit:]]{1}' | head -n1)
if [ ! -z "$REPO_VERSION" ]; then
logger -t mirror.${SOFTWARE}[$$] "Updating $REPOID (to: $REPO_BASE/epel/$REPO_VERSION/release)"
reposync -q --config=/etc/yum/yum.conf --repoid=$REPOID --plugins --newest-only --downloadcomps --download-metadata --norepopath --download_path=$REPO_BASE/epel/$REPO_VERSION/release
createrepo -q ${REPO_BASE}/centos/${REPO_VERSION}/release
logger -t mirror.${SOFTWARE}[$$] "Finished $REPOID"
else
logger -t mirror.${SOFTWARE}[$$] "Invalid version for repoid: $REPOID (name repoid in the format repo-name-VERSION; i.ex. icinga-stable-release-8)"
fi
done
Das Script spiegelt automatisch jedes release repository, welches in /etc/yum.repos.d/icinga2.repo nach dem format: name-release aufgeführt ist, also z.B.: icinga-stable-release-7, icinga-stable-release-8, usw.
Mirror eines DEB (Debian) repositories
Um das ganze Repository zu mirroren wird unter Debian/Ubuntu apt-mirror
verwendet.
apt-get install apt-mirror
In /etc/apt/mirror.list können dann die Einstellungen vorgenommen werden.
Danach startet man den mirror Vorgang mit:
apt-mirror
Achtung: Durch apt-mirror entsteht beim ersten Start ein enormes Datenvolumen! Ubuntu belegt zur Zeit ca. 60 GiB / Architektur OHNE Quellcode-Pakete!
Mirror eines DEB Paket repositories
Ein DEB Paket repository kann man mit dem Tool debmirror
anlegen. Am besten macht man sich dann ein flexibeles Script für mehrere Repositories.
Nachfolgend ein Beispiel für icinga2 und mariadb
repo-mirror.sh
#!/bin/bash
mirror_icinga2() {
method=https
product=icinga2
localpath="/srv/repos/$product"
mirr=packages.icinga.com
rootpath="ubuntu"
distri="icinga-bionic,icinga-focal,icinga-jammy"
section="main"
arch="amd64,i386"
options="--no-check-gpg --ignore-release-gpg --postcleanup --diff=none --rsync-extra=none --verbose"
logger -t mirror[$$] Updating $mirr $rootpath ${distri} ${section}
debmirror --progress --nosource --host=${mirr} --root=${rootpath} --method=$method --dist=${distri} -section=${section} --arch=${arch} $options $localpath
mkdir -p /srv/repos/keys/$product
wget -q 'https://packages.icinga.com/icinga.key' -O /srv/repos/keys/$product/public
return_code=$?
logger -t mirror[$$] Finished $mirr $rootpatha ${distri} ${section}
return $return_code
}
mirror_mariadb105() {
method=http
product=mariadb105
localpath="/srv/repos/$product"
mirr=mirror.mva-n.net
rootpath="/mariadb/repo/10.5/ubuntu"
distri="bionic,focal"
section="main"
arch="amd64"
options="--ignore-missing-release --no-check-gpg --ignore-release-gpg --postcleanup --diff=none --rsync-extra=none --verbose"
logger -t mirror[$$] Updating $mirr $rootpath ${distri} ${section}
debmirror $localpath --progress --method=$method \
--host=${mirr} --root=${rootpath} --dist=${distri} \
--section=${section} --arch=${arch} \
$options
return_code=$?
logger -t mirror[$$] Finished $mirr $rootpatha ${distri} ${section}
return $return_code
}
if [ -n "$1" ]; then
mirror_$1
else
echo "`date`: Mirroring started" > /srv/repos/mirror.log
for app in icinga2 mariadb105; do
if mirror_$app; then
echo "`date`: $app _OKAY_" >> /srv/repos/mirror.log
else
echo "`date`: $app _ERROR_" >> /srv/repos/mirror.log
fi
done
fi
exit $?
Automatische Versionsstände erstellen
Wenn man ein eigenes Repository hat, möchte man meist auch, dass die Versionsstände auf allen Servern über einen bestimmten Zeitraum gleich sind. Man erstellt dann einfach z.B. jedes Quartal, oder Kalenderwoche eine neue „Version“ des repositories.
Was im Red Hat Satellite Server mittels Content-Views möglich ist, geht auch bei z.B. CentOS oder Ubuntu repositories mit einem Shellscript:
repo_version.sh
year=`date +%Y`
kw=`date +%V`
quarter=$(( ($(date +%-m)-1)/3+1 ))
repodir=/srv/repository
repodir_current=${repodir}/current
repodir_kw=${repodir}/${year}/${kw}
repodir_quarter=${repodir}/${year}/q${quarter}
logger -i -t "$0" -p INFO "Syncing current repo to calendar week ${kw}"
mkdir -p ${repodir}/${year}
if [ ! -d ${repodir_kw} ]; then
logs "cp -al ${repodir_current} ${repodir_kw}"
cp -al ${repodir_current} ${repodir_kw}
fi
logger -i -t "$0" -p INFO "/usr/bin/rsync -a --delete ${repodir_current}/* ${repodir_kw}"
rsync -a --delete ${repodir_current}/* ${repodir_kw}
logger -i -t "$0" -p INFO "syncing current repo to quartal repo ${q}"
if [ ! -d ${repodir_q} ]; then
logger -i -t "$0" -p INFO "cp -al ${repodir_current} ${repodir_q}"
cp -al ${repodir_current} ${repodir_q}
else
logger -i -t "$0" -p INFO "${repodir_q} exists. nothing to do"
fi
Zuerst wird mittels dem cp -al
Kommando das Verzeichnis von curretn kopiert, aber mittels hardlinks (-l
Paramater). Das ist wichtig weil sonst der benötigte Speicherplatz mit jeder Version um X GB ansteigen würde. Mittels Hardlinks wird pro Datei immer nur einmal der Speicherplatz verbraucht, egal, wie viele „Kopien“ davon existieren.
Mittels rsync
kann man dann noch ggf. geänderte Dateien als neue Kopie im Verzeichnis erstellen.