AppImage — зручний формат для портативних застосунків у Linux. Якщо ви хочете роздавати власні або внутрішні збірки, безпечно оновлювати їх і красиво додавати до меню — зробимо локальний репозиторій AppImage з підписуванням, автооновленням через zsync та інтеграцією з робочим столом. Обіцяю: усе реально зробити з нуля у звичайному терміналі Linux 🚀

Що таке локальний репозиторій AppImage і навіщо він

Це проста HTTP‑тека з вашими *.AppImage, де додатково лежать підписи (GPG), контрольні суми та файли *.zsync для швидких дельта‑оновлень. Користувачі завантажують застосунки напряму або система оновлює їх автоматично. Без складних серверів.

Крок 1. Підготуйте структуру каталогу

Створимо місце для репозиторію та перший реліз застосунку. Далі всі приклади команд — це чесні linux команди, їх зручно виконувати в терміналі Linux.

sudo mkdir -p /srv/appimages/repo
sudo chown -R "$USER":"$USER" /srv/appimages
cd /srv/appimages/repo
# Покладіть сюди свій реліз
mv ~/Downloads/MyApp-1.0-x86_64.AppImage .
chmod +x MyApp-1.0-x86_64.AppImage
# Зручний "стабільний" лінк
ln -sf MyApp-1.0-x86_64.AppImage MyApp-latest.AppImage

Крок 2. Підписування AppImage (GPG) і контрольні суми

Підпис — це ваша гарантія цілісності. Користувачі можуть перевірити, що файл не було підмінено. Якщо у вас ще немає ключа GPG:

gpg --full-generate-key   # оберіть RSA, 4096, строк, ім'я та email

Підписуємо реліз і публікуємо відкритий ключ разом із контрольними сумами:

cd /srv/appimages/repo
# Відокремлений підпис для кожного релізу
gpg --detach-sign --output MyApp-1.0-x86_64.AppImage.sig \
    MyApp-1.0-x86_64.AppImage

# Публічний ключ для перевірки підпису
gpg --armor --export <ВАШ_EMAIL_АБО_KEYID> > KEYS.asc

# Контрольні суми всіх релізів
sha256sum *.AppImage > SHA256SUMS
# Підпишемо файл сум також
gpg --clearsign SHA256SUMS   # створить SHA256SUMS.asc

Перевірка на клієнтській машині виглядає так:

gpg --import KEYS.asc
# Перевірка підпису окремого релізу
gpg --verify MyApp-1.0-x86_64.AppImage.sig MyApp-1.0-x86_64.AppImage
# Перевірка контрольних сум
sha256sum -c SHA256SUMS.asc

Крок 3. Ввімкніть автооновлення через zsync

Для швидких оновлень AppImage використовує AppImageUpdate та метадані zsync. Потрібно згенерувати *.zsync і (якщо ви збираєте свій AppImage) вбудувати адресу оновлень у заголовок.

# Встановіть інструмент для zsync (Debian/Ubuntu):
sudo apt-get update && sudo apt-get install -y zsync

cd /srv/appimages/repo
# HOST замініть на вашу адресу (IP/домен)
HOST=192.168.1.10
zsyncmake -u http://$HOST/repo/MyApp-latest.AppImage \
          -o MyApp-latest.AppImage.zsync \
          MyApp-1.0-x86_64.AppImage

Якщо ви самі збираєте AppImage, на етапі створення вбудуйте інформацію про оновлення (приклад для appimagetool):

export APPIMAGE_UPDATE_INFORMATION="zsync|http://$HOST/repo/MyApp-latest.AppImage.zsync"
appimagetool AppDir/ MyApp-1.0-x86_64.AppImage

Клієнтське оновлення виконується так (через appimageupdatetool):

# Завантажте appimageupdatetool (AppImage) з GitHub Releases:
wget -O ~/.local/bin/appimageupdatetool \
  https://github.com/AppImage/AppImageUpdate/releases/download/continuous/appimageupdatetool-x86_64.AppImage
chmod +x ~/.local/bin/appimageupdatetool

# Оновлення локального файлу (має бути вбудована Update Information):
~/.local/bin/appimageupdatetool -O ~/Applications/MyApp-latest.AppImage

Важливо: якщо ви лише «перехостите» сторонні AppImage без збудованої Update Information, дельта‑оновлення можуть бути недоступні. Тоді оновлення — звичайна заміна файлу.

Крок 4. Роздаємо репозиторій по HTTP

Найшвидший старт — вбудований сервер Python (зручно для тесту):

cd /srv/appimages/repo
python3 -m http.server 8000

Для постійного доступу краще налаштувати Nginx:

sudo apt-get install -y nginx
sudo tee /etc/nginx/sites-available/appimages >/dev/null <<'EOF'
server {
  listen 80;
  server_name 192.168.1.10;  # або ваш домен
  root /srv/appimages/repo;
  autoindex on;
}
EOF
sudo ln -s /etc/nginx/sites-available/appimages /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Крок 5. Інтеграція з меню робочого столу

Щоб ваш застосунок з'явився в меню, достатньо .desktop‑файла та іконки. Це не складно навіть без додаткових утиліт GUI Linux.

# Рекомендується зберігати AppImage у ~/Applications
mkdir -p ~/Applications ~/.local/share/applications ~/.local/share/icons/hicolor/256x256/apps
cp /srv/appimages/repo/MyApp-latest.AppImage ~/Applications/
chmod +x ~/Applications/MyApp-latest.AppImage
# Іконка (приклад):
wget http://$HOST/repo/icons/myapp.png -O ~/.local/share/icons/hicolor/256x256/apps/myapp.png

# Створимо desktop-файл
cat > ~/.local/share/applications/myapp.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=MyApp
Comment=Мій застосунок у форматі AppImage
Exec=/home/%u/Applications/MyApp-latest.AppImage
Icon=myapp
Terminal=false
Categories=Utility;
EOF

# Оновимо кеш меню
update-desktop-database ~/.local/share/applications || true

Тепер «MyApp» з'явиться у меню запуску. Якщо ні — перелогіньтесь.

Автоматичні оновлення через systemd (user)

Зробимо маленькі bash скрипти для масового оновлення та ввімкнемо автоматизацію задач таймером systemd.

mkdir -p ~/bin ~/.config/systemd/user
cat > ~/bin/appimage-update-all.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
cd "$HOME/Applications" 2>/dev/null || exit 0
for f in *.AppImage; do
  [[ -x "$f" ]] || continue
  echo "Updating: $f"
  ~/.local/bin/appimageupdatetool -O "$f" || echo "Skip: $f"
done
EOF
chmod +x ~/bin/appimage-update-all.sh

cat > ~/.config/systemd/user/appimage-update.service <<'EOF'
[Unit]
Description=Update AppImages in ~/Applications

[Service]
Type=oneshot
ExecStart=%h/bin/appimage-update-all.sh
EOF

cat > ~/.config/systemd/user/appimage-update.timer <<'EOF'
[Unit]
Description=Daily AppImage updates

[Timer]
OnCalendar=daily
Persistent=true
Unit=appimage-update.service

[Install]
WantedBy=timers.target
EOF

systemctl --user daemon-reload
systemctl --user enable --now appimage-update.timer

Готово: ваші AppImage оновлюватимуться раз на добу. Це чиста автоматизація задач без зайвих залежностей.

Альтернативні способи

  • Без zsync: просто публікуйте новий MyApp-2.0.AppImage і оновлюйте символічне посилання MyApp-latest.AppImage. Клієнти перекачують повний файл.
  • Внутрішня мережа: можна роздавати репозиторій через Samba/NFS, але для AppImageUpdate потрібна HTTP‑доступність .zsync.
  • Інтеграція через AppImageLauncher: він сам інтегрує та пропонує оновлення (де підтримується). Див. розділ нижче.

GUI-спосіб: AppImageLauncher

AppImageLauncher додає зручну інтеграцію в меню, керує місцем збереження та може запускати оновлення. Для багатьох дистрибутивів є пакети. Шукайте «AppImageLauncher» у вашому дистро або на GitHub. Після встановлення просто відкрийте AppImage — майстер інтегрує його в систему. Це найпростіший шлях у світі GUI Linux 🧁

FAQ

Чому appimageupdatetool каже «No update information»?
У вашому AppImage не вбудовано APPIMAGE_UPDATE_INFORMATION. Це треба робити під час збирання (через appimagetool). Для «чужих» AppImage автооновлення може бути недоступне.

zsync отримує 404 або не знаходить файл
Перевірте, що URL у *.zsync (параметр -u під час zsyncmake) вказує на фактичний шлях до AppImage на сервері. Також перевірте права доступу Linux до файлів і що веб‑сервер віддає їх коректно.

Іконка не відображається в меню
Переконайтеся, що Icon=myapp збігається з назвою файлу іконки без розширення та що вона лежить у правильній темі іконок (наприклад, ~/.local/share/icons/hicolor/256x256/apps/myapp.png). Оновіть кеш: gtk-update-icon-cache або перелогіньтесь.

Файл не запускається
Задайте біт виконання: chmod +x MyApp.AppImage. Якщо з мережевої теки — переконайтеся у довіреності шляху або скопіюйте в локальний каталог.

Як перевірити підпис?
Імпортуйте KEYS.asc, далі gpg --verify підпис *.sig проти файлу AppImage. Для зручності публікуйте відбиток ключа (gpg --fingerprint) на сайті.

Порада від Kernelka

Версії зберігайте з чіткою семантикою (1.0, 1.1.1), а посилання «latest» тримайте символічним. Так простіше робити відкат, якщо щось пішло не так. І пам'ятайте: невеликі bash скрипти рятують купу часу 😉

Підсумок

  • Створили структуру локального репозиторію й перший реліз.
  • Налаштували GPG‑підпис та контрольні суми для безпеки.
  • Додали zsync і (за потреби) вбудували Update Information.
  • Роздали файли по HTTP через Python або Nginx.
  • Інтегрували застосунок у меню через .desktop та іконку.
  • Увімкнули автооновлення з appimageupdatetool і systemd‑таймером.
  • Показали GUI‑варіант із AppImageLauncher.