Deployment
May 27, 2026 · View on GitHub
Muximux supports three deployment styles. Pick the one that matches your setup.
| Style | You provide | Muximux does | Ports to expose |
|---|---|---|---|
| Behind an external proxy | Traefik / nginx / Caddy handles TLS and auth | Serves the dashboard on a single port | 8080 (internal only) |
| Standalone with built-in proxy | Direct access, optional built-in auth | Dashboard + per-app /proxy/{slug}/ for iframe embedding | 8080 |
| Full reverse proxy appliance | DNS records | TLS certificates, HTTP→HTTPS redirects, gateway for other services | 80, 443 |
The built-in per-app reverse proxy (proxy: true) works in all three styles -- it runs inside the Go server and is independent of Caddy or any external proxy.
Docker
The recommended way to run Muximux in production.
Behind an external proxy (Traefik, nginx, etc.)
# docker-compose.yml
services:
muximux:
image: ghcr.io/mescon/muximux:latest
ports:
- "8080:8080"
volumes:
- ./data:/app/data
restart: unless-stopped
Set auth.method: none or forward_auth in config.yaml and let your external proxy handle TLS and authentication.
As a full reverse proxy appliance
# docker-compose.yml
services:
muximux:
image: ghcr.io/mescon/muximux:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./data:/app/data
restart: unless-stopped
Configure tls.domain and gateway_sites in config.yaml. See TLS & HTTPS for a full walkthrough. Port 8080 does not need to be exposed -- Caddy handles all traffic on 80/443.
Note: The legacy
server.gateway:Caddyfile path was removed in 3.1.0 and replaced by the declarativeserver.gateway_sites:YAML. A 3.0.x config (and any mountedsites.Caddyfile) is auto-migrated on first boot under 3.1.0.
Volume
Mount a directory to /app/data. This stores:
config.yaml-- Configurationthemes/-- Custom themesicons/-- Icon caches and custom uploads
Health Check
The Docker image includes a built-in health check (GET /api/health every 30s).
Logging
To use JSON log format (recommended for container log drivers like Loki or ELK):
environment:
- MUXIMUX_LOG_FORMAT=json
Updating
docker compose pull
docker compose up -d
Systemd Service
For running Muximux as a native binary on Linux.
Create /etc/systemd/system/muximux.service:
[Unit]
Description=Muximux - Web Application Portal
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=muximux
Group=muximux
WorkingDirectory=/opt/muximux
ExecStart=/opt/muximux/muximux --data /opt/muximux/data
Restart=on-failure
RestartSec=5
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/muximux/data
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Setup
# Create user
sudo useradd -r -s /bin/false muximux
# Create directories
sudo mkdir -p /opt/muximux/data
sudo chown -R muximux:muximux /opt/muximux
# Copy binary
sudo cp muximux /opt/muximux/
# Create config
sudo cp config.example.yaml /opt/muximux/data/config.yaml
sudo chown muximux:muximux /opt/muximux/data/config.yaml
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable muximux
sudo systemctl start muximux
# Check status
sudo systemctl status muximux
sudo journalctl -u muximux -f
# Enable debug logging temporarily
sudo systemctl set-environment MUXIMUX_LOG_LEVEL=debug
sudo systemctl restart muximux
Behind an External Reverse Proxy
If you run Muximux behind Nginx, Traefik, or Caddy (external), you do not need Muximux's built-in TLS or gateway. Your external proxy handles TLS termination and optionally authentication. Set auth.method: none (if your proxy handles auth) or forward_auth (for Authelia/Authentik) in config.yaml.
The per-app reverse proxy (proxy: true) still works in this setup -- it runs inside the Go server and is unrelated to the external proxy.
Nginx
server {
listen 443 ssl;
server_name muximux.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Traefik (Docker Labels)
services:
muximux:
image: ghcr.io/mescon/muximux:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.muximux.rule=Host(`muximux.example.com`)"
- "traefik.http.routers.muximux.tls.certresolver=letsencrypt"
- "traefik.http.services.muximux.loadbalancer.server.port=8080"
volumes:
- ./data:/app/data
Subpath Deployment (Base Path)
If your reverse proxy serves Muximux at a subpath (e.g., https://example.com/muximux/ instead of a dedicated domain), configure the base path so Muximux generates correct URLs for assets, API calls, and WebSocket connections.
Configuration
Set the base path using any of these methods (in order of precedence):
# CLI flag
muximux --base-path /muximux
# Environment variable
MUXIMUX_BASE_PATH=/muximux muximux
# Or in config.yaml
server:
base_path: /muximux
The path must start with / and have no trailing slash. If not set, Muximux serves from the root.
Nginx (subpath)
location /muximux/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Traefik (subpath with StripPrefix)
services:
muximux:
image: ghcr.io/mescon/muximux:latest
environment:
- MUXIMUX_BASE_PATH=/muximux
labels:
- "traefik.enable=true"
- "traefik.http.routers.muximux.rule=PathPrefix(`/muximux`)"
- "traefik.http.routers.muximux.tls.certresolver=letsencrypt"
- "traefik.http.services.muximux.loadbalancer.server.port=8080"
volumes:
- ./data:/app/data
Note: Muximux handles its own path stripping internally. Do not use Traefik's
StripPrefixmiddleware - Muximux expects the full path including the base prefix and strips it itself.
Docker Compose (subpath)
services:
muximux:
image: ghcr.io/mescon/muximux:latest
environment:
- MUXIMUX_BASE_PATH=/muximux
ports:
- "8080:8080"
volumes:
- ./data:/app/data
restart: unless-stopped
Network Considerations
- Same network as apps: Muximux needs to reach your apps (for health checks and the built-in reverse proxy). In Docker, use the same Docker network or host networking.
- WebSocket support: If running behind an external reverse proxy, make sure it supports WebSocket connections (needed for real-time health updates).
- Ports:
- Behind an external proxy: only 8080 (or your configured listen port), and it doesn't need to be publicly accessible.
- Standalone: 8080 (or your configured listen port).
- Full reverse proxy appliance: 80 and 443. Port 8080 is not needed externally.