-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
1,919 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: BitTorrent Seeder | ||
|
||
on: | ||
push: | ||
branches: | ||
- 'main' | ||
paths: | ||
- 'bittorrent-seeder/**' | ||
workflow_dispatch: | ||
|
||
jobs: | ||
|
||
bittorrent-tracker: | ||
name: Deploy BitTorrent Seeder Image | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- uses: actions/[email protected] | ||
- name: Publish Docker Image | ||
uses: openzim/docker-publish-action@v10 | ||
with: | ||
image-name: kiwix/bittorrent-seeder | ||
on-master: latest | ||
restrict-to: kiwix/container-images | ||
context: bittorrent-seeder | ||
registries: ghcr.io | ||
credentials: | ||
GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }} | ||
GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
FROM alpine:edge | ||
|
||
ENV SHELL=bash | ||
|
||
RUN set -e \ | ||
# add testing repo for qbittorrent-cli | ||
&& echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ | ||
&& apk update \ | ||
&& apk --no-cache add dumb-init bash \ | ||
&& apk --no-cache add python3 py3-pip \ | ||
# the daemon with webui \ | ||
&& apk --no-cache add qbittorrent-nox \ | ||
# for convenience | ||
&& apk --no-cache add qbittorrent-cli | ||
|
||
ENV NO_DAEMON="" | ||
ENV QBT_TORRENTING_PORT=6901 | ||
ENV QBT_HOST=localhost | ||
ENV QBT_PORT=80 | ||
ENV QBT_USERNAME=admin | ||
ENV QBT_PASSWORD= | ||
|
||
|
||
COPY entrypoint.sh /usr/local/bin/entrypoint | ||
COPY pyproject.toml README.md tasks.py /src/ | ||
COPY src/ /src/src | ||
COPY gen-password.py /usr/local/bin/gen-password | ||
COPY get-pbkdf2.py /usr/local/bin/get-pbkdf2 | ||
|
||
RUN set -e \ | ||
&& pip install --break-system-packages /src/ \ | ||
&& kiwix-seeder --help | ||
|
||
EXPOSE 80 | ||
EXPOSE 6901 | ||
VOLUME /data | ||
WORKDIR /data | ||
|
||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/entrypoint"] | ||
CMD ["kiwix-seeder", "--loop"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
## Kiwix Seeder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#!/bin/sh | ||
|
||
function start_qbt { | ||
echo "Starting a qbittorrent-nox process (set NO_DAEMON if you dont want to)" | ||
|
||
QBT_HOST="${QBT_HOST:-localhost}" | ||
QBT_PORT="${QBT_PORT:-80}" | ||
QBT_USERNAME="${QBT_USERNAME:-admin}" | ||
QBT_TORRENTING_PORT="${QBT_TORRENTING_PORT:-6901}" | ||
|
||
QBT_MAX_CONNECTIONS="${QBT_MAX_CONNECTIONS:-500}" | ||
QBT_MAX_CONNECTIONS_PER_TORRENT="${QBT_MAX_CONNECTIONS_PER_TORRENT:-100}" | ||
QBT_MAX_UPLOADS="${QBT_MAX_UPLOADS:-20}" | ||
QBT_MAX_UPLOADS_PER_TORRENT="${QBT_MAX_UPLOADS_PER_TORRENT:-5}" | ||
|
||
if [ "x${QBT_PASSWORD}" = "x" ]; then | ||
QBT_PASSWORD=$(gen-password) | ||
echo "Generated web-ui password: ${QBT_PASSWORD}" | ||
fi | ||
PKBF2_PASSWORD=$(get-pbkdf2 "${QBT_PASSWORD}") | ||
|
||
QBITTORRENT_CONFIG_FILE=/root/.config/qBittorrent/qBittorrent.conf | ||
mkdir -p $(dirname $QBITTORRENT_CONFIG_FILE) | ||
cat <<EOF > $QBITTORRENT_CONFIG_FILE | ||
[BitTorrent] | ||
MergeTrackersEnabled=true | ||
Session\DefaultSavePath=/data | ||
Session\AddExtensionToIncompleteFiles=true | ||
Session\MaxConnections=${QBT_MAX_CONNECTIONS} | ||
Session\MaxConnectionsPerTorrent=${QBT_MAX_CONNECTIONS_PER_TORRENT} | ||
Session\MaxUploads=${QBT_MAX_UPLOADS} | ||
Session\MaxUploadsPerTorrent=${QBT_MAX_UPLOADS_PER_TORRENT} | ||
Session\Port=${QBT_TORRENTING_PORT} | ||
Session\Preallocation=true | ||
Session\QueueingSystemEnabled=false | ||
Session\SSL\Port=30154 | ||
[LegalNotice] | ||
Accepted=true | ||
[Meta] | ||
MigrationVersion=8 | ||
[Preferences] | ||
General\Locale=en | ||
WebUI\Enabled=true | ||
WebUI\Port=${QBT_PORT} | ||
WebUI\Username=${QBT_USERNAME} | ||
WebUI\Password_PBKDF2="@ByteArray(${PKBF2_PASSWORD})" | ||
WebUI\LocalHostAuth=true | ||
WebUI\HostHeaderValidation=false | ||
WebUI\CSRFProtection=false | ||
[Core] | ||
AutoDeleteAddedTorrentFile=Always | ||
[Application] | ||
FileLogger\Age=5 | ||
FileLogger\AgeType=0 | ||
FileLogger\Backup=true | ||
FileLogger\DeleteOld=true | ||
FileLogger\Enabled=true | ||
FileLogger\MaxSizeBytes=1048576 | ||
FileLogger\Path=/var/log | ||
GUI\Notifications\TorrentAdded=false | ||
EOF | ||
|
||
QBT_CONFIG_FILE=/root/.config/qbt/.qbt.toml | ||
mkdir -p $(dirname $QBT_CONFIG_FILE) | ||
cat <<EOF > $QBT_CONFIG_FILE | ||
[qbittorrent] | ||
addr = "http://${QBT_HOST}:${QBT_PORT}" # qbittorrent webui-api hostname/ip | ||
login = "${QBT_USERNAME}" # qbittorrent webui-api user | ||
password = "${QBT_PASSWORD}" # qbittorrent webui-api password | ||
#basicUser = "user" # qbittorrent webui-api basic auth user | ||
#basicPass = "password" # qbittorrent webui-api basic auth password | ||
[rules] | ||
enabled = true # enable or disable rules | ||
max_active_downloads = 2 # set max active downloads | ||
EOF | ||
|
||
mkdir -p ~/.config/qbt && touch ~/.config/qbt/.qbt.toml | ||
|
||
|
||
# qbittorrent-nox --help | ||
qbittorrent-nox --save-path=/data --daemon | ||
rc=$? | ||
echo "rc=${rc}" | ||
} | ||
|
||
if [ "x${NO_DAEMON}" = "x" ]; then | ||
start_qbt | ||
fi | ||
|
||
exec "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env python | ||
|
||
"""command line to generate a short (8chars) password from alphanum""" | ||
|
||
import secrets | ||
import string | ||
import sys | ||
|
||
|
||
def gen_password() -> str: | ||
alphabet = string.ascii_letters + string.digits | ||
return "".join(secrets.choice(alphabet) for _ in range(8)) | ||
|
||
|
||
def main() -> int: | ||
print(gen_password()) # noqa: T201 | ||
return 0 | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/usr/bin/env python | ||
|
||
""" command line to generate a base64-encoded PBKDF2 version of a password | ||
similar to how qBittorrent stores web-ui password in its config file. | ||
Format is salt:HMAC""" | ||
|
||
import base64 | ||
import hashlib | ||
import secrets | ||
import sys | ||
|
||
|
||
def asb64(data: bytes) -> str: | ||
return base64.b64encode(data).decode("ASCII") | ||
|
||
|
||
def get_pbkdf2_for(password: str) -> str: | ||
salt = secrets.token_bytes(16) | ||
hmac = hashlib.pbkdf2_hmac( | ||
hash_name="sha512", | ||
password=password.encode("UTF-8"), | ||
salt=salt, | ||
iterations=100000, | ||
) | ||
return f"{asb64(salt)}:{asb64(hmac)}" | ||
|
||
|
||
def main() -> int: | ||
if len(sys.argv) != 2: # noqa: PLR2004 | ||
print(f"Usage: {sys.argv[0]} CLEAR_PASSWORD") # noqa: T201 | ||
return 1 | ||
print(get_pbkdf2_for(sys.argv[1])) # noqa: T201 | ||
return 0 | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
Oops, something went wrong.