Last active
January 5, 2026 09:47
-
-
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.
This file contains hidden or 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
| #!/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