mescon/Muximux 是一个托管在 GitHub 上的开源项目,主要使用 Go 编写,采用 GNU General Public License v2.0 许可证,目前获得 1.2k 个 Star、87 次 Fork。
仓库全名
mescon/Muximux
README 摘要
Muximux A self-hosted homelab dashboard with an optional built-in embedding proxy that makes stubborn apps work in iframes. One binary, one port, one YAML config file. AI Disclosure: Muximux is developed with significant AI assistance (Claude Code). All code is reviewed, tested, and approved by the maintainer before shipping. See Development for details. The dashboard, Plex running inside a pane (it refuses to be…
A self-hosted homelab dashboard with an optional built-in embedding proxy that makes stubborn apps work in iframes.
One binary, one port, one YAML config file.
AI Disclosure: Muximux is developed with significant AI assistance (Claude Code). All code is reviewed, tested, and approved by the maintainer before shipping. See Development for details.
The dashboard, Plex running inside a pane (it refuses to be framed without the proxy), split view, and themes.
There’s a good chance you already have a homelab dashboard. Homepage, Homarr, Organizr, and Dashy are all good at what they do. If one of them already fits how you work, you probably don’t need to read further.
Muximux is for people who spend the day working inside their self-hosted apps. Click Sonarr and it opens inside the dashboard; click Plex and so does Plex. You stay in Muximux the whole time instead of juggling browser tabs.
Most self-hosted apps set X-Frame-Options: DENY and refuse to load in an iframe, which makes embedding them hard. Muximux has a built-in embedding proxy that strips those headers, rewrites paths in HTML/CSS/JS, and patches fetch() and XMLHttpRequest at runtime. Even heavy single-page apps then work the way they do when you open them directly. No other dashboard does this, and it’s the reason Muximux exists. Passkeys are the exception: a proxied app runs on Muximux’s address, so a passkey registered for the app’s own hostname works only if the app also accepts Muximux’s address for it.
There are things Muximux deliberately doesn’t do. It doesn’t pull live widgets from Sonarr or qBittorrent (Homepage is lovely at that). It doesn’t have a freeform grid editor where you arrange resizable widgets on a canvas (Homarr is built around that). It doesn’t have Dashy’s range of built-in monitoring widgets. What it does is run your apps side by side in a single tab, and it tries to be pleasant enough that you can leave that tab open all day.
All configuration is in one YAML file. Muximux needs no database and no external dependencies. The application ships as a single binary with the frontend embedded. You can change every setting in the built-in GUI, so you never have to edit the YAML directly.
The exception is a setting that comes from an environment variable. Settings shows that setting as locked. To change it, change the variable and restart Muximux (see environment overrides).
To back up or move your setup, copy config.yaml. If you added your own icons or themes, also copy data/icons/custom/ and data/themes/. Also bring the environment variables and secret files that your deployment sets. If the new host does not get an auth override that the old host had, it can start with a different auth method, or with no auth.
Live service widgets (torrent counts, episode lists, etc.)
❌
✅ (100+)
✅
Partial
✅ (50+)
Drag-and-drop visual editor
✅ apps + groups
❌
✅
Partial
✅
Real-time health checks
✅ (WebSocket)
✅
✅
✅
✅
Built-in users and roles
✅
❌ (external auth)
✅
✅
Simple
Forward-auth / OIDC / SSO
✅
Via external proxy
✅ (OIDC + LDAP)
✅ (Plex / Emby / LDAP)
✅ (Keycloak)
Auto-HTTPS via Let’s Encrypt
✅ (embedded Caddy)
❌
❌
❌
❌
Can front other services on their own subdomains (embedded Caddy)
✅
❌
❌
❌
❌
Start / stop / restart Docker containers from the dashboard
✅
❌
✅
❌
❌
Keeps app URLs working as container IPs / names change
✅
❌
❌
❌
❌
Config
YAML + Docker labels (no DB)
YAML + Docker labels
Database
Database
YAML / UI
Deployment
Docker / single static binary
Docker / K8s / binary
Docker
Docker / PHP
Docker / Node.js
If the rows near the top describe what you want, keep reading.
Why v3?
Muximux v3 is a ground-up rewrite. The original Muximux was a simple bookmark portal written in PHP. v3 has a new stack and does a lot more:
A Go backend with the frontend embedded in the binary. No PHP, no web server, no runtime dependencies.
A built-in embedding proxy that rewrites HTML, CSS, JS, and headers so apps work inside iframes. It is separate from the optional gateway below.
Real-time health monitoring over WebSocket, so you see which apps are up or down without refreshing.
Built-in authentication: username/password, forward auth (Authelia/Authentik), or OIDC, configurable in Settings.
Optional TLS and gateway. An embedded Caddy instance can handle HTTPS certificates and serve other sites alongside Muximux.
A setup wizard that walks you through security setup and adding your first apps.
Split view, with two apps side by side or stacked and a draggable divider between them.
1,600+ icons from Lucide, plus thousands of service-specific icons from Dashboard Icons.
Built-in light and dark modes, plus custom themes via CSS.
How You Can Use It
Pick the setup that matches yours.
Dashboard behind your existing proxy
You already have Traefik, nginx, or Caddy for TLS and auth. Run Muximux behind it with auth: none, and let your proxy handle TLS and auth. Muximux serves on a single port, and your proxy forwards to it. The proxy must forward WebSocket upgrades, because Muximux’s live health updates and many embedded apps use them (see the Deployment Guide). This is the simplest setup.
Dashboard with the embedding proxy
This is the same setup, but some of your apps refuse to load in iframes. Set proxy: true on those apps. Muximux’s embedding proxy then forwards them through /proxy/{slug}/. It strips iframe-blocking headers and rewrites paths, so the apps render inside the dashboard. The embedding proxy runs inside the Go server. It works in every deployment mode with no extra configuration, and no other dashboard has one.
The embedding proxy and the gateway do different jobs. The embedding proxy makes an app render inside the dashboard, which a general-purpose proxy can’t do. The gateway below is an ordinary proxy that routes a subdomain to a backend.
Dashboard plus gateway (skip the separate proxy)
If you have no proxy and do not want to run one, Muximux’s optional gateway (an embedded Caddy) can front your other services too.
To get automatic HTTPS from Let’s Encrypt, set tls.domain and tls.email.
To serve other services on their own subdomains, declare them under gateway_sites: in config.yaml (or in Settings -> Gateway). You can add auth to each site if you want.
The same binary then handles TLS certificates, HTTP-to-HTTPS redirects, and routing.
The gateway is kept simple on purpose, for homelab-sized setups that would otherwise need a separate proxy. If you need wildcard certificates, complex routing rules, load balancing, or access-control lists, keep a dedicated proxy (Nginx Proxy Manager, Traefik, or Caddy on its own) and run Muximux behind it, as in the first option above.
See the Deployment Guide for Docker Compose examples for each setup.
Open http://localhost:8080. An onboarding wizard guides you through security and initial setup.
The wizard asks for a one-time setup token. Muximux generates this token on first boot, so nobody who reaches the port before you can claim the instance. The command above runs detached. Read the token from the container output or from the mounted data directory:
docker logs muximux | grep token
# or
cat data/.setup-token
By default, Muximux uses data/ beside the binary as its data directory. This directory holds config, themes, and icons. To use a different directory, set --data or the MUXIMUX_DATA environment variable.
Release binaries and images carry signed build provenance and ship with an SBOM (software bill of materials, a list of what is in the build). With these, you can confirm that a download came from the workflow that claims to have built it. See Verifying a Download.
See docker-compose.yml for a full example with environment variables, health checks, and optional TLS/gateway ports.
Configuration values can reference environment variables, for example ${OIDC_CLIENT_SECRET}. To override the listen address, use the --listen flag or the MUXIMUX_LISTEN environment variable. Logging, Docker auto-import, the auth method, and every OIDC setting also have MUXIMUX_* overrides. See the environment variable reference. The data directory (where config, themes, and icons live) defaults to data/ beside the binary. To change it, use --data or MUXIMUX_DATA.
Or configure apps with Docker labels
With Docker Discovery enabled, a container can declare its own Muximux entry with labels. Without auto-import, the labels pre-fill the import modal. With discovery.docker.auto_import, the app appears with no clicks and stays in sync. Declare the app once in your compose file, and Muximux picks it up:
muximux.app.* labels cover the whole app entry (icon, group, open mode, health check, access control, and more). muximux.gateway.* labels can also publish the container on its own gateway subdomain. A background poller keeps imported URLs current when container IPs change across restarts. For the full label reference, see Docker Discovery.
If Muximux is behind your own reverse proxy, add muximux.app.url=https://sonarr.example.com. The app then opens at its public name, and health checks still go to the container.
For the full configuration reference, authentication options, TLS setup, and more, see the Wiki.
Features
Reverse Proxy
Strips iframe-blocking headers, rewrites HTML/CSS/JS paths, handles gzip, and isolates window.parent/window.top, so apps that normally refuse to be framed work in an iframe. Per-app TLS settings, custom headers, and a configurable timeout
Health Monitoring
Periodic health checks with real-time WebSocket updates and colored status indicators
Real-Time Log Viewer
In-app log viewer with level/source filtering, search, auto-scroll, pause/resume, and download. Debug level exposes detailed request tracing
Authentication
Built-in users (bcrypt), forward auth (Authelia/Authentik), or OIDC (set up in Settings), with user management and roles. The auth method and every OIDC setting can also come from MUXIMUX_* environment variables, with the client secret in a Docker secret. A fresh container can then start on single sign-on with no config file and no setup wizard
TLS / HTTPS
Automatic Let’s Encrypt certificates or manual cert/key, powered by embedded Caddy
Gateway
Reverse proxies other sites and services on your network, each on its own subdomain. Sites are declared in YAML under gateway_sites, with per-site TLS modes (automatic Let’s Encrypt, none, or custom certs), header forwarding, iframe-blocker stripping, and streaming-safe backends. Edit them visually in Settings -> Gateway or by hand. Each subdomain can optionally require the Muximux login (require_auth), so one sign-in covers your whole homelab
Docker Discovery
Connect Muximux to the Docker daemon and import running containers as apps in one click, with name, icon, and URL filled in. For each row you choose how the app is exposed: direct, through the proxy, or on its own gateway subdomain. A background poller keeps URLs current as container IPs shift across restarts. For GitOps, turn on automatic import (discovery.docker.auto_import, off by default) and Muximux picks up muximux.*-labeled containers by itself, so an app you declare in your compose file appears without any clicks. Labels you set (name, icon, group, order, health check, and the icon, colour and order of the group) stay applied while the app is tracked. Icon labels accept Dashboard Icons, Lucide icons or image URLs. Docker Swarm services and Compose projects keep one app across redeploys
Container Controls
Start, stop, and restart Docker-discovered containers from the dashboard, with a status dot on each app card that stays quiet until a container is stopped, unhealthy, or restarting. Opt-in: it needs a read-write socket mount and role/group permissions. Every action is audit-logged
HTTP Actions
Turn an app into a button that sends an HTTP request (any method, custom headers) through a server-side relay instead of opening a page. Handy for webhooks and automations, such as triggering a backup or waking a host. You can add a confirmation prompt, and every request is audit-logged
Split View
Display two apps side by side or stacked with a draggable divider, panel selector for targeting left/right or top/bottom, and URL hash routing (#app1+app2) for bookmarking layouts
Links Into Apps
A bookmark, a Homarr tile or a note can open Muximux on a given app, a split layout, or a page inside the app (#emby?path=..., #sonarr+radarr?sonarr=...&radarr=...). Apps you allow can also switch apps and open pages from their own links or a small postMessage API. Every path stays inside its target app, and both features are opt-in per app (Navigation from Embedded Apps)
Navigation
5 positions (top, left, right, bottom, floating), pinned apps as one-click buttons in the bar, draggable FAB, auto-hide, customizable width
Keybindings for switching apps, toggling navigation, and search
Accessibility
Usable from the keyboard, with a visible focus outline, focus kept inside dialogs, named controls and screen reader announcements, and reduced motion when the operating system asks for it
Themes
9 built-in theme families (Default, Nord, Dracula, Catppuccin, Solarized, Tokyo Night, Gruvbox, Cineplex, Rose Pine) with dark/light variants, all meeting WCAG 2.1 AA contrast, plus custom themes via CSS
Config Export/Import
Export the config as YAML with sensitive data stripped, or import a file, preview it, and apply it
Environment Variables
${VAR} expansion in config.yaml, plus MUXIMUX_* overrides for the data directory, listen address, base path, logging, Docker auto-import, the auth method and OIDC. Overrides stay in memory and never end up in config.yaml (full list)
REST API
Full CRUD for apps, groups, config, health, and auth
Single Binary
The frontend is embedded in the Go binary, so you deploy one file with no runtime dependencies
Portable
No database: one YAML config file stores everything. Every setting is editable in the GUI, saves merge onto the live config, and every open browser picks up a change at once. To back up or migrate, copy that file plus any custom icons and themes
Project Philosophy
Muximux is meant to stay a focused homelab dashboard: a single page where you open and organize your self-hosted apps. New features are judged by whether they serve that purpose, so it won’t grow into a monitoring suite or a system management tool.
Suggestions are always welcome, but not all of them will make it in. That’s on purpose: a smaller set of features that work well beats a long list.
Development
Muximux is developed using Claude Code (Opus 4.6 through 4.8, currently Claude Fable 5) with MCP servers for browser automation (Playwright), GitHub integration, and other validation tools. It’s a heavily AI-assisted workflow, but all code is reviewed, tested, and committed by the sole maintainer, @mescon. AI output is treated the same way as a pull request from a contributor: nothing ships without understanding and approval.
Every push goes through CI with 85%+ test coverage on both backend (./internal/...) and frontend (the src/lib and src/components surface; the app shell is excluded and verified by browser testing), golangci-lint, ESLint, svelte-check, CodeQL analysis, Snyk vulnerability scanning (Go, Node, Docker), govulncheck, SonarCloud quality gates, and a pre-push hook that blocks pushes below coverage thresholds. The security model is designed against OWASP ASVS Level 2.
git clone https://github.com/mescon/Muximux.git
cd Muximux
# Enable git hooks (pre-push runs tests with coverage checks)
git config core.hooksPath .githooks
# Frontend dev server (hot reload)
cd web && npm install && npm run dev &
# Backend (uses data/ beside the binary by default for config, themes, icons)
go run ./cmd/muximux
Building
# Build frontend (outputs to internal/server/dist/)
cd web && npm run build && cd ..
# Build binary (embeds frontend)
go build -tags embed_web -o muximux ./cmd/muximux
# With version info (uses latest git tag)
go build -tags embed_web -ldflags "-X main.version=$(git describe --tags --abbrev=0)" -o muximux ./cmd/muximux
评论