Власний RPM-репозиторій — це зручно, коли ви підтримуєте внутрішні пакети або хочете ділитися збірками із командою. Сьогодні покажу, як налаштувати повний цикл: побудова RPM, підпис пакунків та метаданих, формування репозиторію і автоматична публікація через GitLab CI. Без страху і паніки — лише дружній підхід і трохи любові до терміналу Linux 😊
Що і навіщо ми будуємо
Мета: автоматично збирати RPM-пакети в CI, підписувати їх GPG-ключем, генерувати метадані через createrepo_c, підписувати repomd.xml і публікувати статично (GitLab Pages або свій сервер Linux). Це полегшує встановлення та оновлення пакетів командою dnf/yum, а також вписується у ваші процеси автоматизація задач і DevOps.
Передумови
- GitLab репозиторій з доступним Shared Runner або власним Runner (Docker executor бажано; це про Docker на Linux).
- GPG 2.x локально для створення ключів.
- Пакети для базового хостингу: nginx або GitLab Pages.
How-to: повний пайплайн
1) Структура проєкту
Пропонована структура для однієї архітектури та дистрибутива (приклад EL9/x86_64):
2) Створення та експорт GPG-ключа
Створіть окремий ключ для підпису пакетів і метаданих. Можна з коротким строком дії.
Файл private.key.asc збережіть у секретах GitLab (CI/CD Variables), наприклад як GPG_PRIVATE_KEY. Пароль від ключа — як GPG_PASSPHRASE (masked, protected).
3) Налаштування rpmsign і підпис пакунків
Щоб rpmsign працював у CI без TTY, вмикаємо loopback-pinentry. Також пропишемо RPM-макроси:
Підпис пакунків:
Якщо ваша версія rpmsign не підтримує passphrase-fd, використайте expect або підписуйте через gpg-agent з попередньою конфігурацією loopback.
4) Створення та підпис репозиторію
Генеруємо метадані й підписуємо repomd.xml:
5) GitLab CI: .gitlab-ci.yml
Мінімальний приклад, що будує RPM (умовно вже зібрані артефакти у dist/*.rpm), підписує їх, формує репозиторій та публікує через GitLab Pages:
Після деплою ваш репозиторій буде доступний як https://<user|group>.gitlab.io/<project>/el9/x86_64/
6) Підключення репозиторію на клієнті
Тепер ви можете встановлювати свої пакети через dnf, а оновлення прилітатимуть автоматично. Красота!
Альтернативні способи
- Хостинг на власному nginx: синхронізуйте repo/ на ваш сервер Linux і віддавайте як статичні файли. Не забудьте SELinux контекст та правильні MIME-ти.
- S3-сумісне сховище (MinIO, AWS S3): публікуйте в бакет, вмикайте статичний веб-хостинг.
- GitLab Package Registry (Generic): зручно для контролю доступу, але клієнтський dnf потребує прямого HTTP-доступу до дерев репозиторію.
- Pulp/Nexus/Artifactory: важка артилерія з ролями, кешами та GUI.
- Інші CI: GitHub Actions, Jenkins — логіка аналогічна, просто перенесіть bash скрипти.
GUI-спосіб: Nexus Repository OSS
- Встановіть Nexus Repository OSS на Docker або як службу (це теж про Docker на Linux).
- Створіть Hosted репозиторій типу yum (RPM). Вкажіть ім'я, політики кешування.
- Завантажте підписані RPM у веб-інтерфейсі або через REST API.
- Імпортуйте ваш публічний GPG-ключ клієнтам і додайте baseurl на Nexus. Готово!
FAQ
GPG: signing failed: Inappropriate ioctl for device
Додайте pinentry-mode loopback (gpg.conf) і allow-loopback-pinentry (gpg-agent.conf), використовуйте --pinentry-mode loopback та передавайте пароль через змінну. Без TTY інакше не працює.
rpmsign не приймає пароль
Перевірте версію rpm-sign. Якщо немає passphrase-fd, використайте expect або підписуйте ключ без пароля виключно в CI-оточенні з обмеженим доступом.
Клієнт каже, що підпис невалідний
Переконайтеся, що імпортовано той самий публічний ключ, що відповідає KEYID, та ввімкнено gpgcheck=1 і repo_gpgcheck=1 (для repomd.xml). Також стежте, щоб час на сервері та клієнті був синхронізований.
createrepo_c не знайдений
Встановіть пакет createrepo_c (dnf -y install createrepo_c). На деяких базових образах він відсутній.
Метадані не оновлюються
Використовуйте createrepo_c --update, а на клієнті виконайте dnf clean all і dnf makecache. Перевірте кешування на проксі/CDN.
403/404 при доступі до репозиторію
Звірте baseurl, права доступу до файлів, налаштування nginx (autoindex on;), а також гілку, з якої деплоїться GitLab Pages. Для приватних репозиторіїв оцініть альтернативу з власним сервером.
Помилки із SELinux на власному хостингу
Встановіть правильні контексти: chcon -R -t httpd_sys_content_t /var/www/repo або налаштуйте policy. Перевіряйте через audit2why/audit2allow.
Порада від Kernelka
Тримайте GPG-ключ окремим для підпису RPM і ротуйте його періодично. У CI зберігайте секрети як protected variables, а гілки для релізів обмежуйте. Маленька дисципліна — велика безпека ✨
Підсумок
- Створили GPG-ключ і додали його до CI як секрет.
- Підписали RPM-пакети і repomd.xml через rpmsign та gpg.
- Згенерували метадані createrepo_c і опублікували статично (GitLab Pages або nginx).
- Підключили репозиторій на клієнті через dnf/yum з gpgcheck.
- За потреби використали GUI-варіант через Nexus.
Ось так, крок за кроком, і у вас є власний безпечний RPM-репозиторій з повною автоматизацією у GitLab CI. Ви круті!

Прокоментувати
На сайті відображається лише твоє ім'я та коментар. Електронна пошта зберігається виключно для зв'язку з тобою за потреби та в жодному разі не передається стороннім особам.