Δικό σας RPM mirror, και χτίσιμο της διόρθωσης πριν τη στείλει η διανομή
Πώς τρέχετε ένα συνεπές τοπικό RPM mirror και, όταν η διόρθωση υπάρχει upstream αλλά όχι ως πακέτο, τη χτίζετε καθαρά ώστε το επίσημο πακέτο να την αντικαταστήσει.

Όταν δημοσιεύεται μια σοβαρή ευπάθεια, δύο πράγματα αποφασίζουν πόσο καιρό μένουν εκτεθειμένοι οι servers σας: πόσο γρήγορα μπορείτε να κατεβάσετε πακέτα, και αν το διορθωμένο πακέτο υπάρχει ακόμη. Ένα τοπικό mirror λύνει το πρώτο. Η ικανότητα να χτίσετε μόνοι σας ένα καθαρό πακέτο, από την ίδια την προδιαγραφή του maintainer, λύνει το δεύτερο. Έτσι κάνουμε και τα δύο σε Enterprise Linux, και πώς να το κάνετε χωρίς να αφήνετε σπιτικά πακέτα να κυκλοφορούν αφού φτάσουν τα επίσημα.
Γιατί να τρέχετε καν δικό σας mirror
Τα δημόσια mirrors τα τρέχουν γενναιόδωροι άνθρωποι και οργανισμοί, και μια συνηθισμένη μέρα είναι γρήγορα. Τη μέρα που κυκλοφορεί μια κρίσιμη διόρθωση, κάθε server στον κόσμο ζητά τα ίδια πακέτα ταυτόχρονα. Ένα τοπικό mirror μέσα στο δικό σας δίκτυο το μετατρέπει σε τοπική αντιγραφή. Σας επιτρέπει επίσης να κάνετε patch servers που είναι σκόπιμα αποκομμένοι από το internet, όπως συστήματα backup και διαχείρισης, χωρίς να τους ανοίξετε.
Υπάρχει και ένα πιο ήσυχο όφελος: ένα mirror που κρατά πλήρες ιστορικό πακέτων σάς επιτρέπει να ξαναχτίσετε έναν server σε γνωστή κατάσταση, ή να γυρίσετε ένα πακέτο πίσω, από το δικό σας αντίγραφο.
Mirror χωρίς να σερβίρετε ποτέ μισοσυγχρονισμένο repository
Το αφελές mirror είναι ένα rsync ή reposync κατευθείαν στον κατάλογο που δημοσιεύει ο web server σας. Αν ένας client τρέξει dnf ενώ ο συγχρονισμός είναι στη μέση, μπορεί να δει νέα metadata που αναφέρονται σε πακέτα που δεν έχουν φτάσει ακόμη, ή παλιά metadata που δείχνουν σε πακέτα που μόλις αφαιρέθηκαν. Το αποτέλεσμα είναι μπερδεμένα σφάλματα ακριβώς τη λάθος στιγμή.
Συγχρονίστε σε δύο φάσεις αντί γι' αυτό:
- Πρώτα τα πακέτα. Κατεβάστε τα πακέτα στον δημοσιευμένο κατάλογο. Τα παλιά metadata εξακολουθούν να περιγράφουν ένα συνεπές σύνολο, γιατί τίποτα από όσα αναφέρουν δεν έχει αφαιρεθεί ακόμη.
dnf reposync --repoid=os-baseos --arch=x86_64 --arch=noarch \
--delete --norepopath -p /srv/repo/os/baseos
- Μετά τα metadata, με εναλλαγή μονομιάς. Κατεβάστε το upstream
repodata/σε έναν αδελφό κατάλογο (κάθε αρχείο που αναφέρει τοrepomd.xml), επαληθεύστε το, και μετά αντικαταστήστε τα δημοσιευμένα metadata με μία μετονομασία. Οι clients βλέπουν το παλιό repository ή το νέο, ποτέ μείγμα.
mv /srv/repo/os/baseos/repodata /srv/repo/os/baseos/repodata.old
mv /srv/repo/os/baseos/repodata.new /srv/repo/os/baseos/repodata
Η χρήση των upstream metadata, αντί να αναπαράγετε δικά σας με createrepo_c, κρατά το repository ακριβώς όπως το έχτισε ο εκδότης.
Δώστε σε κάθε εργασία συγχρονισμού ένα lock ώστε δύο εκτελέσεις να μην επικαλύπτονται ποτέ, γράψτε ένα μικρό αρχείο κατάστασης με το αποτέλεσμα και την ώρα, και ειδοποιήστε κάποιον όταν μια εργασία αποτύχει. Ένα mirror που σταμάτησε αθόρυβα να συγχρονίζεται τον περασμένο μήνα είναι χειρότερο από κανένα mirror, γιατί όλοι το εμπιστεύονται.
Οι clients τότε χρησιμοποιούν ένα απλό αρχείο repository που δείχνει στο mirror σας:
[local-baseos]
name=Local mirror: BaseOS
baseurl=https://mirror.example.internal/os/baseos/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
Όταν η διόρθωση υπάρχει αλλά το πακέτο όχι
Μερικές φορές το upstream project κυκλοφορεί διορθωμένη έκδοση και ο maintainer της διανομής ή του repository δεν την έχει πακετάρει ακόμη. Συχνά αυτό το κενό είναι ώρες. Μερικές φορές είναι μέρες.
Ο κανόνας που ακολουθούμε: χτίστε την upstream έκδοση από το packaging του ίδιου του maintainer, μην αλλάξετε τίποτα άλλο, και βεβαιωθείτε ότι το επίσημο πακέτο θα αντικαταστήσει το δικό σας αυτόματα.
Χτίστε σε καθαρό δωμάτιο
Χρησιμοποιήστε ένα φρέσκο container της ίδιας έκδοσης διανομής με τους servers-στόχους, ώστε το περιβάλλον build να είναι γνωστό και αναλώσιμο:
podman run --rm -it -v ./build:/build:Z oraclelinux:<release> bash
dnf install -y rpm-build rpmdevtools dnf-plugins-core
rpmdev-setuptree
Ξεκινήστε από το τελευταίο source package (SRPM) του maintainer για το branch που τρέχετε, εγκαταστήστε το, και εγκαταστήστε τις εξαρτήσεις build του:
rpm -ivh php-<current>.src.rpm
dnf builddep -y ~/rpmbuild/SPECS/php.spec
Αλλάξτε μόνο την έκδοση, και επαληθεύστε την πηγή
Κατεβάστε το διορθωμένο upstream tarball από το επίσημο site του project και επαληθεύστε το με το checksum που δημοσιεύει το project.
sha256sum php-<fixed>.tar.xz
Στο spec file, ενημερώστε το Version στη διορθωμένη έκδοση και αντικαταστήστε την πηγή. Αφήστε patches, επιλογές configure και λίστες αρχείων όπως τα έγραψε ο maintainer. Αν ένα patch του maintainer δεν εφαρμόζεται πια στη νέα έκδοση, σταματήστε και καταλάβετε γιατί πριν προχωρήσετε.
Διαλέξτε ένα release που παραμερίζει
Αυτό είναι το βήμα που ξεχνούν οι άνθρωποι. Το πακέτο σας πρέπει να ταξινομείται χαμηλότερα από το ενδεχόμενο επίσημο πακέτο του maintainer της ίδιας έκδοσης, ώστε ένα κανονικό dnf upgrade να αντικαταστήσει το δικό σας. Ένα release που ξεκινά με 0. το κάνει αξιόπιστα:
Release: 0.1.local%{?dist}
Ελέγξτε το πριν χτίσετε οτιδήποτε, με την ίδια σύγκριση που χρησιμοποιεί το rpm:
rpmdev-vercmp 0:X.Y.Z-0.1.local.elN 0:X.Y.Z-1.elN.maint
Το επίσημο release πρέπει να βγαίνει νεότερο. Αν δεν βγαίνει, αλλάξτε τη συμβολοσειρά release μέχρι να βγει.
Χτίστε, δοκιμάστε, κρατήστε τα αποδεικτικά
rpmbuild -ba ~/rpmbuild/SPECS/php.spec
Αποθηκεύστε τα χτισμένα πακέτα με τα checksums τους και μια σημείωση με το checksum του source tarball, ώστε οποιοσδήποτε αργότερα να μπορεί να πει ακριβώς τι εγκαταστάθηκε και από πού προήλθε.
Δημοσιεύστε τα builds σας σε ξεχωριστό repository στο mirror σας, όχι ανακατεμένα στο αντίγραφο του repository του vendor. Όταν το επίσημο πακέτο φτάσει στο mirrored repository, η επόμενη κανονική ενημέρωση αντικαθιστά το δικό σας, και το ξεχωριστό repository σας μπορεί να αδειάσει.
Τα εύσημα εκεί που ανήκουν
Τίποτα από αυτά δεν αντικαθιστά τους ανθρώπους που συντηρούν τα πακέτα. Maintainers repositories όπως ο Remi Collet, στου οποίου τα repositories PHP βασίζεται μεγάλο μέρος του κόσμου του Enterprise Linux, συχνά στέλνουν διορθώσεις εντυπωσιακά γρήγορα. Το χτίσιμο από την προδιαγραφή τους είναι τρόπος να καλύψετε τις τελευταίες λίγες ώρες, όχι υποκατάστατο της δουλειάς τους. Κατά τις διορθώσεις του PHP2Shell γράψαμε και για τις δύο πλευρές: PHP2Shell: patched PHP packages και Respect to Remi.
Μια λίστα ελέγχου για τη δική σας πλατφόρμα
- Από πού κατεβάζουν πακέτα οι servers σας, και τι συμβαίνει αν αυτό το μέρος είναι αργό;
- Μπορούν οι απομονωμένοι servers σας να γίνουν patch χωρίς να ανοίξουν στο internet;
- Θα μπορούσε ποτέ ένας client να δει μισοσυγχρονισμένο repository στο mirror σας;
- Ενημερώνεται κάποιος όταν ένας συγχρονισμός mirror αποτυγχάνει;
- Αν έπρεπε να χτίσετε ένα πακέτο απόψε, επιτρέπει η συμβολοσειρά release σας στο επίσημο να το αντικαταστήσει;
Αν θέλετε βοήθεια να στήσετε ένα mirror ή μια διαδικασία έκτακτων builds, οι μηχανικοί μας ευχαρίστως μοιράζονται ό,τι δουλεύει. Μιλήστε με έναν μηχανικό
Related
- /what-we-do/operations/package-builds-mirror/
- /what-we-do/operations/emergency-vulnerability-response/
- /what-we-do/data-web/php-upgrades-security-patching/
Δημοσιεύθηκε 8 Σεπτεμβρίου 2026.
Όλες οι σημειώσεις