Skip to content

Instantly share code, notes, and snippets.

@ravensorb
Last active March 6, 2022 23:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ravensorb/bd875132ecd08326d2f8e7453a4f1dcf to your computer and use it in GitHub Desktop.
Save ravensorb/bd875132ecd08326d2f8e7453a4f1dcf to your computer and use it in GitHub Desktop.
Updated docker-mods script for linuxserver.io base images to allow for accessing mods from harbor (and possibly other) registries
#!/usr/bin/with-contenv bash
# Exit if mods is not set
if [ -z ${DOCKER_MODS+x} ]; then
exit 0
fi
# Check for curl
if [ ! -f /usr/bin/curl ] || [ ! -f /usr/bin/jq ]; then
write_log "Curl/JQ was not found on this system for Docker mods installing"
if [ -f /usr/bin/apt ]; then
## Ubuntu
apt-get update
apt-get install --no-install-recommends -y \
curl \
jq
elif [ -f /sbin/apk ]; then
# Alpine
apk add --no-cache \
curl \
jq
fi
fi
## Functions
write_log() {
echo "[mod-init] $@"
}
write_debug() {
[[ "$DOCKER_MODS_DEBUG" == "1" ]] && echo "[mod-init-ex:debug] $@"
}
get_url () {
local url="$1"
local bearer_token="$2"
curl \
--silent \
--location \
--request GET \
--http1.1 \
${DOCKER_MODS_ALLOW_INSECURE:+--insecure} \
${bearer_token:+--header} ${bearer_token:+Authorization: Bearer $bearer_token} \
"$url"
}
# Use different filtering depending on URL
get_blob_sha () {
echo $(get_url "$1" "$2") | jq -r '.fsLayers[0].blobSum,.layers[0].digest | select(. | .!=null and .!="")'
}
get_auth_token () {
echo $(get_url "$1") | jq -r '.token'
}
apply_image_layer () {
local url="$1"
local bearer_token="$2"
curl \
--silent \
--location \
--request GET \
--http1.1 \
${DOCKER_MODS_ALLOW_INSECURE:+--insecure} \
${bearer_token:+--header} ${bearer_token:+Authorization: Bearer $bearer_token} \
"$url" | tar xz -C ${3:-/}
}
handle_blacklist () {
# Kill off modification logic if any of the usernames are banned
BLACKLIST=$(get_url "https://raw.githubusercontent.com/linuxserver/docker-mods/master/blacklist.txt")
IFS=$'\n'
BLACKLIST=(${BLACKLIST})
for BANNED in "${BLACKLIST[@]}"; do
if [ "${BANNED}" == "${1,,}" ]; then
if [ -z ${RUN_BANNED_MODS+x} ]; then
write_log "${2} is banned from use due to reported abuse aborting mod logic"
exit 0
else
write_log "You have chosen to run banned mods ${2} will be applied"
fi
fi
done
}
# Main run logic
write_log "Attempting to run Docker Modification Logic"
IFS='|'
DOCKER_MODS=(${DOCKER_MODS})
for DOCKER_MOD in "${DOCKER_MODS[@]}"; do
write_log "Processing Request for mod '$DOCKER_MOD'"
# Support alternative endpoints
if [[ ${DOCKER_MOD} =~ .*/.*/.* ]] ; then
write_log "Found registry url in mod name"
DOCKER_MOD_REGISTRY=${DOCKER_MOD%%/*}
DOCKER_MOD=${DOCKER_MOD#*/}
fi
IMAGE_ENDPOINT="${DOCKER_MOD%%:*}"
IMAGE_USERNAME="${DOCKER_MOD%%/*}"
IMAGE_REPO="${IMAGE_ENDPOINT#*/}"
IMAGE_TAG="${DOCKER_MOD#*:}"
if [[ ${IMAGE_TAG} == "${DOCKER_MOD}" ]]; then
IMAGE_TAG="latest"
fi
SHACACHE_FILENAME="${IMAGE_USERNAME}.${IMAGE_REPO}.${IMAGE_TAG}"
REGISTRY_AUTH_SERVICE="registry.docker.io"
if [[ ${DOCKER_MOD_REGISTRY} == ghcr.io/* ]] || [[ ${DOCKER_MOD} == linuxserver/* ]]; then
REGISTRY_AUTH_URL_BASE="https://ghcr.io/token"
REGISTRY_URL_BASE="https://ghcr.io/v2"
elif [[ ! -z "${DOCKER_MOD_REGISTRY}" ]]; then
REGISTRY_AUTH_URL_BASE="https://${DOCKER_MOD_REGISTRY}/service/token"
REGISTRY_URL_BASE="https://${DOCKER_MOD_REGISTRY}/v2"
# Need a better way to handle this
[[ ${DOCKER_MOD_REGISTRY} == *"harbor"* && -z ${DOCKER_MOD_REGISTRY_AUTH_SERVICE} ]] && REGISTRY_AUTH_SERVICE="harbor-registry" || REGISTRY_AUTH_SERVICE=$DOCKER_MOD_REGISTRY
else
REGISTRY_AUTH_URL_BASE="https://auth.docker.io/token"
REGISTRY_URL_BASE="https://registry-1.docker.io/v2"
REGISTRY_AUTH_QSP_SERVICE="service=registry.docker.io&"
fi
REGISTRY_AUTH_URL="${REGISTRY_AUTH_URL_BASE}?service=$REGISTRY_AUTH_SERVICE&scope=repository:${IMAGE_ENDPOINT}:pull"
REGISTRY_MANIFEST_URL="${REGISTRY_URL_BASE}/${IMAGE_ENDPOINT}/manifests/${IMAGE_TAG}"
REGISTRY_BLOB_URL="${REGISTRY_URL_BASE}/${IMAGE_ENDPOINT}/blobs/"
write_debug "Auth URL : $REGISTRY_AUTH_URL"
write_debug "Manifest URL: $REGISTRY_MANIFEST_URL"
write_debug "Blobl URL : $REGISTRY_BLOB_URL"
write_log "Checking Blacklist"
handle_blacklist "${IMAGE_USERNAME}" "${DOCKER_MOD}"
write_log "Getting Authentication Token"
# Get Registry token for api operations
REGISTRY_AUTH_TOKEN=$(get_auth_token "${REGISTRY_AUTH_URL}")
# Determine first and only layer of image
if [[ -z ${REGISTRY_AUTH_TOKEN} ]]; then
write_log "Unable to request auth token. "
else
write_log "Getting image layer information"
SHALAYER=$(get_blob_sha "${REGISTRY_MANIFEST_URL}" "${REGISTRY_AUTH_TOKEN}")
if [[ -z ${SHALAYER} ]]; then
write_log "Unable to request image layer information. "
else
# Check if we have allready applied this layer
if [ -f "/${SHACACHE_FILENAME}" ] && [ "${SHALAYER}" == "$(cat /${SHACACHE_FILENAME})" ]; then
write_log "${DOCKER_MOD} at ${SHALAYER} has been previously applied skipping"
else
write_log "Applying ${DOCKER_MOD} files to container"
apply_image_layer "${REGISTRY_BLOB_URL}${SHALAYER}" "${REGISTRY_AUTH_TOKEN}" "/"
echo ${SHALAYER} > "/${SHACACHE_FILENAME}"
fi
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment