The example here is based on having the Ubuntu 'jammy' distribution.
Assumed is that a Nexus server is installed already.
Generate a new gpg key on Nexus repository.
apt-get update && apt-get install gpg && gpg --gen-key
Get the key ID which was added.
gpg --list-keys
Export the created keys as files.
gpg --armor --output nexus-apt-repo.public.gpg.key --export <gpg key Id>
gpg --armor --output nexus-apt-repo.private.gpg.key --export-secret-key <gpg key Id>
gpg --output nexus-apt-repo.public.gpg --export <gpg key Id>
gpg --output nexus-apt-repo.private.gpg --export-secret-key <gpg key Id>
Paste the ASCII content of file nexus-repo.private.gpg.key
into the APT-repository
settings 'APT Settings > Signing Key'.
Assign a role to the uploader user account containing at least:
nx-repository-view-*-*-edit
nx-repository-view-*-*-read
Copy the GPG-public-key nexus-repo.public.gpg
to directory and file
/etc/apt/trusted.gpg.d/nexus-repo.public.gpg
.
For the Scanframe apt repository the key is located in the raw shared
repository and can be added using the wget
command.
wget https://nexus.scanframe.com/repository/shared/apt-repo-signatures/nexus-apt-repo.public.gpg \
-O /etc/apt/trusted.gpg.d/nexus-apt-repo.public.gpg
The sources.list
format is deb [options] repository_url distribution <components...>
where in our case:
Field | Description |
---|---|
options | Like arch=amd64 to only look for 64-bit packages. |
repository_url | Formated like https://<nexus-hostname>/repository/<nexus-repo-name> . |
distribution | For example jammy as the Ubuntu named distribution. |
components | Always main is the default and fixed single component of the Nexus APT-repository. |
So for the file named /etc/apt/sources.list.d/nexus-repo.list
the following is inserted.
deb [arch=amd64] https://nexus.scanframe.com/repository/apt-hosted jammy main
echo "deb [arch=amd64] https://nexus.scanframe.com/repository/apt-hosted jammy main" \
> /etc/apt/sources.list.d/nexus-repo.list
Alternatively use the add-apt-repository
command from the package software-properties-common
when installed.
add-apt-repository --yes "https://nexus.scanframe.com/repository/apt-hosted"
Check if the repository was added.
add-apt-repository --list
To upload to the APT-repository use the next command/script.
#!/usr/bin/env bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CRED_FILE="${SCRIPT_DIR}/.apt-repo-credentials"
# Include the WriteLog function.
source "${SCRIPT_DIR}/inc/WriteLog.sh"
# Prints the help to stderr.
#
function ShowHelp() {
echo "Usage: ${0} <file-to-upload...>
Uploads files to a Sonatype Nexus repository allowing wildcards.
When the credentials are not passed as environment variables a file named
'${CRED_FILE}'
is sourced containing the following variables e.g.:
NEXUS_USER='uploader'
NEXUS_PASSWORD='<uploader-password>'
NEXUS_SERVER_URL='https://nexus.scanframe.com'
NEXUS_REPO_NAME='apt-hosted'
These environment variables can be set in GitLab for a project for CI-pipeline
or partially by the pipeline configuration.
"
}
function PrependAndEscape() {
while read -r line; do
WriteLog -e "${1}${line}"
done
}
# When no arguments are passed show help.
if [[ $# -eq 0 ]]; then
ShowHelp
exit 0
fi
# Import the credentials and repo details...
#NEXUS_USER="uploader"
#NEXUS_PASSWORD="<password>"
#NEXUS_SERVER_URL="https://nexus.scanframe.com"
#NEXUS_REPO_NAME="apt-hosted"
# Check if the user was configured and if not try to read the credentials file.
if [[ -z "${NEXUS_USER}" ]]; then
WriteLog "# Reading credentials file: ${CRED_FILE}"
if [[ ! -f "${CRED_FILE}" ]]; then
WriteLog "Credential file not found: ${CRED_FILE} !"
exit 1
fi
source "${SCRIPT_DIR}/.apt-repo-credentials"
fi
# Check if the credentials were set fully.
if [[ -z "${NEXUS_USER}" || -z "${NEXUS_PASSWORD}" || -z "${NEXUS_SERVER_URL}" || -z "${NEXUS_REPO_NAME}" ]]; then
WriteLog "Credentials are not fully set!"
exit 1
fi
# iterate over all the command-line arguments.
for UPLOAD_FILE in "$@"; do
# Check if the file exists.
if [[ ! -f "${UPLOAD_FILE}" ]]; then
WriteLog "File not found: ${UPLOAD_FILE} !"
exit 1
else
WriteLog "- Uploading file: ${UPLOAD_FILE}"
fi
# Perform curl and retrieve the HTTP response_code.
response_code="$(curl \
--silent --include \
--request 'POST' \
--user "${NEXUS_USER}:${NEXUS_PASSWORD}" \
--header 'Accept: application/json' \
--header 'Content-Type: multipart/form-data' \
--form "apt.asset=@${UPLOAD_FILE};type=application/vnd.debian.binary-package" \
"${NEXUS_SERVER_URL}/service/rest/v1/components?repository=${NEXUS_REPO_NAME}" |
tee >(cat | PrependAndEscape "- " 1>&2) | grep -P "^HTTP/" | tail -n 1 | cut -d$' ' -f2)"
# Check the response code for failure.
if [[ "${response_code}" -lt 200 || "${response_code}" -ge 300 ]]; then
WriteLog "Upload failed (${response_code}) of file: ${UPLOAD_FILE} !"
exit 1
fi
done
When this error occurs it could be the GPG key private has been changed.
W: GPG error:
https://nexus.scanframe.com/repository/apt-hosted
jammy InRelease: The following signatures
couldn't be verified because the public key is not available: NO_PUBKEY
An update in the settings seems not to update the metadata folder in the repository.
To resolve this the metadata/dist
folder needs to be removed/deleted.
The metadata
folder is created and content is generated when the repository is
connected to using apt-get update
.