Optional lightweight interface¶
For a minimal installation from the repository root, use the Compose quickstart. The standalone example below remains available for the advanced UI overlays.
monit-docker-ui is a separate, optional Community component. The Python package
and the simple/cron mode do not include a frontend. An agent in serve mode
supplies API v1; Nginx serves the UI and authenticates its API requests.
The desktop layout shows a compact container list; on mobile each container is a card with touch-sized buttons. It displays current status, CPU, memory, collection health and cumulative rule-action counters. It has no historical graphs: use Grafana for those. The last 32 manual request results are a temporary operational view, not a durable audit log.
When a monitoring cycle fails, the dashboard can show the last complete snapshot with its date and time. Its rows are read only. The failure notice identifies the action and container when available. A fresh successful cycle restores the live view. Before the first success there are no historical rows to show.
The browser refreshes every five seconds while visible. It hides measurements and disables controls if no successful status response arrives for ten seconds, including when automatic refresh is paused. Unknown metrics display a dash, not zero; CPU usage can exceed 100% on multiple cores.
Available since 0.0.63. The commands below use matching versioned images for the agent and the optional UI.
Try the published release in an isolated test¶
The Published UI acceptance GitHub Actions workflow pulls a matching agent/UI release from Docker Hub without rebuilding either image. It creates a temporary Compose project, credentials, certificate and one Alpine demonstration container. The agent’s name selector permits actions only on that container. The runner tests read-only access first, then enables manual controls and exercises cancellation, Stop, Start and Restart through Chromium at desktop and mobile viewport sizes. Actual Docker state is checked after each action; the API is not mocked.
For a quicker test, the overlay uses a one-second collection interval and manual cooldown. These are test settings; the documented installation below retains its 30-second defaults. The agent port stays private and HTTPS binds only to loopback. The temporary stack and state volume are removed when the test finishes.
The workflow artifact published-ui-acceptance contains desktop/mobile screenshots
and a report with the image tags and pulled digests. It contains no credentials or
browser traces. This is an automated test environment, not a persistent dashboard
URL. Once the workflow is on the default branch, Run workflow accepts a
published X.Y.Z version.
To reproduce on a disposable Linux Docker host with Python 3, OpenSSL, Node and Playwright Chromium installed:
MONIT_UI_RELEASE=0.0.69 \
PLAYWRIGHT_MODULE=/path/to/node_modules/playwright \
UI_SCREENSHOTS=/tmp/monit-ui-release-results \
python3 .github/scripts/check-ui-release.py
Start with read-only access¶
Requirements: Docker Compose v2, Python 3 and OpenSSL on the host. From the repository root:
cd examples/ui
python3 prepare.py --self-signed
docker compose up -d
The script asks for a username and password without echoing the password. It creates private local files and refuses to overwrite an existing directory. Open https://localhost:8443/ and authenticate using those credentials. The self-signed certificate is only for a local trial, expires after seven days, and causes a browser trust warning. No port 80 or unencrypted login is exposed.
For a real hostname, run python3 prepare.py without --self-signed, then put
your trusted certificate chain in secrets.local/tls.crt and its private key in
secrets.local/tls.key. Keep the directory and key private. Certificates are
provided by the operator; this example does not automate ACME or renewal.
To make the HTTPS proxy reachable on a chosen host interface, create a local
.env file, for example:
UI_BIND=192.0.2.10
UI_PORT=443
Replace the documentation address with an actual address on your host and use a certificate for your hostname. The default is loopback only. The agent’s port 9808 is never published by this Compose example. Nginx is the only component exposed to the browser.
Enable manual actions¶
For a new installation, prepare the additional proxy secret:
cd examples/ui
python3 prepare.py --actions --self-signed
If you already prepared read-only credentials, stop the example, move
secrets.local to a private backup location outside the repository, then rerun
the command. For a real hostname, omit --self-signed and supply the trusted
certificate/key as above. Never commit or distribute the generated directory.
Set the exact browser origin, including a nonstandard port, in .env:
UI_ORIGIN=https://localhost:8443
Then start the action overlay:
docker compose -f compose.yaml -f compose.actions.yaml up -d
Opening https://127.0.0.1:8443 when the origin is configured as
https://localhost:8443 will allow reads but reject commands. Set the exact
origin you intend to use; do not add a trailing slash. There is no wildcard.
The UI requires confirmation before submitting a command. The server permits:
Action |
Accepted current container state |
|---|---|
Start |
|
Stop |
|
Restart |
|
Rearm auto restarts |
|
Rearm auto restarts appears when a counter is nonzero and the agent advertises support. Its confirmation shows the count being cleared and explains that matching rules may restart the container on the next cycle. The reset itself executes no Docker command and preserves automatic cooldowns and trigger timers. It uses the same authenticated queue, full-ID selection, protection checks and audit journal as the other actions. After success, the next snapshot refreshes the counter and the button disappears. See restart budgets.
All authenticated users have the same permissions. No user database, roles, shell execution, removal, pause or configuration editing is provided. The browser’s Basic authentication credentials are managed by Nginx; logging out may require closing the browser’s authenticated session.
An accepted request is queued, not proof that Docker completed the action. Follow its outcome under Manual activity. A slow monitoring cycle delays the command; an unstarted request expires after 60 seconds. There is at most one queued or running request. The next monitoring cycle refreshes measurements after the attempt. There is no forced timeout or cancellation of an active Docker call, and shutting down the agent discards queued requests.
The agent reselects the target using its full container ID and the configured
selectors immediately before execution. A replacement with the same name is
not targeted. A persistent 30-second per-container manual cooldown applies
across all manual commands, including rearm, and agent restarts, including failed attempts after
reservation. --action-cooldown can change this (minimum one second).
Autonomous rule cooldowns remain separate. Existing rules remain active and
may reverse a manual stop/start on the next cycle; account for that in rules.
Manual requests do not reset persistent trigger observations.
The API deduplicates request IDs within its last 32 in-memory results. That history and deduplication disappear at agent restart; this is not an exactly-once delivery guarantee. The persistent cooldown reduces repeated attempts. If a network response is lost, the UI does not retry automatically; inspect recent requests and the actual container state before another action.
Protect a container from manual actions¶
Add this Docker label to a container that should stay visible in monitoring but must not accept manual Start, Stop, Restart or Rearm requests:
services:
database:
labels:
monit-docker.protected: "true"
Apply the label through your normal container deployment. Editing a Compose file alone does not change a running container’s labels; recreation is required. The UI displays a Protected lock and disables that container’s controls. The agent rejects authenticated direct API requests too, and checks fresh container metadata again before executing an already queued request. Rejections do not reserve a manual cooldown.
Only manual actions are blocked. Monitoring, metrics, notifications and
automatic rules in serve, cron or monit retain their existing behavior.
This label is not a Docker permission boundary: it does not restrict an operator
using the Docker CLI or another service with Docker socket access.
Without the label, existing manual behavior is unchanged. Use "false" to opt
out explicitly ("0", "no" and "off" are also accepted, ignoring case and
surrounding whitespace). Any other value, including an empty value or typo,
protects the container. Prefer the quoted "true" / "false" spelling above.
This feature is available since 0.0.64 in both the agent and UI. The earlier
0.0.63 images do not enforce this label. Older UIs may
still show enabled buttons, but the upgraded agent rejects protected actions.
Authentication and network boundaries¶
Nginx protects the HTML, assets, status API and command endpoint with Basic
authentication over TLS. The browser never receives the proxy’s action secret.
Nginx replaces any caller-supplied X-Monit-Action-Token with the configured
secret. The agent requires that secret plus the exact allowed HTTPS Origin
and a bounded JSON request. It does not trust a forwarded username. A cross-site
form cannot submit an accepted command. No CORS permission is granted.
The agent itself still has no read authentication or TLS. Only the private
network can reach its status/metrics endpoints. Its write API is disabled
unless --allow-actions is set together with --action-origin,
--action-token-file and --state-file. Combining it with --dry-run is an
error. The token file contains 64 lowercase hexadecimal characters; generate
it using a cryptographic random source. Rotate the token on both the agent and
proxy, then restart both. Use one state file when coordinating with cron.
Nginx serves only /, /app.css, /app.js, /v1/status and /v1/actions.
/metrics, /healthz, /readyz and other paths are not forwarded publicly.
The page uses a restrictive Content Security Policy and treats names as text.
All frontend assets are local and require no third-party network requests.
Only the agent mounts the Docker socket. A read-only socket mount does not restrict Docker API privileges. Limit the agent’s container selectors when you do not want all containers to be eligible for manual operations.
Prometheus¶
Prometheus uses http://monit-docker:9808/metrics on the private agent
network, without the browser’s authentication. There is no second agent port.
For example, add this file as another Compose overlay:
services:
prometheus:
image: prom/prometheus:v3.5.0
networks: [agent]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
Create prometheus.yml alongside it:
global:
scrape_interval: 15s
scrape_configs:
- job_name: monit-docker
static_configs:
- targets: ['monit-docker:9808']
Do not run the existing full monitoring Compose stack as well unless you intend to run a second agent. You can instead adapt its Prometheus/Grafana services to this stack. If an agent needs a remote Docker API rather than a local socket, review the private network’s routing before changing the example.
Updates and validation¶
Update both image tags in the Compose file, pull the images and recreate both services. Nginx resolves the agent’s Docker DNS address when it starts, so restart Nginx when recreating the agent. After replacing a certificate or credentials, recreate the UI container to reread the mounted files:
docker compose -f compose.yaml -f compose.actions.yaml pull
docker compose -f compose.yaml -f compose.actions.yaml up -d --force-recreate
Use only compose.yaml for read-only installations. To disable writes, recreate
the agent without the actions overlay. Keep the state volume if you need its
cooldowns; down --volumes deletes it.
The release workflow tests the Nginx image for authentication, TLS, origin
checks, token replacement, direct-write rejection and private metrics. Browser
tests cover mobile/desktop rendering, literal container names, confirmation,
offline/stale data and ambiguous responses. The ui-screenshots CI artifact
contains screenshots generated from synthetic demonstration data.
Nginx configuration reference: Basic authentication, HTTPS and proxy headers.
Public demo¶
Try the shared public demo without installing
anything. Actions operate real containers and are visible to other visitors.
Only monit-demo-web and monit-demo-worker can be controlled; the agent,
interface and HTTPS proxy remain visible and protected from manual actions.
Stopped test containers are automatically started after five minutes, checked once per minute by a timer on the demo host. Running containers are left alone; containers, volumes and recent manual activity are not cleared. This recovery is specific to the public demonstration and is not enabled on your own installation. Its starts are recorded in the host journal, outside the manual request history.
Your own UI installation uses the credentials, trusted proxy and exact action origin described in this guide.
For persistent manual and automatic action history and authenticated actor attribution, see the audit journal guide.
Persistent journal page (since 0.0.66)¶
The optional Journal link opens /logs when private audit reading is enabled.
It provides filters, event details, bounded pagination and CSV/JSONL exports of
the displayed page. It does not poll in the background. See the
audit guide for explicit
activation, a separate proxy secret, versioned Compose wiring and retention.
The public demo keeps its journal private.