Хочете пакувати свою службу під systemd у зручний .deb і розгортати її через локальний APT-репозиторій? Зараз покажу простий і надійний шлях, який працює і на робочих станціях, і на сервер Linux. Будемо працювати через термінал Linux, писати мінімальні bash скрипти й використовувати зрозумілі apt команди. Поїхали! 🚀
Що будемо робити
- Створимо мінімальний .deb-пакет для служби systemd
- Додамо preinst/postinst/prerm/postrm скрипти
- Підпишемо репозиторій GPG-ключем
- Піднімемо локальний APT-репозиторій та встановимо пакет через нього
Підготовка структури пакета
Приклад пакета hello-service: служба друкує повідомлення в журнал кожні 5 секунд. Створіть робочу структуру:
mkdir -p pkg/hello-service_1.0-1/DEBIAN
mkdir -p pkg/hello-service_1.0-1/usr/bin
mkdir -p pkg/hello-service_1.0-1/lib/systemd/system
Скрипт служби
Це простий демон на bash, який пише в stdout (journald збере лог).
cat > pkg/hello-service_1.0-1/usr/bin/hello-service <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
while true; do
echo "$(date -Is) Hello from hello-service"
sleep 5
done
EOF
chmod 0755 pkg/hello-service_1.0-1/usr/bin/hello-service
Юніт systemd
Опишемо службу, яка працює від ізольованого системного користувача hello з базовим hardening.
cat > pkg/hello-service_1.0-1/lib/systemd/system/hello-service.service <<'EOF'
[Unit]
Description=Hello demo service
After=network.target
[Service]
Type=simple
User=hello
Group=hello
ExecStart=/usr/bin/hello-service
Restart=on-failure
RestartSec=3
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
Control і maintainer-скрипти
Створіть файл control із метаданими:
cat > pkg/hello-service_1.0-1/DEBIAN/control <<'EOF'
Package: hello-service
Version: 1.0-1
Section: utils
Priority: optional
Architecture: all
Depends: systemd
Maintainer: Your Name <you@example.com>
Description: Demo systemd service that prints hello every 5s
A minimal demo service managed by systemd.
EOF
Тепер maintainer-скрипти (вони мають бути виконувані):
cat > pkg/hello-service_1.0-1/DEBIAN/preinst <<'EOF'
#!/bin/bash
set -e
# Створюємо системного користувача/групу для служби
if ! id -u hello >/dev/null 2>&1; then
adduser --system --group --no-create-home \
--home /nonexistent --shell /usr/sbin/nologin hello
fi
EOF
cat > pkg/hello-service_1.0-1/DEBIAN/postinst <<'EOF'
#!/bin/bash
set -e
chown root:root /usr/bin/hello-service
chmod 0755 /usr/bin/hello-service
systemctl daemon-reload || true
# Після встановлення/оновлення — вмикаємо та перезапускаємо
if [ "$1" = "configure" ] || [ "$1" = "upgrade" ]; then
systemctl enable hello-service || true
systemctl restart hello-service || true
fi
EOF
cat > pkg/hello-service_1.0-1/DEBIAN/prerm <<'EOF'
#!/bin/bash
set -e
# Перед видаленням зупинимо й вимкнемо
if [ "$1" = "remove" ]; then
systemctl stop hello-service || true
systemctl disable hello-service || true
fi
EOF
cat > pkg/hello-service_1.0-1/DEBIAN/postrm <<'EOF'
#!/bin/bash
set -e
systemctl daemon-reload || true
# На purge — прибираємо користувача/групу
if [ "$1" = "purge" ]; then
deluser --system hello 2>/dev/null || true
delgroup hello 2>/dev/null || true
fi
EOF
chmod 0755 pkg/hello-service_1.0-1/DEBIAN/*
Збірка та встановлення .deb
Збираємо пакет і встановлюємо його через apt команди (це коректніше, ніж тільки dpkg -i, бо тягне залежності):
dpkg-deb --build pkg/hello-service_1.0-1
sudo apt install ./hello-service_1.0-1.deb
# Перевірка стану
systemctl status hello-service --no-pager
journalctl -u hello-service -f
Підпис і локальний APT-репозиторій
Тепер зробимо репозиторій у поточній директорії та підпишемо його GPG-ключем. Це зручно для багаторазового розгортання на кількох вузлах (особливо на сервер Linux).
Створення й підпис ключа GPG
sudo apt update && sudo apt install -y dpkg-dev apt-utils gnupg apt-transport-https
# Створюємо ключ (параметри можна змінювати)
gpg --quick-generate-key "Hello Repo (local) <repo@example>" ed25519 sign 2y
# Експортуємо публічний ключ у систему клієнта
gpg --export -a "Hello Repo (local)" > hello-repo.asc
sudo gpg --dearmor -o /usr/share/keyrings/hello-repo-archive.gpg hello-repo.asc
Побудова індексу та Release
mkdir -p repo && cp hello-service_1.0-1.deb repo/
cd repo
# Створюємо Packages.gz
dpkg-scanpackages -m . /dev/null | gzip -9c > Packages.gz
# Створюємо Release
apt-ftparchive release . > Release
# Підписуємо (двома способами: окремий підпис і InRelease)
gpg --yes --armor --detach-sign -o Release.gpg Release
gpg --yes --clearsign -o InRelease Release
# Запускаємо простий HTTP-сервер для роздачі
python3 -m http.server 8080
Додавання репозиторію і встановлення
echo "deb [signed-by=/usr/share/keyrings/hello-repo-archive.gpg] http://localhost:8080 ./" | \
sudo tee /etc/apt/sources.list.d/hello-local.list
sudo apt update
sudo apt install hello-service
Готово! Тепер ви можете оновлювати пакет, класти нові версії в repo/, регенерувати метадані та розгортати через знайомі apt команди.
Альтернативні способи
- Швидка збірка через FPM:
fpm -s dir -t deb -n hello-service -v 1.0.1 --deb-systemd hello-service.service usr/bin/hello-service. Зручно для прототипів. - Профі-вариант через debhelper/dpkg-buildpackage: створіть
debian/(control, rules, install, systemd), збирайтеdpkg-buildpackage -us -uc. Це краще для CI/CD. - Репозиторій із
reprepro: акуратна структураdists//pool/, зручне включення пакетів:reprepro includedeb stable ../hello-service_1.0-1.deb.
GUI-спосіб
- Встановлення .deb: відкрийте файл у “Software Center” або в GDebi — зручно, якщо не хочете одразу йти в термінал Linux.
- Додавання репозиторію: “Software & Updates” → вкладка “Other Software” → “Add…” і вставте рядок
deb [signed-by=/usr/share/keyrings/hello-repo-archive.gpg] http://localhost:8080 ./. Ключ можна імпортувати через утиліту “Passwords and Keys (Seahorse)”.
FAQ
Служба не стартує після встановлення.
Перевірте журнал: journalctl -u hello-service -b. Найчастіше причина — неправильний ExecStart або відсутній користувач hello (див. preinst).
Помилка в maintainer-скриптах (preinst/postinst).
Переконайтеся, що у файлів права 0755, початок з #!/bin/bash, та додавайте set -e. Тестуйте скрипти окремо.
Зміни в юніті не підхоплюються.
Додайте systemctl daemon-reload у postinst/postrm або виконайте вручну.
APT каже “NO_PUBKEY”.
Експортуйте і встановіть публічний ключ у /usr/share/keyrings/*.gpg і використайте параметр signed-by=... у джерелі.
dpkg-scanpackages не знайдено.
Встановіть інструменти: sudo apt install dpkg-dev.
Як додати залежності (наприклад, bash)?
Вкажіть у Depends: файлу control (наприклад, Depends: systemd, bash (>= 5)). Не зловживайте залежностями.
Пакет встановився, але служба не увімкнена.
Перевірте умовну гілку в postinst і наявність секції [Install] у юніті.
Порада від Kernelka
Для безпеки в systemd-додатку вмикайте hardening: ProtectSystem, NoNewPrivileges, PrivateTmp, а також окремого користувача/групу. Якщо сервісу потрібні файли, робіть каталоги через tmpfiles.d або створюйте їх у preinst з правильними правами. А ще — тестуйте пакет у чистому контейнері (наприклад, через systemd-nspawn або Docker) перед релізом. 📦
Підсумок
- Зібрали .deb із правильною структурою та systemd-юнітом
- Додали робочі pre/post-скрипти для керування службою
- Підписали локальний APT-репозиторій GPG-ключем
- Підключили репозиторій і встановили пакет через apt
- Ознайомилися з альтернативами (FPM, debhelper, reprepro) і GUI-варіантами
Тепер у вас є свій шлях від коду до встановлюваного пакета, готового для CI/CD і продакшен-розгортань. Вітаю! 😊

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