#!/command/with-contenv bash
# shellcheck shell=bash

# Use /command/with-contenv shebang because /usr/bin/with-contenv is created in this script for older bases

# Version 3
# 2022-09-25 - Initial Release
MOD_SCRIPT_VER="3.20250825"

# Define custom folder paths
SCRIPTS_DIR="/custom-cont-init.d"
SERVICES_DIR="/custom-services.d"

if [[ ${DOCKER_MODS_DEBUG_CURL,,} = "true" ]]; then
    CURL_NOISE_LEVEL="-vs"
else
    CURL_NOISE_LEVEL="--silent"
fi

tamper_check() {
    # Tamper check custom service locations
    if [[ -d "${SERVICES_DIR}" ]] && [[ -n "$(find ${SERVICES_DIR}/* ! -user root 2>/dev/null)" ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║        Some of the contents of the folder ${SERVICES_DIR}            ║
║            are not owned by root, which is a security risk.             ║
║                                                                         ║
║  Please review the permissions of this folder and its contents to make  ║
║     sure they are owned by root, and can only be modified by root.      ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
    elif [[ -d "${SERVICES_DIR}" ]] && [[ -n "$(find ${SERVICES_DIR}/* -perm -o+w 2>/dev/null)" ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║        Some of the contents of the folder ${SERVICES_DIR}            ║
║      have write permissions for others, which is a security risk.       ║
║                                                                         ║
║  Please review the permissions of this folder and its contents to make  ║
║     sure they are owned by root, and can only be modified by root.      ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
    fi
    # Tamper check custom script locations
    if [[ -d "${SCRIPTS_DIR}" ]] && [[ -n "$(find ${SCRIPTS_DIR}/* ! -user root 2>/dev/null)" ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║        Some of the contents of the folder ${SCRIPTS_DIR}           ║
║            are not owned by root, which is a security risk.             ║
║                                                                         ║
║  Please review the permissions of this folder and its contents to make  ║
║     sure they are owned by root, and can only be modified by root.      ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
    elif [[ -d "${SCRIPTS_DIR}" ]] && [[ -n "$(find ${SCRIPTS_DIR}/* -perm -o+w 2>/dev/null)" ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║        Some of the contents of the folder ${SCRIPTS_DIR}           ║
║      have write permissions for others, which is a security risk.       ║
║                                                                         ║
║  Please review the permissions of this folder and its contents to make  ║
║     sure they are owned by root, and can only be modified by root.      ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
    fi
}

process_custom_services() {
    # Remove all existing custom services before continuing to ensure
    # we aren't running anything the user may have removed
    if [[ -n "$(/bin/ls -A /etc/s6-overlay/s6-rc.d/custom-svc-* 2>/dev/null)" ]]; then
        echo "[custom-init] removing existing custom services..."
        rm -rf /etc/s6-overlay/s6-rc.d/custom-svc-*
        rm /etc/s6-overlay/s6-rc.d/user/contents.d/custom-svc-*
    fi

    # Make sure custom service directory exists and has files in it
    if [[ -e "${SERVICES_DIR}" ]] && [[ -n "$(/bin/ls -A ${SERVICES_DIR} 2>/dev/null)" ]]; then
        echo "[custom-init] Service files found in ${SERVICES_DIR}"
        for SERVICE in "${SERVICES_DIR}"/*; do
            NAME="$(basename "${SERVICE}")"
            if [[ -f "${SERVICE}" ]]; then
                echo "[custom-init] ${NAME}: service detected, copying..."
                mkdir -p /etc/s6-overlay/s6-rc.d/custom-svc-"${NAME}"/dependencies.d/
                cp "${SERVICE}" /etc/s6-overlay/s6-rc.d/custom-svc-"${NAME}"/run
                chmod +x /etc/s6-overlay/s6-rc.d/custom-svc-"${NAME}"/run
                echo "longrun" >/etc/s6-overlay/s6-rc.d/custom-svc-"${NAME}"/type
                touch /etc/s6-overlay/s6-rc.d/custom-svc-"${NAME}"/dependencies.d/init-services
                touch /etc/s6-overlay/s6-rc.d/user/contents.d/custom-svc-"${NAME}"
                echo "[custom-init] ${NAME}: copied"
            elif [[ ! -f "${SERVICE}" ]]; then
                echo "[custom-init] ${NAME}: is not a file"
            fi
        done
    else
        echo "[custom-init] No custom services found, skipping..."
    fi
}

# Create our with-contenv alias with umask support
create_with_contenv_alias() {
    if [[ ! -f /command/with-contenv ]]; then
        echo "/command/with-contenv not found, skipping alias creation"
        return
    fi
    rm -rf /usr/bin/with-contenv
    # intentional tabs in the heredoc
    cat <<-EOF >/usr/bin/with-contenv
	#!/bin/bash
	if [[ -f /run/s6/container_environment/UMASK ]] &&
	    { [[ "\$(pwdx \$\$)" =~ "/run/s6/legacy-services/" ]] ||
	        [[ "\$(pwdx \$\$)" =~ "/run/s6/services/" ]] ||
	        [[ "\$(pwdx \$\$)" =~ "/servicedirs/svc-" ]]; }; then
	    umask "\$(cat /run/s6/container_environment/UMASK)"
	fi
	exec /command/with-contenv "\$@"
	EOF
    chmod +x /usr/bin/with-contenv
}

# Check for curl
curl_check() {
    if [[ ! -f /usr/bin/curl ]] || [[ ! -f /usr/bin/jq ]]; then
        write_mod_info "Curl/JQ was not found on this system and is required for Docker mods, installing..."
        if [[ -f /usr/bin/apt ]]; then
            # Ubuntu
            export DEBIAN_FRONTEND="noninteractive"
            apt-get update
            apt-get install --no-install-recommends -y \
                curl \
                jq
        elif [[ -f /sbin/apk ]]; then
            # Alpine
            apk add --no-cache \
                curl \
                jq
        elif [[ -f /usr/bin/dnf ]]; then
            # Fedora
            dnf install -y --setopt=install_weak_deps=False --best \
                curl \
                jq
        elif [[ -f /usr/sbin/pacman ]]; then
            # Arch
            pacman -Sy --noconfirm \
                curl \
                jq
        fi
    fi
}

write_mod_info() {
    local MSG=$*
    echo -e "[mod-init] $MSG"
}

write_mod_error() {
    local MSG=$*
    echo -e "[mod-init] (ERROR) $MSG"
}

write_mod_debug() {
    local MSG=$*
    if [[ ${DOCKER_MODS_DEBUG,,} = "true" ]]; then echo -e "[mod-init] (DEBUG) $MSG"; fi
}

# Use different filtering depending on URL
get_blob_sha() {
    MULTIDIGEST=$(curl  -f --retry 5 --retry-max-time 30 --retry-connrefused \
        ${CURL_NOISE_LEVEL} \
        --location \
        --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
        --header "Accept: application/vnd.oci.image.index.v1+json" \
        --header "Authorization: Bearer ${1}" \
        --user-agent "${MOD_UA}" \
        "${2}/${3}")
    if jq -e '.layers // empty' <<< "${MULTIDIGEST}" >/dev/null 2>&1; then
        # If there's a layer element it's a single-arch manifest so just get that digest
        jq -r '.layers[0].digest' <<< "${MULTIDIGEST}";
    else
        # Otherwise it's multi-arch or has manifest annotations
        if jq -e '.manifests[]?.annotations // empty' <<< "${MULTIDIGEST}" >/dev/null 2>&1; then
            # Check for manifest annotations and delete if found
            write_mod_debug "Mod has one or more manifest annotations" >&2
            MULTIDIGEST=$(jq 'del(.manifests[] | select(.annotations))' <<< "${MULTIDIGEST}")
        fi
        if [[ $(jq '.manifests | length' <<< "${MULTIDIGEST}") -gt 1 ]]; then
            # If there's still more than one digest, it's multi-arch
            write_mod_debug "Mod has a multi-arch manifest" >&2
            MULTIDIGEST=$(jq -r ".manifests[] | select(.platform.architecture == \"${4}\").digest?" <<< "${MULTIDIGEST}")
            if [[ -z "${MULTIDIGEST}" ]]; then
                exit 1
            fi
        else
            # Otherwise it's single arch
            write_mod_debug "Mod only has a single arch manifest" >&2
            MULTIDIGEST=$(jq -r ".manifests[].digest?" <<< "${MULTIDIGEST}")
        fi
        if DIGEST=$(curl  -f --retry 5 --retry-max-time 30 --retry-connrefused \
            ${CURL_NOISE_LEVEL} \
            --location \
            --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
            --header "Accept: application/vnd.oci.image.manifest.v1+json" \
            --header "Authorization: Bearer ${1}" \
            --user-agent "${MOD_UA}" \
            "${2}/${MULTIDIGEST}"); then
            jq -r '.layers[0].digest' <<< "${DIGEST}";
        fi
    fi
}

get_auth_url() {
    local auth_header
    local realm_url
    local service
    local scope
    # Call to get manifests and extract www-authenticate header
    auth_header=$(curl -sLI ${CURL_NOISE_LEVEL} "${1}/${2}" | grep -i www-authenticate | tr -d '\r')
    if [[ -n "${auth_header}" ]]; then
        write_mod_debug "${auth_header}" >&2
        # Extract realm URL from www-authenticate header
        realm_url=$(echo "$auth_header" | awk -F'[="]+' '/realm=/{print $2}')
        service=$(echo "$auth_header" | awk -F'[="]+' '/service=/{print $4}')
        scope=$(echo "$auth_header" | awk -F'[="]+' '/scope=/{print $6}')
        echo "$realm_url?service=$service&scope=$scope"
    else
        exit 1
    fi
}

get_arch(){
    local arch

    if [[ -f /sbin/apk ]]; then
        arch=$(apk --print-arch)
    elif [[ -f /usr/bin/dpkg ]]; then
        arch=$(dpkg --print-architecture)
    else
        arch=$(uname -m)
    fi

    case "${arch}" in
    x86_64 )
        arch="amd64"
        ;;
    aarch64 )
        arch="arm64"
        ;;
    esac

    echo "${arch}"
}

# Main run logic
run_mods() {
    write_mod_info "Running Docker Modification Logic"
    write_mod_debug "Running in debug mode"
    write_mod_debug "Mod script version ${MOD_SCRIPT_VER}"
    mkdir -p /modcache
    # Fetch internal fds
    FD_MAX=3
    while IFS= read -r -d '' FD; do
        if [[ $(cat "${FD}") -gt "${FD_MAX}" ]]; then
            FD_MAX=$(cat "${FD}")
        fi
    done <   <(find /etc/s6-overlay/s6-rc.d -type f -name 'notification-fd' -print0)
    for DOCKER_MOD in $(echo "${DOCKER_MODS}" | tr '|' '\n'); do
        # Support alternative endpoints
        case "${DOCKER_MOD}" in
        linuxserver/* )
            [[ ${DOCKER_MODS_FORCE_REGISTRY,,} = "true" ]] && REGISTRY="registry-1.docker.io" || REGISTRY="lscr.io"
            ;;
        docker.io/linuxserver/* )
            [[ ${DOCKER_MODS_FORCE_REGISTRY,,} = "true" ]] && REGISTRY="registry-1.docker.io" || REGISTRY="lscr.io"
            DOCKER_MOD="${DOCKER_MOD#docker.io/*}"
            ;;
        ghcr.io/linuxserver/* )
            [[ ${DOCKER_MODS_FORCE_REGISTRY,,} = "true" ]] && REGISTRY="ghcr.io" || REGISTRY="lscr.io"
            DOCKER_MOD="${DOCKER_MOD#ghcr.io/*}"
            ;;
        docker.io/* )
            REGISTRY="registry-1.docker.io"
            DOCKER_MOD="${DOCKER_MOD#docker.io/*}"
            ;;
        * )
            # Default assumption is docker.io
            REGISTRY="registry-1.docker.io"
            MOD="${DOCKER_MOD%/*}"
            # If mod still has a / after stripping off the image name it's not docker.io
            if [[ $MOD == */* ]]; then
                REGISTRY="${MOD%%/*}"
                DOCKER_MOD="${DOCKER_MOD#"$REGISTRY"/*}"
            # If "repo" name has . in it, then assume it's actually a registry with no repo
            elif [[ ${DOCKER_MOD%%/*} =~ \. ]]; then
                REGISTRY="${DOCKER_MOD%%/*}"
                DOCKER_MOD="${DOCKER_MOD##*/}"
            fi
            ;;
        esac
        # Identify what kind of image name format we're working with
        if [[ ${DOCKER_MOD} == *:*@* ]]; then
            ENDPOINT="${DOCKER_MOD%%:*}"
            USERNAME="${DOCKER_MOD%%/*}"
            REPO="${ENDPOINT#*/}"
            FULLTAG="${DOCKER_MOD#*:}"
            TAG="${FULLTAG%@*}"
            TAGSHA="${DOCKER_MOD#*@}"
        elif [[ ${DOCKER_MOD} == *@* ]]; then
            ENDPOINT="${DOCKER_MOD%%@*}"
            USERNAME="${DOCKER_MOD%%/*}"
            REPO="${ENDPOINT#*/}"
            unset FULLTAG
            unset TAG
            TAGSHA="${DOCKER_MOD#*@}"
        elif [[ ${DOCKER_MOD} == *:* ]]; then
            ENDPOINT="${DOCKER_MOD%%:*}"
            USERNAME="${DOCKER_MOD%%/*}"
            REPO="${ENDPOINT#*/}"
            unset FULLTAG
            TAG="${DOCKER_MOD#*:}"
            unset TAGSHA
        else
            # Mod has no tag
            ENDPOINT="${DOCKER_MOD}"
            USERNAME="${DOCKER_MOD%%/*}"
            REPO="${ENDPOINT#*/}"
            unset FULLTAG
            TAG="latest"
            unset TAGSHA
        fi
        FILENAME="${USERNAME}.${REPO}${TAG:+.${TAG}}${TAGSHA:+.${TAGSHA#*:}}"
        MANIFEST_URL="https://${REGISTRY}/v2/${ENDPOINT}/manifests"
        write_mod_debug "Manifest URL: ${MANIFEST_URL}"
        BLOB_URL="https://${REGISTRY}/v2/${ENDPOINT}/blobs/"
        MOD_UA="Mozilla/5.0 (Linux $(uname -m)) linuxserver.io ${REGISTRY}/${ENDPOINT}${TAG:+:${TAG}}${TAGSHA:+@${TAGSHA}}"
        write_mod_debug "Registry='${REGISTRY}', Repository='${USERNAME}', Image='${ENDPOINT}', Tag='${TAG:-N/A}', TagSHA='${TAGSHA:-N/A}'"
        case "${REGISTRY}" in
            "lscr.io") AUTH_URL="https://ghcr.io/token?scope=repository%3A${USERNAME}%2F${REPO}%3Apull";;
            "ghcr.io") AUTH_URL="https://ghcr.io/token?scope=repository%3A${USERNAME}%2F${REPO}%3Apull";;
            "quay.io") AUTH_URL="https://quay.io/v2/auth?service=quay.io&scope=repository%3A${USERNAME}%2F${REPO}%3Apull";;
            "registry-1.docker.io") AUTH_URL="https://auth.docker.io/token?service=registry.docker.io&scope=repository:${ENDPOINT}:pull";;
            *) AUTH_URL=$(get_auth_url "${MANIFEST_URL}" "${TAG:-${TAGSHA}}")
        esac
        # Kill off modification logic if any of the usernames are banned
        for BANNED in $(curl -s https://raw.githubusercontent.com/linuxserver/docker-mods/master/blacklist.txt); do
            if [[ "${BANNED,,}" == "${USERNAME,,}" ]]; then
                if [[ -z ${RUN_BANNED_MODS+x} ]]; then
                    write_mod_info "${DOCKER_MOD} is banned from use due to reported abuse, skipping mod"
                    continue
                else
                    write_mod_info "You have chosen to run banned mods, ${DOCKER_MOD} will be applied"
                fi
            fi
        done
        if [[ -n "${AUTH_URL}" ]]; then
            # Get registry token for api operations
            TOKEN="$(
                curl -f --retry 5 --retry-max-time 30 --retry-connrefused \
                    ${CURL_NOISE_LEVEL} \
                    "${AUTH_URL}" |
                    jq -r '.token'
            )"
        else
            write_mod_info "Could not fetch auth URL from registry for ${DOCKER_MOD}, attempting unauthenticated fetch"
        fi
        write_mod_info "Adding ${DOCKER_MOD} to container"
        # If we're using lscr try and get the manifest from ghcr, if it fails re-request a token from Docker Hub
        if [[ "${REGISTRY}" == "lscr.io" ]]; then
            if [[ -n $(curl --user-agent "${MOD_UA}" -sLH "Authorization: Bearer ${TOKEN}" "${MANIFEST_URL}/${TAG:-${TAGSHA}}" | jq -r '.errors' >/dev/null 2>&1) ]]; then
                write_mod_debug "Couldn't fetch manifest from ghcr.io, trying docker.io"
                AUTH_URL="https://auth.docker.io/token?service=registry.docker.io&scope=repository:${ENDPOINT}:pull"
                TOKEN="$(
                    curl -f --retry 5 --retry-max-time 30 --retry-connrefused \
                        ${CURL_NOISE_LEVEL} \
                        "${AUTH_URL}" |
                        jq -r '.token'
                )"
            fi
        fi
        if [[ -n "${AUTH_URL}" ]]; then
            write_mod_debug "Using ${AUTH_URL} as auth endpoint"
        fi
        ARCH=$(get_arch)
        write_mod_debug "Arch detected as ${ARCH}"
        if [[ -z "${TOKEN}" ]] && [[ -z $(curl -sIk "${MANIFEST_URL}") ]]; then
            write_mod_error "No response from ${REGISTRY}, switching to offline mode for ${DOCKER_MOD}"
            MOD_OFFLINE="true"
        else
            # Determine first and only layer of image
            SHALAYER=$(get_blob_sha "${TOKEN}" "${MANIFEST_URL}" "${TAGSHA:-$TAG}" "${ARCH:--amd64}")
            if [[ $? -eq 1 ]]; then
                write_mod_error "No manifest available for arch ${ARCH:--amd64}, cannot fetch mod"
                continue
            elif [[ -z "${SHALAYER}" ]]; then
                write_mod_info "${DOCKER_MOD} digest could not be fetched from ${REGISTRY}, checking local cache"
                MOD_OFFLINE="true"
            fi
            write_mod_debug "Mod SHA is ${SHALAYER:-unknown, mod may not exist}"
        fi
        # Check if we have allready applied this layer
        if [[ -f "/${FILENAME}" ]] && [[ "${SHALAYER}" == "$(cat /"${FILENAME}")" ]]; then
            write_mod_info "${DOCKER_MOD} at ${SHALAYER} has been previously applied skipping"
            unset MOD_OFFLINE
            continue
        elif [[ -f "/modcache/${FILENAME}.tar.xz" ]] && [[ "${SHALAYER}" =~ $(sha256sum "/modcache/${FILENAME}.tar.xz" | cut -f1 -d" ") ]]; then
            write_mod_info "${DOCKER_MOD} at ${SHALAYER} found in modcache, applying"
        elif [[ -f "/modcache/${FILENAME}.tar.xz" ]] && [[ "${MOD_OFFLINE}" = "true" ]]; then
            write_mod_info "OFFLINE: ${DOCKER_MOD} found in modcache"
        elif [[ ! -f "/modcache/${FILENAME}.tar.xz" ]] && [[ "${MOD_OFFLINE}" = "true" ]]; then
            write_mod_error "OFFLINE: ${DOCKER_MOD} not found in modcache, skipping"
            unset MOD_OFFLINE
            continue
        else
            write_mod_info "Downloading ${DOCKER_MOD} from ${REGISTRY}"
            if [[ -f "/modcache/${FILENAME}.lock" ]]; then
                write_mod_info "${DOCKER_MOD} is already being downloaded by another container, waiting..."
                for ((i = 5 ; i < 41 ; i=i*2 )); do
                    sleep $i
                    if [[ ! -f "/modcache/${FILENAME}.lock" ]]; then
                        SKIP_MOD_DOWNLOAD=true
                        break
                    elif [[ $i == 40 ]]; then
                        write_mod_error "${DOCKER_MOD} timed out waiting for lock, skipping\n\tIf no other containers are using this mod you may need to delete /modcache/${FILENAME}.lock"
                        SKIP_MOD=true
                    fi
                done
            fi
            if [[ "${SKIP_MOD}" == "true" ]]; then
                unset MOD_OFFLINE SKIP_MOD_DOWNLOAD SKIP_MOD
                continue
            elif [[ "${SKIP_MOD_DOWNLOAD}" != "true" ]]; then
                # Download and extract layer to /
                touch "/modcache/${FILENAME}.lock"
                curl -f --retry 5 --retry-max-time 30 --retry-all-errors \
                    ${CURL_NOISE_LEVEL} \
                    --location \
                    --header "Authorization: Bearer ${TOKEN}" \
                    --user-agent "${MOD_UA}" \
                    "${BLOB_URL}${SHALAYER}" -o \
                    "/modcache/${FILENAME}.tar.xz"
            fi
        fi
        if ! tar -tzf "/modcache/${FILENAME}.tar.xz" >/dev/null 2>&1; then
            write_mod_error "Invalid tarball for ${DOCKER_MOD}, skipping"
            if [[ -f "/modcache/${FILENAME}.lock" ]]; then
                rm "/modcache/${FILENAME}.lock" || write_mod_error "Failed to delete lock file /modcache/${FILENAME}.lock"
            fi
            unset MOD_OFFLINE SKIP_MOD_DOWNLOAD SKIP_MOD
            continue
        fi
        if [[ -z "${MODMANAGER_MODONLY}" ]]; then
            write_mod_info "Installing ${DOCKER_MOD}"
            mkdir -p /tmp/mod
            tar xzf "/modcache/${FILENAME}.tar.xz" -C /tmp/mod
            # Remove any v2 mod elements as they're no longer supported
            if [[ -d /tmp/mod/etc/cont-init.d ]]; then
                rm -rf /tmp/mod/etc/cont-init.d
            fi
            if [[ -d /tmp/mod/etc/services.d ]]; then
                rm -rf /tmp/mod/etc/services.d
            fi
            # Rationalise fds
            if [[ ! -f "/tmp/mod/fd-static" ]]; then
                while IFS= read -r -d '' FD; do
                    (( FD_MAX++ ))
                    echo $FD_MAX > "${FD}"
                done <   <(find /tmp/mod/etc/s6-overlay/s6-rc.d -type f -name 'notification-fd' -print0)
            fi
            shopt -s dotglob
            cp -R /tmp/mod/* /
            shopt -u dotglob
            rm -rf /tmp/mod
            echo "${SHALAYER}" >"/${FILENAME}"
        else
            write_mod_debug "Modmanager skipping mod application"
        fi
        if [[ -f "/modcache/${FILENAME}.lock" ]]; then
            rm "/modcache/${FILENAME}.lock" || write_mod_error "Failed to delete lock file /modcache/${FILENAME}.lock"
        fi
        if [[ -z "${MODMANAGER_MODONLY}" ]]; then
            write_mod_info "${DOCKER_MOD} applied to container"
        fi
        unset MOD_OFFLINE SKIP_MOD_DOWNLOAD SKIP_MOD
    done
}

run_mods_local() {
    write_mod_info "Running Local Docker Modification Logic"
    for DOCKER_MOD in $(echo "${DOCKER_MODS}" | tr '|' '\n'); do
        # Check mod file exists
        if [[ -f "/mods/${DOCKER_MOD}.tar" ]]; then
            # Calculate mod bits
            FILENAME="${DOCKER_MOD}.local"
            SHALAYER=$(sha256sum "/mods/${DOCKER_MOD}.tar" | cut -d " " -f 1)
            write_mod_debug "Mod checksum is ${SHALAYER}"
            # Check if we have allready applied this layer
            if [[ -f "/${FILENAME}" ]] && [[ "${SHALAYER}" == "$(cat /"${FILENAME}")" ]]; then
                write_mod_info "${DOCKER_MOD} at ${SHALAYER} has been previously applied, skipping"
            else
                write_mod_info "Installing ${DOCKER_MOD} from /mods/${DOCKER_MOD}.tar"
                mkdir -p "/tmp/mod/${DOCKER_MOD}"
                tar xf "/mods/${DOCKER_MOD}.tar" -C "/tmp/mod/${DOCKER_MOD}"
                # Remove any v2 mod elements as they're no longer supported
                if [[ -d "/tmp/mod/${DOCKER_MOD}/etc/cont-init.d" ]]; then
                    rm -rf "/tmp/mod/${DOCKER_MOD}/etc/cont-init.d"
                fi
                if [[ -d "/tmp/mod/${DOCKER_MOD}/etc/services.d" ]]; then
                    rm -rf "/tmp/mod/${DOCKER_MOD}/etc/services.d"
                fi
                shopt -s dotglob
                cp -R "/tmp/mod/${DOCKER_MOD}"/* /
                shopt -u dotglob
                rm -rf "/tmp/mod/${DOCKER_MOD}"
                echo "${SHALAYER}" >"/${FILENAME}"
                write_mod_info "${DOCKER_MOD} applied to container"
            fi
        elif [[ -d "/mods/${DOCKER_MOD}" ]]; then
            # Calculate mod bits
            FILENAME="${DOCKER_MOD}.local"
            SHALAYER=$(tar c "/mods/${DOCKER_MOD}"  2>/dev/null | sha256sum | cut -d " " -f 1)
            write_mod_debug "Mod checksum is ${SHALAYER}"
            # Check if we have allready applied this layer
            if [[ -f "/${FILENAME}" ]] && [[ "${SHALAYER}" == "$(cat /"${FILENAME}")" ]]; then
                write_mod_info "${DOCKER_MOD} at ${SHALAYER} has been previously applied, skipping"
            else
                write_mod_info "Installing ${DOCKER_MOD} from /mods/${DOCKER_MOD}/"
                mkdir -p "/tmp/mod/${DOCKER_MOD}"
                cp -R "/mods/${DOCKER_MOD}" "/tmp/mod/"
                # Remove any v2 mod elements as they're no longer supported
                if [[ -d "/tmp/mod/${DOCKER_MOD}/etc/cont-init.d" ]]; then
                    rm -rf "/tmp/mod/${DOCKER_MOD}/etc/cont-init.d"
                fi
                if [[ -d "/tmp/mod/${DOCKER_MOD}/etc/services.d" ]]; then
                    rm -rf "/tmp/mod/${DOCKER_MOD}/etc/services.d"
                fi
                shopt -s dotglob
                cp -R "/tmp/mod/${DOCKER_MOD}"/* /
                shopt -u dotglob
                rm -rf "/tmp/mod/${DOCKER_MOD}"
                echo "${SHALAYER}" >"/${FILENAME}"
                write_mod_info "${DOCKER_MOD} applied to container"
            fi
        else
            write_mod_error "${DOCKER_MOD} not found in /mods, skipping"
        fi
    done
}

run_branding() {
  # intentional tabs in the heredoc
  cat <<-EOF | tee /run/branding /etc/s6-overlay/s6-rc.d/init-adduser/branding > /dev/null 2>&1
	───────────────────────────────────────

	      ██╗     ███████╗██╗ ██████╗
	      ██║     ██╔════╝██║██╔═══██╗
	      ██║     ███████╗██║██║   ██║
	      ██║     ╚════██║██║██║   ██║
	      ███████╗███████║██║╚██████╔╝
	      ╚══════╝╚══════╝╚═╝ ╚═════╝

	   Brought to you by linuxserver.io
	───────────────────────────────────────
	EOF
}

# Main script loop
if [[ -n "${MODMANAGER_MODONLY}" ]]; then
    run_mods
    exit 0
fi

if grep -qEe ' / \w+ ro' /proc/mounts; then
    printf '1' > /run/s6/container_environment/LSIO_READ_ONLY_FS
    LSIO_READ_ONLY_FS=1
fi

if [[ ! $(stat /run -c %u) == "0" ]]; then
    printf '1' > /run/s6/container_environment/LSIO_NON_ROOT_USER
    LSIO_NON_ROOT_USER=1
fi

if [[ "${LSIO_FIRST_PARTY}" = "true" ]]; then
    run_branding
fi

if [[ -z ${LSIO_READ_ONLY_FS} ]] && [[ -z ${LSIO_NON_ROOT_USER} ]]; then
    # Run alias creation functions
    if [[ ! -f "/usr/bin/with-contenv" ]] || [[ -L "/usr/bin/with-contenv" ]]; then
        create_with_contenv_alias
    fi

    if [[ -d "${SCRIPTS_DIR}" ]] || [[ -d "${SERVICES_DIR}" ]]; then
        tamper_check
        process_custom_services
    fi

    # Run mod logic
    if [[ -n "${DOCKER_MODS+x}" ]] && [[ "${DOCKER_MODS_SIDELOAD,,}" = "true" ]]; then
        run_mods_local
    elif [[ -n "${DOCKER_MODS+x}" ]]; then
        curl_check
        run_mods
    fi
elif [[ -n ${LSIO_READ_ONLY_FS} ]] && [[ -n ${LSIO_NON_ROOT_USER} ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║    You are running this container read-only and as a non-root user:     ║
║              This combination of settings is not supported              ║
║                  and may result in unwanted behaviour.                  ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
elif [[ -n ${LSIO_READ_ONLY_FS} ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║                You are running this container read-only:                ║
║   UMASK, custom services, & docker mod functionality will be disabled   ║
║      and the PUID/PGID environment variables will have no effect.       ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
elif [[ -n ${LSIO_NON_ROOT_USER} ]]; then
echo "╔═════════════════════════════════════════════════════════════════════════╗
║                                                                         ║
║           You are running this container as a non-root user:            ║
║   UMASK, custom services, & docker mod functionality will be disabled   ║
║      and the PUID/PGID environment variables will have no effect.       ║
║                                                                         ║
╚═════════════════════════════════════════════════════════════════════════╝"
fi
