====== Creating repository from automated Debian Salsa builds ======
{{ :salsa_to_aptly.png |}}
===== Motivation =====
I'm not an Debian maintainer. Nor I want to be in future.
My reasons to do all this is:
- I want some specific software to be packaged for Debian
- when I update packaging on salsa.debian.org I want to have available package for my devices
- I don't want to bother with downloading packages from Salsa CI manually or compiling them again on these devices
- I want also others to be able use my packages
These reasons motivated me to look into [[salsa.debian.org/|Salsa]], [[https://docs.gitlab.com/ee/api/|GitLab API]] and [[https://www.aptly.info/tutorial/|Aptly]] deployment.
==== Advantages ====
* package build process is handled by salsa, no need to worry about it
* ecologic - it's build only once
==== Disadvantages ====
* no control about build process than offered by salsa-ci.yml configuration file
===== Predisposition =====
- You did correctly setup **debian/salsa-ci.yml** and Gitlab settings ([[https://debconf19.debconf.org/talks/148-salsa-ci-debian-pipeline-for-developers/|Debconf19 talk about Salsa CI]])
- you build for achitectures you'll be distributing with aptly
You can look at project configuration of [[https://salsa.debian.org/okias-guest/]] as an example.
===== Where to start =====
Aptly. First, you need to find a place, where you can host your repository. It's right, that Salsa-CI can offer you 1 repository per one pipeline, but that's not very pleasant having to switch repository everytime you build a package.
So, you need some VPS or physical machine with IPv6 (every provider should give you at least /64 range for free) or/and with IPv4 connectivity.
When you get it, just installing Debian, [[https://www.aptly.info/download/|aptly]] and nginx should be enough.
Then it's a time to create user and generate your repository replated GPG key.
==== Aptly ====
useradd -m repo && export USER=repo # create user repo
sudo -u $USER gpg --default-new-key-algo rsa4096 --gen-key # generate new key
sudo -u $USER mkdir -p /home/${USER}/.aptly/public/
sudo -u $USER GPG_TTY=$(tty) gpg --export > /home/${USER}/.aptly/public/public-key.asc # export key
sudo -u $USER aptly repo create -distribution unstable ${REPO_NAME}
Now we have our user and GPG key, we can move to creating our script **gitlab_to_aptly.sh** which we will place into **/home/$USER/**
Before continuing, please prepare your Bearer token, you'll learn how to do that from https://www.youtube.com/watch?v=0LsMC3ZiXkA . Fill **USER=** and **TOKEN=** inside the script.
Script does simple things
- it does check for all your projects
- for each project it check latest successful jobs
- if there is new successful job, then it picks debian packages generated by salsa-ci and downloads and unpack them
- then export them into aptly repository
#!/bin/sh
# SPDX-License-Identifier: GPL-3.0-only
# version 0.1; created by David Heidelberg
if [ `id -u` -eq 0 ]; then
echo "Please DO NOT run as root!"
exit
fi
USER= # your gitlab username
TOKEN= # watch https://www.youtube.com/watch?v=0LsMC3ZiXkA
ARCHS="amd64"
JOBS="build" # jobs must match to build == amd64;
ARTIF_UNPACK=debian/output
echo "* Downloading projects..."
PROJ_JSON=`curl -s -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" "https://salsa.debian.org/api/v4/users/${USER}/projects/"`
PROJECTS=`echo $PROJ_JSON | jq ".[].id" | xargs`
PUBLISH=0
check_new_jobs() {
for id in $PROJECTS; do
echo "* Checking jobs for project ${id}..."
LAST_JOB_ID_FILE="proj_${id}_last_job.txt"
LAST_JOB_ID=`curl -s -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" "https://salsa.debian.org/api/v4/projects/${id}/jobs?scope[]=success" | jq ".[0].id" | xargs`
if [ -e "${LAST_JOB_ID_FILE}" ]; then
JOB_ID=`cat ${LAST_JOB_ID_FILE}`
else
JOB_ID=0
fi
if [ $LAST_JOB_ID != "null" ] && [ $JOB_ID -ne $LAST_JOB_ID ]; then
echo $LAST_JOB_ID > ${LAST_JOB_ID_FILE}
echo "* Written new JOB ID $LAST_JOB_ID into file ${LAST_JOB_ID_FILE}."
get_artifacts
PUBLISH=1
fi
unset LAST_JOB_ID
done
}
cleanup() {
rm -vrf ./${ARTIF_UNPACK}/*
}
get_artifacts() {
for job in $JOBS; do
BRANCH="debian/latest"
curl -o ${id}_${job}.zip -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" "https://salsa.debian.org/api/v4/projects/${id}/jobs/artifacts/${BRANCH}/download?job=${job}" && \
unzip ${id}_${job}.zip && \
rm ${id}_${job}.zip && \
echo aptly command ID: ${id} JOB: ${job} done!
rm ${ARTIF_UNPACK}/output.log
done
}
publish() {
if [ $PUBLISH -eq 0 ]; then
echo "* Nothing to publish. Quiting..."
exit 0
fi
REPO_NAME=ixit
aptly repo add ${REPO_NAME} ${ARTIF_UNPACK} # add files
aptly publish drop unstable # first we get rid of previously published repo
APTLY_ARCHS=`echo $ARCHS | tr " " ,`
aptly publish repo -batch -architectures "${APTLY_ARCHS}" -distribution unstable ${REPO_NAME}
}
cleanup
check_new_jobs
publish
==== Nginx ====
Test script with sudo -u $USER ./gitlab_to_aptly.sh
, if your /home/$USER/.aptly/public is populated, prepare nginx configuration. This configuration may differ a lot from your use. I'm assuming you have SSL configured (ssl.conf) and SSL certificates in place.
**/etc/nginx/sites-available/repo.ixit.cz.conf**
server {
include ssl.conf;
server_name repo.ixit.cz;
ssl_certificate /etc/letsencrypt/live/ixit.cz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ixit.cz/privkey.pem;
location / {
root /home/repo/.aptly/public/;
autoindex on;
}
}
systemctl reload nginx and check URL, if you see the repository.
==== Testing it ====
In that case, you can try add it to the first device. Replace ixit with your repository name:
echo "deb https://repo.ixit.cz/ unstable main" > /etc/apt/sources.list.d/ixit.list # repository
curl -o /etc/apt/trusted.gpg.d/ixit.gpg https://repo.ixit.cz/public-key.asc # GPG key
apt update # shouldn't report any errors
now you can install package you desire and test.
==== Repository refreshing ====
Most likely, you'll want to regenerate your repository at least every hour.
This is how can look **/etc/systemd/system/gitlab_to_aptly.service**
[Unit]
Description=Radioalarm service
[Service]
User=repo
WorkingDirectory=/home/repo/tmp/
ExecStart=/home/repo/gitlab_to_aptly.sh
and **/etc/systemd/system/gitlab_to_aptly.timer**
[Unit]
Description=Update aptly repository every hour
[Timer]
OnBootSec=60min
OnUnitActiveSec=60min
Unit=gitlab_to_aptly.service
[Install]
WantedBy=timers.target