Skip to content

Instantly share code, notes, and snippets.

@Guiorgy
Last active January 5, 2026 09:47
Show Gist options
  • Select an option

  • Save Guiorgy/33bc12c3e6f396d653a6a14890e7d532 to your computer and use it in GitHub Desktop.

Select an option

Save Guiorgy/33bc12c3e6f396d653a6a14890e7d532 to your computer and use it in GitHub Desktop.
Update the WebUI theme inside a qBittorrent container. The cjratliff theme is hardcoded, so modify the script if another one is used.
#!/usr/bin/env bash
# ============================================================================= #
# Copyright © 2025 Guiorgy #
# #
# This program is free software: you can redistribute it and/or modify it under #
# the terms of the GNU General Public License as published by the Free Software #
# Foundation, either version 3 of the License, or (at your option) any later #
# version. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
# FOR A PARTICULAR PURPOSE. #
# #
# You can see the full GNU General Public License at #
# <https://www.gnu.org/licenses/> for more details. #
# ============================================================================= #
# Usage:
# - Place the script inside the config volume, e.g. /va/lib/docker/volumes/qbittorrent_config/_data
# - Make it executable, e.g chmod +x ./update-theme.sh
# - Stop the container before updating the theme, e.g. docker stop qBittorrent
# In order to apply the theme the container needs to be restarted, but when stopping, the current config
# is saved into the config file, overwriting any changes made while the container was running.
# - Apply the new theme by executing the script, e.g. sudo -u 1000 ./update-theme.sh
# - Start the stopped container, e.g. docker start qBittorrent
NC='\033[0m' # reset
ERR='\033[0;31m' # red
OK='\033[0;32m' # green
WARN='\033[0;33m' # yellow
ACC='\033[0;94m' # bright blue
if [[ "$UID" -ne '1000' ]]; then
echo -e "${ERR}Error${NC}: This script must be run by the user with UID ${ACC}1000${NC} (${ACC}qbtUser${NC})" 1>&2
exit 1
fi
cd "$(dirname -- "$0")"
set -Eeo pipefail
handle_error() {
error_code=$?
echo -e "${ERR}Script failed on line #${1} with error code ${error_code}!${NC}" 1>&2
exit $error_code
}
trap 'handle_error $LINENO' ERR
print() {
COLOR="$WARN"
if [[ $# -gt 1 ]]; then
case "$1" in
--*)
case "$1" in
--no-color) COLOR="$NC" ;;
--error) COLOR="$ERR" ;;
--ok) COLOR="$OK" ;;
--warn) COLOR="$WARN" ;;
--accent) COLOR="$ACC" ;;
*) error 'Unrecognized color' ;;
esac
shift
;;
*) ;;
esac
fi
if [[ $# -gt 1 ]]; then
if [[ -n "$1" ]]; then
echo -e -n "${COLOR}${1}${NC}: "
fi
shift
fi
echo -e "$1"
}
error() {
print --error 'Error' "${1}" 1>&2
if [[ -n "$2" ]]; then
exit "$2"
else
exit 1
fi
}
releaseTag="$1"
if [[ -z "$releaseTag" ]]; then
print 'Getting the latest release tag from GitHub'
response=$(curl --silent --show-error 'https://api.github.com/repos/Carve/qbittorrent-webui-cjratliff.com/releases/latest')
releaseTag=$(grep -m 1 '"tag_name"' <<< "$response" | cut -d : -d '"' -f 4) || error "Failed to grep the release tag. Response from GitHub: ${ACC}${response}${NC}"
print "Latest release tag: ${ACC}${releaseTag}${NC}"
fi
if ! [[ "$releaseTag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
error "The specified release tag '${ACC}${releaseTag}${NC}' is not in the correct format"
fi
currentBundle=$(find . -mindepth 1 -maxdepth 1 -type d -regex '^.+-[0-9]+\.[0-9]+\.[0-9]+$' -print -quit)
if [[ -n "$currentBundle" ]]; then
currentTag=$(echo "$currentBundle" | sed -E 's/.*([0-9]+\.[0-9]+\.[0-9]+)$/v\1/')
if [[ "$currentTag" = "$releaseTag" ]]; then
print --ok "Already Installed" "Release tag '${ACC}${releaseTag}${NC}' already installed"
exit 0
else
print "Current release tag: '${ACC}${currentTag}${NC}'"
fi
fi
releaseArchive="${releaseTag}.tar.gz"
print "Downloading '${ACC}${releaseArchive}${NC}'"
curl -sSLO "https://github.com/Carve/qbittorrent-webui-cjratliff.com/archive/refs/tags/${releaseArchive}" || error "Failed to download release '${ACC}${releaseTag}${NC}'"
print "Unpacking '${ACC}${releaseArchive}${NC}'"
tar -xzf "${releaseArchive}" || error 'Failed to unpack the source archive'
if [[ -n "$currentBundle" ]]; then
print "Removinf the old release"
rm -rf "$currentBundle"
fi
currentBundle=$(find . -mindepth 1 -maxdepth 1 -type d -regex '^.+-[0-9]+\.[0-9]+\.[0-9]+$' -print -quit | sed 's/^\.\///')
if [[ -z "$currentBundle" ]]; then
error "Extracted files not found"
fi
print "Setting permissions for extracted files"
chmod -R g-w,o-rwx "$currentBundle"
print "Removing downloaded archive"
rm "${releaseArchive}"
currentBundle="/config/$currentBundle"
print "Changing configured theme to '${ACC}${currentBundle}${NC}'"
sed -i "s|^\\(WebUI\\\\RootFolder=\\).*\$|\\1${currentBundle}|" './qBittorrent/config/qBittorrent.conf' \
|| print --warn 'Warning' "Failed to change the configured theme to the new version. Manually set the theme to '${ACC}${currentBundle}${NC}'"
print --ok 'Done' "Successfully updated to '${ACC}${releaseTag}${NC}'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment