Skip to content
github-actions[bot] edited this page Jul 28, 2026 · 21 revisions

Configuration

Overview

Muximux is configured via a single YAML file. By default, this is data/config.yaml (inside the data directory). The data directory defaults to data/ relative to the binary's location and can be changed with --data or MUXIMUX_DATA. You can also override the config path directly:

# Change the data directory (config will be at /opt/muximux/data/config.yaml)
muximux --data /opt/muximux/data

# Or override the config path explicitly
muximux --config /path/to/config.yaml

Complete Configuration Reference

# ─── Server ─────────────────────────────────────
server:
  listen: ":8080"              # Listen address (default: ":8080")
  title: "Muximux"             # Page title shown in browser tab
  log_level: info              # Log verbosity: debug, info, warn, error
  log_format: text             # Log output format: text or json
  proxy_timeout: 30s           # Global timeout for proxied requests
  base_path: ""                # Subpath for reverse proxy (e.g. "/muximux")

  # Optional: TLS / HTTPS
  tls:
    domain: ""                 # Auto-HTTPS domain (requires email)
    email: ""                  # Let's Encrypt registration email
    cert: ""                   # Path to TLS certificate PEM
    key: ""                    # Path to TLS private key PEM

  # Replaced by `gateway_sites:` below. If you're upgrading from
  # 3.0.x and still have this set, Muximux converts it to
  # `gateway_sites:` on first boot and saves backups of both the
  # original `config.yaml` and your Caddyfile alongside them.
  gateway: ""                  # legacy

  # Optional: Override the bind address for the embedded Caddy that
  # serves gateway sites. Useful when (a) you don't want to grant
  # CAP_NET_BIND_SERVICE / run as root, or (b) an upstream proxy
  # terminates TLS and you want Caddy on a high port behind it.
  # When set, gateway sites are emitted with http://<domain>:<port>
  # and auto-https is disabled. Empty = legacy behaviour (:80/:443).
  gateway_listen: ""           # e.g. ":8443"

  # Optional: cookie scope for cross-subdomain session sharing.
  # Required when any entry in gateway_sites has require_auth=true,
  # otherwise the session cookie won't reach the gated subdomain.
  # Leading dot is optional (browsers normalise).
  session_cookie_domain: ""    # e.g. ".example.com"

  # Optional: declarative gateway sites served by the embedded Caddy.
  # See the Gateway Examples and Gateway Auth Gate wiki pages for the
  # full reference. Each entry can optionally gate access behind the
  # Muximux session via require_auth + min_role + allowed_groups.
  gateway_sites:
    - domain: sonarr.example.com         # required
      backend_url: http://192.168.1.5:8989  # required
      tls: auto                          # auto | none | custom
      tls_cert: ""                       # required when tls=custom
      tls_key: ""                        # required when tls=custom
      streaming: false                   # disable Caddy response buffering for live data
      strip_frame_blockers: true         # strip X-Frame-Options for iframe embedding
      forwarded_headers: true            # forward X-Forwarded-Proto/Host/Real-IP
      backend_skip_tls_verify: false     # skip verifying a self-signed HTTPS backend (Proxmox); https backends only
      proxy_headers: {}                  # extra headers injected on upstream requests
      # Optional: also surface this site in the dashboard menu
      app_name: ""                       # link to an existing app by name
      # Gateway auth gate (3.1.0+) -- gate this subdomain behind Muximux login
      require_auth: false                # 302 anonymous visitors to /login first
      min_role: ""                       # "user" / "power-user" / "admin"; empty = any signed-in user
      allowed_groups: []                 # case-insensitive; admins bypass
      # Auto-populated by Docker discovery on import; do not hand-edit.
      # Presence of docker_key locks backend_url to the refresh poller.
      docker_key: ""
      docker_endpoint: ""
      docker_strategy: ""

# ─── Authentication ─────────────────────────────
auth:
  method: none                 # none, builtin, forward_auth, oidc
  setup_complete: false        # Set automatically after onboarding wizard completes

  session_max_age: 24h         # Session duration (default: 24h)
  secure_cookies: false        # Require HTTPS for session cookies
  api_key_hash: ""             # Optional bcrypt hash of API key for X-Api-Key auth

  # Builtin auth users
  users:
    - username: ""
      password_hash: ""        # bcrypt hash (see Authentication page)
      role: admin              # admin, power-user, or user
      email: ""                # Optional
      display_name: ""         # Optional

  # Forward auth settings
  trusted_proxies: []          # CIDR ranges, e.g., ["192.168.0.0/16"]
  headers:
    user: Remote-User
    email: Remote-Email
    groups: Remote-Groups
    name: Remote-Name          # Note: key is "name" not "display_name"
  logout_url: ""               # Auth provider logout URL (e.g., https://auth.example.com/logout)

  # OIDC settings
  oidc:
    enabled: false
    issuer_url: ""
    client_id: ""
    client_secret: ""          # Supports ${ENV_VAR} syntax
    redirect_url: ""           # Must match provider callback URL
    scopes: [openid, profile, email]
    username_claim: preferred_username
    email_claim: email
    groups_claim: groups
    display_name_claim: name
    admin_groups: []           # Groups that grant admin role

# ─── Theme ─────────────────────────────────────
theme:
  family: default              # Theme family: default, nord, dracula, etc.
  variant: system              # dark, light, system (follow OS preference)

# ─── Navigation ─────────────────────────────────
navigation:
  position: top                # top, left, right, bottom, floating
  width: 220px                 # Sidebar width
  auto_hide: false
  auto_hide_delay: 0.5s
  show_on_hover: true
  show_labels: true
  show_logo: true
  show_app_colors: true
  show_icon_background: false
  show_splash_on_startup: false
  show_shadow: true
  icon_scale: 1.0              # Icon zoom multiplier
  bar_style: grouped           # grouped or flat (top/bottom bars only)
  floating_position: bottom-right  # bottom-right, bottom-left, top-right, top-left
  hide_sidebar_footer: false   # Hide the footer section in sidebars
  max_open_tabs: 0             # Max app tabs kept alive in memory (0 = unlimited)

# ─── Icons ──────────────────────────────────────
icons:
  dashboard_icons:
    cache_dir: icons/dashboard   # Where fetched dashboard icons are cached
    cache_ttl: 7d                # How long a cached icon is reused before refetch

# ─── Health Monitoring ──────────────────────────
health:
  enabled: true
  interval: 30s
  timeout: 5s

# ─── Docker Discovery (optional, opt-in) ───────
# Connect to a Docker daemon to discover running
# containers and keep their URLs current. See the
# Docker Discovery wiki page for the full guide.
discovery:
  docker:
    enabled: false                               # opt-in; requires socket access
    endpoint: unix:///var/run/docker.sock        # or tcp://host:2376
    network_strategy: container_ip               # container_ip | container_dns | host_port | host_docker_internal
    network_filter: ""                           # scope scans to one docker network when set
    host_ip: ""                                  # required by host_port strategy
    refresh_interval: 60s                        # poller cadence
    auto_import: off                             # off (default) | add | update | sync; auto-import muximux.*-labeled containers
    lifecycle_enabled: false                     # allow start/stop/restart of tracked containers (requires :rw socket mount)
    lifecycle_min_role: admin                    # min role for lifecycle controls
    lifecycle_allowed_groups: []                 # additionally require group membership
    health_badge_placement: overview             # overview | overview_and_nav | off
    tls:                                         # only needed for tcp:// with mTLS
      enabled: false
      ca_cert: ""                                # CA bundle that signed the daemon cert
      client_cert: ""                            # client certificate (PEM)
      client_key: ""                             # client key (PEM, chmod 600)

# ─── Keyboard Shortcuts ────────────────────────
keybindings:
  bindings: {}                 # Custom overrides only; defaults managed client-side

# ─── Groups ─────────────────────────────────────
groups:
  - name: Media
    icon:
      type: lucide
      name: play
    color: "#e5a00d"
    order: 1
    expanded: true

# ─── Apps ───────────────────────────────────────
apps:
  - name: Plex
    url: http://plex:32400
    # health_url: http://plex:32400/web  # Optional custom health endpoint
    icon:
      type: dashboard
      name: plex
      # variant: light         # Icon variant (dashboard icons only)
      # file: healarr          # Filename in data/icons/ (type: custom only)
      # url: https://example.com/icon.png  # Remote image URL (type: url only)
      # color: "#ff0000"       # Tint color (Lucide only)
      # background: "#1a1a2e"  # Icon background override
      # invert: false          # Invert icon colors (dark ↔ light)
    color: "#e5a00d"
    group: Media
    order: 1
    enabled: true
    default: true
    open_mode: iframe          # iframe, new_tab, new_window, redirect, http_action
    proxy: false
    proxy_skip_tls_verify: true  # Skip TLS certificate verification (default: true)
    proxy_headers:               # Custom headers sent to the backend
      X-Custom-Header: value
    scale: 1.0
    health_check: true           # Opt-in: set true to enable health monitoring for this app
    shortcut: null               # Assign a number key (1-9) for quick switching
    min_role: ""                 # Minimum role to see this app (user, power-user, admin)
    force_icon_background: false # Show icon background even when global setting is off
    auth_bypass: []
    access:
      roles: []
      users: []

Command Line Options

muximux [flags]
  --data PATH      Base data directory (default: data/ beside binary, env: MUXIMUX_DATA)
  --config PATH    Override config file path (default: <data>/config.yaml, env: MUXIMUX_CONFIG)
  --listen ADDR    Override listen address (env: MUXIMUX_LISTEN)
  --base-path PATH Subpath for reverse proxy (e.g. /muximux, env: MUXIMUX_BASE_PATH)
  --version        Show version and exit

Precedence: CLI flag > environment variable > config file value > default.

Environment Variable Expansion

Use ${VARIABLE_NAME} in any string value to reference environment variables. This is useful for keeping secrets out of config files:

auth:
  oidc:
    client_secret: ${OIDC_CLIENT_SECRET}
  api_key_hash: ${MUXIMUX_API_KEY_HASH}

apps:
  - name: Plex
    url: ${PLEX_URL}

If the referenced environment variable is not set, the ${VAR} reference is left as-is (the literal string is preserved). This avoids silently deleting values when an env var is missing.

Direct Override Environment Variables

These override the corresponding config file values without needing ${VAR} syntax in config.yaml:

Variable Description Default
MUXIMUX_DATA Base data directory data/ beside binary
MUXIMUX_CONFIG Override config file path <data>/config.yaml
MUXIMUX_LISTEN Listen address (e.g., :9090) From config file
MUXIMUX_BASE_PATH Subpath for reverse proxy (e.g., /muximux) Empty (root)
MUXIMUX_LOG_LEVEL Log verbosity (debug, info, warn, error) From config file
MUXIMUX_LOG_FORMAT Log format (text or json) text

Validation Rules

Muximux validates the configuration on startup and will refuse to start if the configuration is invalid. The following rules are enforced:

  • If tls.domain is set, tls.email is required (for Let's Encrypt registration).
  • tls.cert and tls.key must both be set or both empty. You cannot provide only one.
  • tls.domain and tls.cert are mutually exclusive. Use either auto-HTTPS or manual certificates, not both.
  • Legacy gateway: (Caddyfile path) configs from 3.0.x are auto-migrated to gateway_sites: on first boot under 3.1.0 (clean conversions only; lossy ones surface a hard error pointing at muximux migrate-gateway).
  • If any gateway_sites[] entry has require_auth: true, server.session_cookie_domain is required and every gated site must be a subdomain of it (real host-suffix check: evilexample.com is not a subdomain of example.com).
  • gateway_sites[].min_role must be one of user, power-user, admin when set (empty means "any authenticated user").
  • server.gateway_listen must be a valid bind address (e.g., :8443 or 127.0.0.1:8443).

Live Configuration

Most settings can be changed through the Settings panel while Muximux is running. Changes are saved to data/config.yaml immediately and take effect without restarting.

The following settings require a restart to take effect:

  • server.listen (listen address/port)
  • server.base_path (subpath prefix)
  • server.tls.* (all TLS settings)
  • server.gateway_listen (overrides the bind port for the embedded Caddy)
  • server.session_cookie_domain (cookie scope; takes effect on next login)
  • server.gateway_sites: schema changes (the auth gate; backend swaps and TLS-mode flips reload Caddy in place)

Everything else -- navigation, themes, apps, groups, icons, keybindings, health monitoring, log level, log format -- is applied immediately.

Config Export and Import

You can export your configuration as a downloadable YAML file and import it on another instance:

  • Export strips sensitive data (password hashes, OIDC secrets, API key hashes) before download.
  • Import parses the uploaded YAML, validates it, and shows a preview so you can review before applying.

This is available in the Settings panel under the General tab, or via the API (see API Reference).

Config API

The configuration can also be read and updated via the API:

  • GET /api/config -- Retrieve the current configuration (any authenticated user).
  • PUT /api/config -- Update the full configuration (admin role required).
  • GET /api/appearance -- Read-only snapshot of language, theme id, and theme colors, for embedded apps that want to sync their own appearance (see Apps > Appearance API).

See the API Reference for details.

Clone this wiki locally