ProxMorph
Custom themes for Proxmox VE (PVE), Proxmox Backup Server (PBS), and Proxmox Datacenter Manager (PDM) that integrate with the native Color Theme selector.
✨ Features
- Native Integration - Themes appear in built-in Color Theme dropdown (PVE, PBS, and PDM)
- Auto-Patch on Updates - Automatically re-applies themes after product updates
- Hybrid Engine - CSS for styling + JavaScript for dynamic chart patching
- Server-Side Default Theme - Pick a default for browsers that have not chosen one yet; a user’s own selection always wins
- Automatic Light/Dark - Opt-in “(Auto)” entries per collection that follow the system color scheme live (PVE, PBS)
- Custom UI Font - Any font family on top of any theme, from an installed system font or an embedded WOFF2/WOFF/TTF/OTF file, with the icon fonts left untouched (PVE, PBS, PDM)
- Hardware Sensor Monitoring - Optional CPU/storage temps, fan speeds, and UPS status on node Summary dashboard (PVE)
- Easy Installation - Single command installation for PVE, PBS, and PDM
📸 Screenshot
Comparison between default Proxmox Dark theme and UniFi theme:

🎨 Themes
24 themes across 10 collections on PVE, PBS and PDM. Featured themes below. View Full Gallery →
UniFi
Inspired by Ubiquiti UniFi Network Application
|
Dracula
Classic Dracula dark with purple accent
|
Catppuccin Mocha
Darkest Catppuccin flavor, deep warm tones
|
Nord Dark
Arctic dark palette with polar blue accent
|
All Available Collections
| Collection |
Themes |
| Catppuccin |
Mocha, Mocha Teal, Macchiato, Frappé, Latte |
| Dracula |
Classic, Midnight, Pink, Cyan, Green, Orange |
| Nord |
Dark, Light |
| Gruvbox |
Dark, Light |
| Solarized |
Dark, Light |
| Tokyo Night |
Single theme |
| UniFi |
Dark, Light, OLED |
| GitHub Dark |
Single theme |
| Blue Slate |
Single theme |
| ESXi Light (by @rufftruffles) |
Single theme (PVE and PBS with bundled Clarity City fonts; PDM palette only) |
🚀 Installation
One-Liner Install
bash <(curl -fsSL https://raw.githubusercontent.com/IT-BAER/proxmorph/main/install.sh) install
Manual Install
git clone https://github.com/IT-BAER/proxmorph.git
cd proxmorph
chmod +x install.sh
./install.sh install
Verify before you run
Every release ships a SHA256SUMS manifest and a GitHub build-provenance attestation. The installer verifies the downloaded tarball against SHA256SUMS automatically and refuses to install on a mismatch, or if the manifest is missing (fail closed). That runs on the Proxmox host with tools already present (sha256sum), so normal install and update stay a single command with no extra setup.
For stronger, provenance-level checks, verify a release on your workstation before you roll it out (a stock Proxmox host has no gh CLI, so this step belongs on your machine, not the node):
# integrity: do the bytes match the published manifest?
curl -fsSLO https://github.com/IT-BAER/proxmorph/releases/download/v<ver>/proxmorph-<ver>.tar.gz
curl -fsSLO https://github.com/IT-BAER/proxmorph/releases/download/v<ver>/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
# provenance: was it built by this repo's release workflow?
gh attestation verify proxmorph-<ver>.tar.gz --repo IT-BAER/proxmorph
What each gives you: SHA256SUMS proves the bytes match what was published with the release (integrity). The attestation gives you a Sigstore/OIDC chain tying the artifact to this repository’s Actions build, so you can check origin against something other than the transport. It is a check you opt into, not something the host enforces; neither replaces reading install.sh before running it as root. The What the installer changes section lists exactly what it touches.
Install from a clone (review first)
git clone https://github.com/IT-BAER/proxmorph.git
cd proxmorph
git checkout v<ver> # pin a release
less install.sh # read it
./install.sh install # installs from the local files, no download
Install from an internal mirror
For air-gapped or policy-controlled environments, point the installer at your own copy of the release artifacts. PROXMORPH_RELEASE_BASE is the directory that directly contains proxmorph-<ver>.tar.gz and SHA256SUMS:
PROXMORPH_RELEASE_BASE=https://mirror.example.internal/proxmorph \
./install.sh update <ver>
Checksum verification still runs, against your mirrored SHA256SUMS.
Apply Theme
- Hard refresh browser (Ctrl+Shift+R)
- Click username → Color Theme
- Select a ProxMorph theme
Automatic light/dark switching
Opt in once per host, then pick an “(Auto)” entry in the Color Theme dialog:
./install.sh auto-theme enable
Each entry is a small generated stylesheet that imports the light or dark member of a collection through the browser’s prefers-color-scheme, so the theme follows the system setting live, without a reload. Pairs: UniFi (UniFi Light / UniFi), UniFi OLED (UniFi Light / UniFi OLED), Nord, Gruvbox, Solarized and Catppuccin (Latte / Mocha). The entries survive ProxMorph and Proxmox updates while enabled; ./install.sh auto-theme disable removes them again. They also work as server-side default, for example ./install.sh default-theme unifi-auto. Not available on PDM.
Custom UI font
Replace the UI text font for every theme without touching the icon fonts:
./install.sh font Inter https://cdn.jsdelivr.net/npm/@fontsource/[email protected]/files/inter-latin-400-normal.woff2
./install.sh font "Segoe UI"
./install.sh font none
A font file (.woff2, .woff, .ttf or .otf; a local path, or an https URL fetched once on the host; up to 4 MB) is embedded into a generated stylesheet, so browsers never load anything from the internet. With only a family name, the font has to be installed on the viewing machine. The stylesheet targets the ExtJS text selectors only, never .fa, .x-fa or the tree expanders, so FontAwesome and the status glyphs keep working, and it is linked after the active theme, so it also applies on top of ESXi Light’s bundled Clarity City. The setting lives in /etc/proxmorph/font and survives ProxMorph and Proxmox updates. On PDM, which sets its font rule by rule, the selectors are read from the installed PDM stylesheets each time the font is applied and again after every PDM update, so the font also follows changes in new PDM releases.
💻 Commands
| Command |
Description |
./install.sh install |
Install themes (fetches the latest release when no local theme files are present) |
./install.sh update [version] or bash <(curl -fsSL https://raw.githubusercontent.com/IT-BAER/proxmorph/main/install.sh) update |
Download a release from GitHub (latest, or the given version) and install its themes |
./install.sh reinstall |
Re-apply themes and patches, e.g. after a Proxmox update |
./install.sh uninstall |
Remove themes |
./install.sh list |
List available themes and whether each is installed |
./install.sh status |
Show installation status |
./install.sh check |
Check whether a newer release is available |
./install.sh sensors [enable|disable|detect|configure|status] |
Manage hardware sensor display (PVE only; default status) |
./install.sh default-theme <key|none> |
Set a server-side default theme for new browsers (user choice always wins) |
./install.sh auto-theme [enable|disable|status] |
Add or remove “(Auto)” dropdown entries that follow the system light/dark setting (PVE, PBS; default status) |
./install.sh font [<family> [file|url] | none] |
Set or clear a custom UI text font, icon-safe (no argument shows the current setting) |
./install.sh |
Shows Menu to manage |
🔍 What the installer changes on your system
Run as root, install.sh makes only these changes, all reversible with ./install.sh uninstall:
- Themes: copies
theme-*.css into the product’s widget-toolkit themes directory.
- Theme registration:
sed-patches the theme_map in proxmoxlib.js so the themes appear in the native Color Theme selector.
- Index template: injects
<script> / <link> tags into the product index template for the JS patches, the optional default theme and custom font, and (PDM) theme links. Those two settings live under /etc/proxmorph/.
- Persistence: installs an APT hook at
/etc/apt/apt.conf.d/99proxmorph that runs /opt/proxmorph/post-update.sh to re-apply the patches after a Proxmox update. The hook re-patches from the local /opt/proxmorph copy only; it downloads nothing.
- Sensors (PVE, optional): if you enable sensor display, edits
Nodes.pm to expose lm-sensors data.
Originals are backed up to /root/.proxmorph-backup before any file is modified. ./install.sh uninstall restores them and removes the hook.
🛠️ Creating Themes
- Copy an existing theme from
themes/
- Rename to
theme-yourname.css
- Edit the first line:
/*!Your Theme Name*/
- Modify CSS styles
- Run
./install.sh install
Theme files must start with /*!Display Name*/ - this sets the name in Proxmox’s dropdown.
Generated themes
The UniFi OLED themes are not edited by hand. They are derived from the UniFi
bases by tools/gen-oled.sh, which applies a per-product substitution table
(tools/oled-palette-pve.tsv, tools/oled-palette-pdm.tsv).
bash tools/gen-oled.sh # rewrite the OLED stylesheets
bash tools/gen-oled.sh --check # fail if they are stale
bash test/oled_sync.test.sh # same check, plus regression guards
After changing themes/theme-unifi.css or themes/pdm/theme-unifi.css, re-run the
generator and commit the result. PVE/PBS and PDM need separate tables because PDM
stores its palette in rgb() while PVE/PBS uses hex.
❓ Troubleshooting
Themes not appearing in Color Theme dropdown
If themes don’t appear after installation:
- Clear browser cache: Press Ctrl+Shift+R (hard refresh)
- Reinstall the themes: Run
./install.sh reinstall
- Check installation status: Run
./install.sh status
- Restart proxy service: Run
systemctl restart pveproxy (PVE), systemctl restart proxmox-backup-proxy (PBS), or systemctl restart proxmox-datacenter-api (PDM)
Cloudflare Tunnel caching issues
If you access Proxmox through a Cloudflare Tunnel, themes may not load due to aggressive caching. To fix:
- Log in to Cloudflare Dashboard and select your domain
- Navigate to Caching → Cache Rules
- Click Create rule
- Set Hostname to your Proxmox subdomain (e.g.,
proxmox.example.com)
- Set Cache eligibility to Bypass cache
- Save and deploy the rule
See Issue #13 for more details. Thanks to @gioxx for the solution!
ℹ️ How It Works
PVE / PBS:
- Theme CSS files are copied to
/usr/share/javascript/proxmox-widget-toolkit/themes/
- JavaScript patches (for charts) are installed to product-specific JS directories
proxmoxlib.js is patched to register themes, and product index templates (.tpl or .hbs) are patched to load JS patches
- An apt hook automatically re-patches after product updates
- Themes appear in the native Color Theme selector
PDM:
- PDM-specific CSS override themes are installed to
/usr/share/javascript/proxmox-datacenter-manager/proxmorph-themes/
<link> tags are injected into index.hbs (disabled by default, activated by JavaScript)
- A theme selector JS patch adds ProxMorph themes to PDM’s native Theme dialog
- Selected theme is persisted in
localStorage and activated before WASM loads
📦 Supported Versions
- Proxmox VE 9.x / 8.x
- Proxmox Backup Server 4.x / 3.x
- Proxmox Datacenter Manager 1.x
📄 License
MIT License
💜 Support
If you like my themes, consider supporting this and future work, which heavily relies on coffee:
评论