Light/dark theme for pfSense that follows your operating system's appearance setting — no manual theme switching. Ships as a pfSense package and also patches the login page, which pfSense always renders in light mode.
| Light | Dark |
|---|---|
![]() |
![]() |
Same theme, no settings touched — it follows the prefers-color-scheme of
the machine you browse from.
Full write-up on the blog: https://tmiland.com/pfsense-theme-lightdark/
pfSense-light-dark.css— a theme you select per user under System → User Manager → (user) → Settings. It loads the standardpfSense.cssby default and switches topfSense-dark.cssbehind@media (prefers-color-scheme: dark), so the webConfigurator follows the system theme of the machine you browse from. Light desktop → light UI, dark desktop → dark UI, switching live without reloading settings.- Dark-mode fixes missing from upstream
pfSense-dark.css:.text-danger/.text-success/.text-warninglegibility on dark backgrounds (values follow upstreampfSense-dark-BETA.css)pre/code/kbdno longer render with light Bootstrap backgroundscolor-scheme: darkso native widgets (dropdowns, scrollbars, checkboxes) render dark too
- Dark login page — the login page (
/etc/inc/authgui.inc) hardcodeslogin.cssand never loads the per-user theme. The package installs a patchedlogin.csswith a matchingprefers-color-scheme: darkblock. - Usability tweaks (both schemes):
- sticky table headers — column titles stay visible while scrolling long
unwrapped tables (headers yield to
.table-responsivewrappers, where sticking against the page would be broken/incorrect anyway) - monospace stack for
pre/code/kbd/samp - the light/dark system switch itself, plus the denser table/menu spacing carried over from the upstream experimental stylesheets
- sticky table headers — column titles stay visible while scrolling long
unwrapped tables (headers yield to
Third-party packages install from the CLI (the GUI Available Packages tab only lists the official repo):
cat > /usr/local/etc/pkg/repos/pfsense-theme-lightdark.conf <<'EOF'
pfsense-theme-lightdark: {
url: "https://tmiland-lab.github.io/pfsense-theme-lightdark/repo",
mirror_type: "NONE",
signature_type: "none",
enabled: yes
}
EOF
pkg update
pkg install -y -r pfsense-theme-lightdark pfSense-theme-lightdarkThen select pfSense-light-dark (System → User Manager → user → Settings → Theme). That's it — the login page is patched automatically.
Survives pfSense upgrades: the package is reinstalled by pfSense after an upgrade and re-applies both the theme file and the login patch.
The login patch only applies when the on-disk login.css matches the known
stock content (or is already patched). If a pfSense release changes
login.css, the patcher refuses to touch it and says so — copy the new
stock file into pkg/files/.../login.css.stock, re-apply the dark block,
and ship a new package version.
pkg remove -r pfsense-theme-lightdark pfSense-theme-lightdarkThe pre-deinstall script restores the stock login.css; switch any user
back to pfSense.css / pfSense-dark.css afterwards.
| Path | Purpose |
|---|---|
/usr/local/www/css/pfSense-light-dark.css |
the theme (select it per user) |
/usr/local/share/pfsense_theme_lightdark/login.css |
patched login stylesheet |
/usr/local/share/pfsense_theme_lightdark/login.css.stock |
stock copy for safe restore |
# on a pfSense host (or matching FreeBSD box):
sh pkg/build.shOutput: /tmp/pfsense-theme-lightdark-repo-out/. The pkg is published to the
gh-pages branch (repo/ flat layout, pkg repo .).
- Netgate / pfSense —
pfSense.css,pfSense-dark.cssand the experimental BETA stylesheets this theme builds on (Apache-2.0) - Built with opencode
Apache-2.0 — see LICENSE. Derived from pfSense's Apache-2.0 stylesheets.
Built with opencode — the open-source AI coding agent for the terminal. Grab your own at opencode.ai/go.

