-
-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
I whipped this up with ChatGPT in a hurry. Works well! Basically, after every apt install/reinstall command, this shell script will be run. It checks if the solarized patch is applied and reacts accordingly.
shell script
Create a new shell script file: nano /usr/local/sbin/apply-pve-dark-theme-patch.sh and paste these contents:
don't forget to make it executable: chmod +x /usr/local/sbin/apply-pve-dark-theme-patch.sh
#!/usr/bin/env bash
# ==============================================================================
# Proxmox Dark Theme Patcher
#
# This script patches the Proxmox index.html.tpl to add a dark theme helper
# and restarts the pveproxy service to apply the change.
# It is idempotent and designed to be run by an APT hook.
# ==============================================================================
# --- Strict Mode & Configuration ---
# Exit on error, treat unset variables as errors, and propagate exit status
# through pipes.
set -o errexit
set -o nounset
set -o pipefail
# --- Global Constants ---
readonly TARGET_FILE="/usr/share/pve-manager/index.html.tpl"
readonly CHECK_STRING="solarized.css"
# mktemp creates the file for us securely
readonly SNIPPET_FILE=$(mktemp)
# --- Color-coded Logging ---
# Check if stdout is a terminal before using colors
if [[ -t 1 ]]; then
readonly C_RESET='\e[0m'
readonly C_RED='\e[0;31m'
readonly C_GREEN='\e[0;32m'
readonly C_YELLOW='\e[0;33m'
readonly C_BLUE='\e[0;34m'
else
readonly C_RESET=''
readonly C_RED=''
readonly C_GREEN=''
readonly C_YELLOW=''
readonly C_BLUE=''
fi
# Logging function
log() {
local level="$1"
local color="$2"
shift 2
local message="$@"
echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] [${level}]${C_RESET} ${message}"
}
info() { log "INFO" "${C_BLUE}" "$@"; }
success() { log "SUCCESS" "${C_GREEN}" "$@"; }
warn() { log "WARNING" "${C_YELLOW}" "$@"; }
error() { log "ERROR" "${C_RED}" "$@"; }
# --- Cleanup Function ---
# This function is called on any script exit to ensure the temp file is removed.
cleanup() {
rm -f "${SNIPPET_FILE}"
}
trap cleanup EXIT
# --- Main Logic ---
main() {
info "PVE Dark Theme Patcher started."
# 1. Pre-flight Checks
info "Running pre-flight checks..."
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root."
exit 1
fi
if [[ ! -f "$TARGET_FILE" ]]; then
error "Target file not found: $TARGET_FILE"
exit 1
fi
if [[ ! -w "$TARGET_FILE" ]]; then
error "Target file is not writable: $TARGET_FILE"
exit 1
fi
success "Pre-flight checks passed."
# 2. Check if Patch is Already Applied
if grep -q "$CHECK_STRING" "$TARGET_FILE"; then
success "Patch is already applied. No action needed."
exit 0
fi
info "Patch not found. Proceeding with installation."
# 3. Define and Write Snippet
# Using a local variable for the snippet keeps it contained to the main function.
local snippet
snippet='<script>
document.addEventListener("DOMContentLoaded", () => {
// Detect if Proxmox’s dark stylesheet is loaded
const darkLink = document.querySelector(
"link[href*=\"theme-proxmox-dark.css\"]"
);
if (darkLink) {
document.body.classList.add("proxmox-theme-dark");
}
});
</script>
<link rel="stylesheet" href="/pve2/images/solarized.css">'
if ! echo "$snippet" > "$SNIPPET_FILE"; then
error "Failed to write snippet to temporary file: $SNIPPET_FILE"
exit 1
fi
# 4. Apply the Patch
info "Backing up original file to ${TARGET_FILE}.bak"
if ! cp "$TARGET_FILE" "${TARGET_FILE}.bak"; then
error "Failed to create backup file."
exit 1
fi
info "Applying patch..."
# Your clever solution to insert after <html>, which works well.
if ! sed -i "/<html>/r $SNIPPET_FILE" "$TARGET_FILE"; then
error "Failed to apply patch with sed. Restoring from backup."
mv "${TARGET_FILE}.bak" "$TARGET_FILE"
exit 1
fi
success "Patch applied successfully."
# 5. Restart Service
info "Restarting pveproxy service..."
if ! systemctl restart pveproxy.service; then
error "Failed to restart pveproxy.service. Please check the service status manually with 'systemctl status pveproxy.service'."
exit 1
fi
# Optional: Verify the service is actually running
if systemctl is-active --quiet pveproxy.service; then
success "Service restarted successfully."
info "Hard-refresh your browser (Ctrl+F5) to see the changes."
else
warn "The pveproxy.service was restarted but is not currently active. Please investigate."
fi
info "Script finished."
}
# --- Execute Script ---
# Run the main function, passing along any arguments.
main "$@"apt dpkg hook
Create a file: nano /etc/apt/apt.conf.d/99-pve-dark-theme-hook and add this line:
DPkg::Post-Invoke { "/usr/local/sbin/apply-pve-dark-theme-patch.sh"; };test
You can test that the hook is working properly by issuing apt reinstall nano
❯ apt reinstall nano
The following package was automatically installed and is no longer required:
proxmox-headers-6.14.11-2-pve
Use 'apt autoremove' to remove it.
Summary:
Upgrading: 0, Installing: 0, Reinstalling: 1, Removing: 0, Not Upgrading: 0
Download size: 645 kB
Space needed: 0 B / 58.5 GB available
Get:1 http://deb.debian.org/debian trixie/main amd64 nano amd64 8.4-1 [645 kB]
Fetched 645 kB in 0s (8,426 kB/s)
(Reading database ... 132510 files and directories currently installed.)
Preparing to unpack .../archives/nano_8.4-1_amd64.deb ...
Unpacking nano (8.4-1) over (8.4-1) ...
Setting up nano (8.4-1) ...
Processing triggers for man-db (2.13.1-1) ...
[2025-10-04 13:16:30] [INFO] PVE Dark Theme Patcher started.
[2025-10-04 13:16:30] [INFO] Running pre-flight checks...
[2025-10-04 13:16:30] [SUCCESS] Pre-flight checks passed.
[2025-10-04 13:16:30] [SUCCESS] Patch is already applied. No action needed.Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels