Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .editorconfig
100755 → 100644
Empty file.
Empty file modified .github/CONTRIBUTING.md
100755 → 100644
Empty file.
Empty file modified .github/FUNDING.yml
100755 → 100644
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/config.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/call_issue_pr_tracker.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/call_issues_cron.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/external_trigger.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/external_trigger_scheduler.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/greetings.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/package_trigger_scheduler.yml
100755 → 100644
Empty file.
Empty file modified .github/workflows/permissions.yml
100755 → 100644
Empty file.
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

FROM ghcr.io/linuxserver/unrar:latest AS unrar

FROM ghcr.io/by275/libtorrent:1-alpine3.21 AS libtorrent
FROM ghcr.io/by275/libtorrent:1-alpine3.23 AS libtorrent

FROM ghcr.io/linuxserver/baseimage-alpine:3.21
FROM ghcr.io/linuxserver/baseimage-alpine:3.23

# set version label
ARG BUILD_DATE
Expand Down Expand Up @@ -37,12 +37,14 @@ RUN \
pip \
setuptools \
wheel && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.23/ \
rencode==1.0.6 && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.23/ \
deluge[all]==${DELUGE_VERSION} \
pygeoip && \
echo "**** grab GeoIP database ****" && \
curl -L --retry 10 --retry-max-time 60 --retry-all-errors \
"https://mailfud.org/geoip-legacy/GeoIP.dat.gz" \
"https://geoip.linuxserver.io/GeoIP.dat.gz" \
| gunzip > /usr/share/GeoIP/GeoIP.dat && \
printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \
echo "**** cleanup ****" && \
Expand Down
10 changes: 6 additions & 4 deletions Dockerfile.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

FROM ghcr.io/linuxserver/unrar:arm64v8-latest AS unrar

FROM ghcr.io/by275/libtorrent:1-alpine3.21-arm64 AS libtorrent
FROM ghcr.io/by275/libtorrent:1-alpine3.23-arm64 AS libtorrent

FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.21
FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.23

# set version label
ARG BUILD_DATE
Expand Down Expand Up @@ -37,12 +37,14 @@ RUN \
pip \
setuptools \
wheel && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.23/ \
rencode==1.0.6 && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.23/ \
deluge[all]==${DELUGE_VERSION} \
pygeoip && \
echo "**** grab GeoIP database ****" && \
curl -L --retry 10 --retry-max-time 60 --retry-all-errors \
"https://mailfud.org/geoip-legacy/GeoIP.dat.gz" \
"https://geoip.linuxserver.io/GeoIP.dat.gz" \
| gunzip > /usr/share/GeoIP/GeoIP.dat && \
printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \
echo "**** cleanup ****" && \
Expand Down
110 changes: 75 additions & 35 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ pipeline {
env.META_TAG = 'libtorrentv1-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER
env.EXT_RELEASE_TAG = 'libtorrentv1-version-' + env.EXT_RELEASE_CLEAN
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
env.CITEST_IMAGETAG = 'latest'
}
}
}
Expand All @@ -233,6 +234,7 @@ pipeline {
env.EXT_RELEASE_TAG = 'libtorrentv1-version-' + env.EXT_RELEASE_CLEAN
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/'
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
env.CITEST_IMAGETAG = 'develop'
}
}
}
Expand All @@ -258,6 +260,7 @@ pipeline {
env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/pull/' + env.PULL_REQUEST
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.PR_DOCKERHUB_IMAGE + '/tags/'
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
env.CITEST_IMAGETAG = 'develop'
}
}
}
Expand All @@ -280,7 +283,7 @@ pipeline {
-v ${WORKSPACE}:/mnt \
-e AWS_ACCESS_KEY_ID=\"${S3_KEY}\" \
-e AWS_SECRET_ACCESS_KEY=\"${S3_SECRET}\" \
ghcr.io/linuxserver/baseimage-alpine:3.20 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\
ghcr.io/linuxserver/baseimage-alpine:3 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\
apk add --no-cache python3 && \
python3 -m venv /lsiopy && \
pip install --no-cache-dir -U pip && \
Expand Down Expand Up @@ -615,13 +618,16 @@ pipeline {
echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin

if [[ "${PACKAGE_CHECK}" != "true" ]]; then
declare -A pids
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
for i in "${CACHE[@]}"; do
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
pids[$!]="$i"
done
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
for p in "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
done
fi
'''
Expand Down Expand Up @@ -681,13 +687,16 @@ pipeline {
echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin

if [[ "${PACKAGE_CHECK}" != "true" ]]; then
declare -A pids
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
for i in "${CACHE[@]}"; do
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
pids[$!]="$i"
done
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
for p in "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
done
fi
'''
Expand Down Expand Up @@ -741,12 +750,14 @@ pipeline {
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin
if [[ "${PACKAGE_CHECK}" != "true" ]]; then
declare -A pids
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
for i in "${CACHE[@]}"; do
docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} &
pids[$!]="$i"
done
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
for p in "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
done
fi
'''
Expand Down Expand Up @@ -871,7 +882,7 @@ pipeline {
CI_DOCKERENV="LSIO_FIRST_PARTY=true"
fi
fi
docker pull ghcr.io/linuxserver/ci:latest
docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG}
if [ "${MULTIARCH}" == "true" ]; then
docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64
docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG}
Expand All @@ -895,7 +906,9 @@ pipeline {
-e WEB_PATH=\"${CI_WEBPATH}\" \
-e NODE_NAME=\"${NODE_NAME}\" \
-e SYFT_IMAGE_TAG=\"${CI_SYFT_IMAGE_TAG:-${SYFT_IMAGE_TAG}}\" \
-t ghcr.io/linuxserver/ci:latest \
-e COMMIT_SHA=\"${COMMIT_SHA}\" \
-e BUILD_NUMBER=\"${BUILD_NUMBER}\" \
-t ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} \
python3 test_build.py'''
}
}
Expand All @@ -921,9 +934,11 @@ pipeline {
CACHEIMAGE=${i}
fi
done
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:libtorrentv1 -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:libtorrentv1 -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
if [ -n "${SEMVER}" ]; then
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
fi
done
'''
Expand All @@ -948,20 +963,27 @@ pipeline {
CACHEIMAGE=${i}
fi
done
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-libtorrentv1 -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-libtorrentv1 -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-libtorrentv1 -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-libtorrentv1 -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
if [ -n "${SEMVER}" ]; then
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
fi
done
for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do
docker buildx imagetools create -t ${MANIFESTIMAGE}:libtorrentv1 ${MANIFESTIMAGE}:amd64-libtorrentv1 ${MANIFESTIMAGE}:arm64v8-libtorrentv1
docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG}

docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG}
docker buildx imagetools create -t ${MANIFESTIMAGE}:libtorrentv1 ${MANIFESTIMAGE}:amd64-libtorrentv1 ${MANIFESTIMAGE}:arm64v8-libtorrentv1 || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
if [ -n "${SEMVER}" ]; then
docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER}
docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
fi
done
'''
Expand All @@ -979,23 +1001,41 @@ pipeline {
environment name: 'EXIT_STATUS', value: ''
}
steps {
echo "Pushing New tag for current commit ${META_TAG}"
sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \
-d '{"tag":"'${META_TAG}'",\
"object": "'${COMMIT_SHA}'",\
"message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to libtorrentv1",\
"type": "commit",\
"tagger": {"name": "LinuxServer-CI","email": "[email protected]","date": "'${GITHUB_DATE}'"}}' '''
echo "Pushing New release for Tag"
sh '''#! /bin/bash
echo "Auto-generating release notes"
if [ "$(git tag --points-at HEAD)" != "" ]; then
echo "Existing tag points to current commit, suggesting no new LS changes"
AUTO_RELEASE_NOTES="No changes"
else
AUTO_RELEASE_NOTES=$(curl -fsL -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github+json" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases/generate-notes \
-d '{"tag_name":"'${META_TAG}'",\
"target_commitish": "libtorrentv1"}' \
| jq -r '.body' | sed 's|## What.s Changed||')
fi
echo "Pushing New tag for current commit ${META_TAG}"
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \
-d '{"tag":"'${META_TAG}'",\
"object": "'${COMMIT_SHA}'",\
"message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to libtorrentv1",\
"type": "commit",\
"tagger": {"name": "LinuxServer-CI","email": "[email protected]","date": "'${GITHUB_DATE}'"}}'
echo "Pushing New release for Tag"
echo "Updating PIP version of ${EXT_PIP} to ${EXT_RELEASE_CLEAN}" > releasebody.json
echo '{"tag_name":"'${META_TAG}'",\
"target_commitish": "libtorrentv1",\
"name": "'${META_TAG}'",\
"body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Remote Changes:**\\n\\n' > start
printf '","draft": false,"prerelease": true}' >> releasebody.json
paste -d'\\0' start releasebody.json > releasebody.json.done
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done'''
jq -n \
--arg tag_name "$META_TAG" \
--arg target_commitish "libtorrentv1" \
--arg ci_url "${CI_URL:-N/A}" \
--arg ls_notes "$AUTO_RELEASE_NOTES" \
--arg remote_notes "$(cat releasebody.json)" \
'{
"tag_name": $tag_name,
"target_commitish": $target_commitish,
"name": $tag_name,
"body": ("**CI Report:**\\n\\n" + $ci_url + "\\n\\n**LinuxServer Changes:**\\n\\n" + $ls_notes + "\\n\\n**Remote Changes:**\\n\\n" + $remote_notes),
"draft": false,
"prerelease": true }' > releasebody.json.done
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done
'''
}
}
// Add protection to the release branch
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,18 @@ Change the inbound port to 6881 (or whichever port you've mapped for the contain

This image can be run with a read-only container filesystem. For details please [read the docs](https://docs.linuxserver.io/misc/read-only/).

### Caveats

* Automatic GeoIP updates will not work

## Non-Root Operation

This image can be run with a non-root user. For details please [read the docs](https://docs.linuxserver.io/misc/non-root/).

### Caveats

* Automatic GeoIP updates will not work

## Usage

To help you get started creating a container from this image you can either use docker-compose or the docker cli.
Expand Down Expand Up @@ -315,7 +323,8 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64

## Versions

* **12.01.25:** - Rebase libtorrentv1 branch to Alpine 3.21.
* **29.12.25:** - Rebase to Alpine 3.23, update GeoIP provider, add weekly cronjob to update.
* **12.01.25:** - Rebase to Alpine 3.21.
* **19.09.24:** - Prevent race condition related delay during container stop.
* **26.08.24:** - Add libtorrentv1 tag.
* **26.12.23:** - Replace source for GeoIP database.
Expand Down
7 changes: 6 additions & 1 deletion readme-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ opt_param_usage_include_ports: true
opt_param_ports:
- {external_port: "58846", internal_port: "58846", port_desc: "Default deluged port for thin client connectivity"}
readonly_supported: true
readonly_message: |
* Automatic GeoIP updates will not work
nonroot_supported: true
nonroot_message: |
* Automatic GeoIP updates will not work
# application setup block
app_setup_block_enabled: true
app_setup_block: |
Expand Down Expand Up @@ -95,7 +99,8 @@ init_diagram: |
"deluge:libtorrentv1" <- Base Images
# changelog
changelogs:
- {date: "12.01.25:", desc: "Rebase libtorrentv1 branch to Alpine 3.21."}
- {date: "29.12.25:", desc: "Rebase to Alpine 3.23, update GeoIP provider, add weekly cronjob to update."}
- {date: "12.01.25:", desc: "Rebase to Alpine 3.21."}
- {date: "19.09.24:", desc: "Prevent race condition related delay during container stop."}
- {date: "26.08.24:", desc: "Add libtorrentv1 tag."}
- {date: "26.12.23:", desc: "Replace source for GeoIP database."}
Expand Down
Loading