github mescon/Muximux v3.6.0

4 hours ago

Docker discovery becomes predictable: auto-import only touches containers
that carry a muximux.* label, it can never write an app without a URL or
leave a config that refuses to start, Swarm and Compose apps keep one
identity across redeploys, and labels you set (name, icon, group, order,
health check, group style) stay applied while an app is tracked. Settings
now merges onto the live config instead of overwriting it, every open
browser follows config changes, and every bundled theme meets WCAG AA
contrast, with focus kept inside dialogs and much better keyboard support.

Upgrade notes:

  • Auto-import imports only labelled containers. An auto-imported app whose
    container has no labels is detached from auto-import (the app is kept) on
    the first refresh under update/sync.
  • Swarm and Compose apps get new tracking keys (swarm:<service>,
    compose:<project>:<service>), migrated in place on the first refresh.
  • Labels that are set now re-sync onto apps you imported by hand, so an
    edit to those fields in Settings is reset while the label is set; remove
    the label or detach the app to keep your edit. (#500)
  • Restore refuses legacy server.gateway backups and explains how to
    convert them; a saved theme cannot use a bundled theme's name;
    lifecycle_allowed_groups accepts any group names.
  • API scripts that PUT /api/config without base keep the old two-way
    behaviour; the gateway site PUT accepts an optional base_backend_url;
    GET /api/discovery/docker/config is new.

Added

  • Explicit opt-in for auto-import. discovery.docker.require_explicit_enable
    and MUXIMUX_DISCOVERY_REQUIRE_EXPLICIT_ENABLE limit auto-import to
    containers labelled muximux.app.enabled=true. The environment override
    stays in memory and shows as locked in Settings. (#496)
  • muximux.app.health_check label enables or disables health monitoring
    for an imported app; it is re-synced like the other label fields and shown
    locked in the app's settings. (#497)
  • Docker Swarm. Services are tracked as swarm:<service> (and Compose
    services as compose:<project>:<service>), ingress-published ports and
    deploy.labels are read from the service, container_dns uses the
    service name, and one app is imported per service. Existing name: keys
    are migrated on the first refresh. A socket proxy must allow /services
    (SERVICES=1). (#499)
  • The Discover modal says why a container is not auto-imported, and
    Settings -> Discovery lists invalid auto-imported entries that were not
    loaded and tracked containers that are missing. (#499)
  • GET /api/discovery/docker/config returns the stored discovery
    config, and PUT merges onto it. (#494)
  • base on PUT /api/config enables a three-way merge, and apps and
    groups accept original_name; the admin config response lists
    env_overrides. A save that would create two apps or groups with the same
    name is refused with 409 and Settings blocks Save until one is renamed.
    (#494)
  • base_backend_url on the gateway site PUT keeps Docker tracking when
    the backend address was refreshed while the site was being edited. (#494)
  • Docker group labels. muximux.group.icon, muximux.group.color and
    muximux.group.order set the look and order of a group Docker discovery
    created; the container with the lowest tracking key wins a conflict, and
    editing the group in Settings hands it back. (#500)
  • The Discover modal marks containers that are already tracked with a
    "Tracked" chip naming the app, gateway site or quarantined entry, and warns
    when an import name is already taken. (#500)

Changed

  • Auto-import considers only labelled containers. A container needs at
    least one muximux.* label; muximux.app.enabled=false opts out (under
    sync the app is removed). Upgrade note: an auto-imported app whose
    container has no labels is detached from auto-import on the first refresh
    under update/sync: it stays, its URL keeps refreshing, and sync no
    longer removes it. (#499)
  • Tracking keys for Swarm and Compose containers change to
    swarm:<service> and compose:<project>:<service>; existing name: keys
    are migrated automatically on the first refresh. (#499)
  • Swarm apps take their name from the service. Under update/sync an
    auto-imported Swarm app without a muximux.app.name label is re-synced
    from the task name to the service name on the first refresh, which can
    change its slug and its /proxy/<slug>/ path. (#499)
  • Images whose last path segment is generic (server, app, web, api
    and similar) no longer match a catalog entry by that segment. (#499)
  • Live updates. Every open browser receives a config_updated event
    after any config change and refetches the config (the page reloads only
    when the language changed); an open Settings dialog keeps unsaved edits
    and rebases them onto the new state. (#494)
  • Settings closes only after a successful save. On failure it stays open
    with the server's message; every close path asks about unsaved changes and
    is blocked while a save runs. Discard also reverts keybinding and theme
    previews. (#494)
  • Docker tracking is server-owned on every endpoint. POST /api/apps
    and POST /api/gateway/sites ignore docker_* fields in the payload, as
    the PUTs already do; only discovery's import attaches an app or site to a
    container. (#494)
  • lifecycle_allowed_groups are user and identity-provider group names;
    renaming or deleting a dashboard group no longer touches them. (#494)
  • Restore uses the startup load path. ${VAR} expansion, defaults and
    validation apply, and users, auth, OIDC, discovery and proxy routes reload
    at once. Listen address, TLS, base-path routing and session cookie
    settings still need a restart. A backup with the legacy server.gateway
    setting is refused with 400. (#494)
  • Status colours come from theme tokens. Warnings, errors, success and
    info notices, pills and the danger button read --success-*,
    --warning-*, --danger-*, --info-*, --accent-text,
    --accent-on-primary and --danger-solid instead of fixed Tailwind
    shades, so themes can set them; omitted tokens fall back to the defaults.
    The theme editor writes the text colour for accent fills when a custom
    theme is saved (pure white or black, whichever reads better on the
    accent). Visible shifts that come with this: status text, tints and
    borders move to one shade per status; the Login and onboarding primary
    buttons use the theme accent instead of a fixed brand shade; buttons
    share the standard button style; accent-coloured text and links are one
    shade off in some themes and links underline on hover; focus is a uniform
    2px outline; the unknown health dot is a hollow ring and the tooltip's
    uptime badge uses the status badge colours.
  • Theme colours adjusted for contrast. Every bundled theme now meets
    WCAG 2.1 AA for text (4.5:1) and for control borders and focus outlines
    (3:1), light and dark. Muted and secondary text moved a step towards the
    foreground; the elevated and overlay surfaces of Catppuccin, Cineplex Dark,
    Gruvbox, Nord and Solarized Dark are a step darker; buttons use dark text
    on most accents; accent-coloured text moved a step away from the
    background so accent badges reach 4.5:1 on their tint. Accent and status
    base colours are unchanged. Custom themes that omit the new tokens get
    values derived from their own colours, switched by @theme-is-dark.
  • Form controls have a visible boundary. Inputs, selects, textareas,
    checkboxes and the locale picker use a new --border-input token that
    meets 3:1 on every surface; card and divider borders are unchanged.
  • Toasts follow the theme instead of always being dark.
  • Primary buttons keep their colour on hover. The primary button and
    the floating navigation button signal hover with their glow and shadow
    instead of switching to the secondary accent, which fell below AA in
    several light themes. A custom theme that omits --accent-on-primary
    gets a readable text colour derived from its own accent.
  • Linux in the update instructions shows Tux in his own colours.

Fixed

  • Label re-sync for tracked apps. muximux.app.name, icon, group and
    order are re-synced onto every tracked app that auto-import does not own
    (apps imported by hand), in every mode including off, instead of only on
    first import. Auto-imported apps follow auto_import update/sync and
    are left alone under off and add. (#500)
  • Auto-created groups appear in the sidebar. A group an import needs is
    created in the same save, and an app whose group is missing is listed
    under Ungrouped instead of disappearing. (#500)
  • network_filter is applied consistently. The refresh tick lists
    containers through the same filtered path as the scan, so a multi-network
    container gets its URL from the filtered network, and Swarm services are
    read once per tick. (#500)
  • Docker auto-import can no longer break the config. A container without
    a usable port is skipped (and shown as not importable) instead of written
    without a URL; an update never blanks an existing URL; the poller validates
    before saving. An invalid auto-imported entry already in config.yaml is
    quarantined at startup with a warning instead of stopping Muximux, is kept
    in the file, and no longer blocks saving from Settings. Swarm redeploys and
    scaled Compose services no longer duplicate or re-create apps. Names that
    differ only by case or punctuation are deduplicated. "Tracked docker
    container not found" is logged once per outage instead of every refresh.
    sync removes only auto-imported apps, and only after the container has
    been absent for three consecutive scans. (#499)
  • Custom apps added in the onboarding wizard appear on the dashboard.
    An app added through the wizard's custom app form was saved in an "Other"
    group that was never created, so it stayed hidden until the group was
    added by hand. Finishing the wizard now also creates any group an app
    refers to.
  • Settings keeps what you changed and nothing else. Saving from Settings
    merges your edits onto the current server config instead of replacing it,
    so apps added by Docker auto-import or an import, URLs refreshed by the
    poller, a cookie scope set in the Gateway tab, and edits from another tab
    are no longer reverted or deleted. Renaming an app keeps its access rules,
    Docker tracking and forwarded-headers setting. Imports no longer show a
    false "Unsaved changes" or an empty Apps list. (#494)
  • Discovery tab shows and keeps its stored values. Host IP, network
    filter, refresh interval, auto-import mode and badge placement are read
    from the config and preserved on save, including fields the tab does not
    show (auto_import, TLS paths); npipe:// endpoints are accepted on
    Windows and an enabled config with an empty endpoint gets the platform
    default. (#494)
  • Environment overrides stay in the environment. MUXIMUX_LOG_LEVEL,
    MUXIMUX_LOG_FORMAT, --listen/MUXIMUX_LISTEN,
    --base-path/MUXIMUX_BASE_PATH and MUXIMUX_DISCOVERY_AUTO_IMPORT are
    no longer written into config.yaml by a save; Settings shows them as
    locked. (#494)
  • Forward-auth saves keep forward_auth_admin_groups; a failed user change
    no longer lingers in memory. (#494)
  • Gateway site saves are validated like startup, so a gated site without a
    cookie scope can no longer break the next restart; the forward-headers
    checkbox shows the real value; sites imported from the Gateway tab appear
    at once. (#494)
  • The onboarding wizard opens only on a new install and never for a
    non-admin; finishing it keeps existing groups, navigation, theme and
    discovery settings; a retry after a failed save no longer hits 409. (#494)
  • Custom theme delete works again; a theme cannot shadow a bundled one;
    theme editor previews are cleaned up. (#494)
  • Health settings reach the client with snake_case keys and polling follows
    them right after a save; floating navigation position from the config is
    honoured; Docker state loads under a base path; the http_action method no
    longer flips to GET when the form opens; proxy_timeout can be cleared;
    replacing a custom icon in another format shows at once. (#494)
  • Restoring a backup with the legacy server.gateway setting (string or
    map) explains how to convert it instead of reporting invalid YAML. (#494)
  • Accessibility groundwork. Every focusable element shows the same
    visible focus outline, and a field with an error keeps its danger border
    while focused. The health indicator has a name, a distinct shape per
    status and a tooltip that opens with the keyboard ("Check now" in it is
    still mouse-only). Errors are announced as alerts and confirmations as
    status messages, the onboarding wizard announces step changes, the log
    level filters report on or off, and form controls and icon-only buttons
    have names, including per-row actions. Transitions, spinners and pulses
    calm down when the operating system asks for reduced motion.
  • Focus stays inside dialogs. Settings and every other dialog trap Tab
    and Shift+Tab, make the page behind them inert and return focus to the
    control that opened them; pickers opened over a dialog keep their own
    focus, and Escape closes each sub-dialog. Theme and onboarding cards no
    longer nest controls inside each other, links in running text are
    underlined, and the log view scrolls with the keyboard.
  • Status text is legible on light themes. "Unsaved changes", failed
    saves (previously pink on pink), warnings, success notices, pills, the
    Logs level colours and the keyboard-conflict notice use per-theme colours
    with AA contrast; disabled-looking grey is no longer used for real
    content or placeholders.

Security

  • golang.org/x/net v0.60.0 -- fixes GO-2026-6603, GO-2026-6610,
    GO-2026-6611, GO-2026-6612 and GO-2026-6617 in the HTTP/2 code reached by
    the reverse proxy.
  • Restore drops all sessions and refuses racing logins. Restoring a
    backup reloads users and auth immediately, ends every session, and refuses
    a login that was in progress during the restore, so credentials from before
    the restore cannot survive it. An unreachable OIDC provider in a backup is
    switched off instead of kept. (#494)
  • Admin auth endpoints wait for setup. Before setup completes, only auth
    status, setup, login, logout, me and the OIDC sign-in routes answer
    without the setup token; creating users or an API key, changing the auth
    method and the OIDC settings return 503 setup_required instead of
    running as the pre-setup admin. (#494)
  • Setup token no longer readable from the log viewer. Before setup, an
    anonymous caller could read the setup token from GET /api/logs/recent
    and use it to claim the instance. The token is now printed only to the
    console (container/console output) and is never written to the log
    buffer or muximux.log; the log viewer, /api/system/updates and
    /api/system/info, the /ws live stream and the /proxy/ app routes
    return 503 setup_required until setup completes -- only the theme list,
    icon routes and static assets the wizard uses stay open. A setup
    token found in a log file written by an earlier release is replaced with
    a new one at startup, and newly created log files are mode 0600. (#494)

Don't miss a new Muximux release

NewReleases is sending notifications on new releases.