Self-Hosting Monit with Docker Compose

What Is Monit?

Monit is a lightweight process and system monitoring tool that can automatically restart failed services, monitor resource usage, and alert you when thresholds are breached. It replaces the need for manual process babysitting and expensive monitoring SaaS. Monit runs as a daemon, checking services at configurable intervals, and provides a simple web UI for status visibility.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 512 MB of free RAM (minimum)
  • 1 GB of free disk space
  • A domain name (optional, for remote access)

Docker Compose Configuration

Monit does not have an official Docker image. The best community option is the lightweight Alpine-based image. Create a project directory and the following files.

Create a docker-compose.yml file:

services:
  monit:
    image: kijart/monit:5.34.2
    container_name: monit
    restart: unless-stopped
    ports:
      - "2812:2812"    # Monit web UI
    volumes:
      - ./monitrc:/etc/monit/monitrc:ro    # Main config file
      - ./conf.d:/etc/monit/conf.d:ro      # Additional service monitors
      - monit-state:/var/lib/monit          # Persistent state
      - /var/run/docker.sock:/var/run/docker.sock:ro  # Monitor Docker containers
      - /proc:/host/proc:ro                 # Host process info
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge

volumes:
  monit-state:

Create a monitrc configuration file:

# /monitrc - Monit main configuration
# This file MUST have permissions 0700 (chmod 700 monitrc)

# Check services every 30 seconds
set daemon 30

# Enable web interface
set httpd port 2812 and
    use address 0.0.0.0
    allow admin:changeme    # CHANGE THIS PASSWORD

# Log to stdout for Docker
set log syslog

# State file for persistence
set statefile /var/lib/monit/monit.state

# Mail server for alerts (optional - configure your SMTP)
# set mailserver smtp.example.com port 587
#     username "alerts@example.com"
#     password "your-smtp-password"
#     using tlsv13

# Alert recipient
# set alert admin@example.com

# System monitoring
check system $HOST
    if loadavg (1min) per core > 2 for 5 cycles then alert
    if loadavg (5min) per core > 1.5 for 10 cycles then alert
    if cpu usage > 90% for 5 cycles then alert
    if memory usage > 85% then alert
    if swap usage > 25% then alert

# Include additional service monitors
include /etc/monit/conf.d/*

Create a conf.d/ directory with example service monitors:

mkdir -p conf.d

Example conf.d/docker.conf for monitoring a Docker container:

# Monitor a Docker container by name
check program nginx-container with path "/bin/sh -c 'docker inspect --format={{.State.Running}} nginx 2>/dev/null | grep true'"
    if status != 0 for 3 cycles then alert
    group docker

Set correct permissions and start:

chmod 700 monitrc
docker compose up -d

Initial Setup

  1. Open http://your-server-ip:2812 in your browser
  2. Log in with the credentials from monitrc (default: admin / changeme)
  3. The dashboard shows all monitored services and system metrics
  4. Change the default password immediately by editing monitrc
Default SettingValue
Web UI port2812
Usernameadmin
Passwordchangeme
Check interval30 seconds

Configuration

Adding Service Monitors

Monit uses a declarative config syntax. Add files to conf.d/ for each service:

Monitor a network service:

# conf.d/ssh.conf
check process sshd with pidfile /var/run/sshd.pid
    start program = "/usr/sbin/service ssh start"
    stop program = "/usr/sbin/service ssh stop"
    if failed port 22 protocol ssh then restart
    if 5 restarts within 5 cycles then alert

Monitor disk space:

# conf.d/disk.conf
check filesystem rootfs with path /
    if space usage > 80% then alert
    if space usage > 95% then exec "/bin/sh -c 'docker system prune -f'"

Monitor a Docker container health:

# conf.d/nextcloud.conf
check program nextcloud with path "/bin/sh -c 'docker inspect --format={{.State.Health.Status}} nextcloud 2>/dev/null | grep healthy'"
    if status != 0 for 5 cycles then alert
    group docker

Alert Configuration

Configure email alerts by uncommenting the mail server section in monitrc:

set mailserver smtp.gmail.com port 587
    username "your-email@gmail.com"
    password "app-specific-password"
    using tlsv13

set alert admin@example.com not on { instance, pid, ppid }

Advanced Configuration (Optional)

M/Monit Integration

M/Monit is the commercial companion that aggregates data from multiple Monit instances. Add to monitrc:

set mmonit http://user:password@mmonit.example.com:8080/collector

Custom Event Handlers

Monit can execute arbitrary scripts when conditions are met:

check process myapp matching "myapp"
    if failed port 8080 protocol http then exec "/usr/local/bin/restart-myapp.sh"
    if memory > 500 MB for 5 cycles then exec "/usr/local/bin/alert-slack.sh"

Reverse Proxy

To access Monit behind a reverse proxy with SSL:

Nginx Proxy Manager: Create a proxy host pointing to monit:2812. For detailed reverse proxy setup, see our Reverse Proxy Setup guide.

Caddy:

monit.example.com {
    reverse_proxy monit:2812
}

Backup

Back up the Monit configuration:

# Back up config files
cp -r monitrc conf.d/ /path/to/backup/

# State is recreated on restart — no backup needed

For a comprehensive backup strategy, see our Backup Strategy guide.

Troubleshooting

Monit refuses to start — “Permission denied”

Symptom: Container exits immediately with a permissions error. Fix: The monitrc file must have chmod 700 permissions:

chmod 700 monitrc
docker compose restart monit

Web UI not accessible

Symptom: Cannot reach the web interface on port 2812. Fix: Ensure monitrc has use address 0.0.0.0 (not localhost). Localhost binding prevents external access from outside the container.

Docker socket monitoring not working

Symptom: Docker container checks always fail. Fix: Verify the Docker socket is mounted and the container user has access:

docker compose exec monit ls -la /var/run/docker.sock

Alerts not sending

Symptom: Conditions trigger but no email arrives. Fix: Test SMTP connectivity from inside the container. Check that your mail server accepts connections from Docker’s network range. Use app-specific passwords for Gmail.

Resource Requirements

ResourceRequirement
RAM~20 MB idle, ~50 MB under load
CPUVery low — lightweight C daemon
Disk~10 MB for application + state

Monit is one of the lightest monitoring tools available. It runs comfortably on a Raspberry Pi.

Verdict

Monit is the right choice when you need process supervision and automatic restarts — not dashboards or metrics history. It excels at keeping services alive and alerting on basic system thresholds with almost zero resource overhead. If you want pretty graphs and long-term metrics, use Grafana + Prometheus. If you want simple uptime monitoring, use Uptime Kuma. But if you want a tiny daemon that watches your processes and restarts them when they die, Monit is hard to beat.

For a richer monitoring experience with a web dashboard, consider Netdata (real-time metrics) or Beszel (lightweight server monitoring).

FAQ

How does Monit compare to Uptime Kuma?

Different tools for different jobs. Uptime Kuma monitors URLs and services from the outside — is it up or down? Monit monitors processes from the inside — is the PID running, is RAM usage too high, should I restart it? Use Uptime Kuma for uptime dashboards and status pages. Use Monit for automatic service recovery and process supervision.

Can Monit automatically restart Docker containers?

Yes, with some setup. Mount the Docker socket into the Monit container and use check program with docker inspect to verify container health. Configure the exec action to run docker restart <container> when checks fail. This requires the Docker CLI inside the Monit container.

Is M/Monit required?

No. M/Monit is the commercial web dashboard that aggregates data from multiple Monit instances. The free Monit daemon works standalone with its built-in web UI. M/Monit adds centralized monitoring across multiple servers, historical data, and better alerting — useful for managing 5+ servers.

Can Monit replace Prometheus and Grafana?

No. Monit is a process supervisor with basic threshold alerting — it watches services and restarts them. Prometheus + Grafana provide time-series metrics, dashboards, and complex alerting rules. Monit is 20 MB; Prometheus + Grafana is 1+ GB. Use Monit for automatic recovery; use Prometheus/Grafana for metrics visualization.

How do I monitor host processes from inside Docker?

Mount /proc and /var/run/docker.sock as read-only volumes into the Monit container. Use check program with shell commands that inspect host-level data through these mounts. For full host monitoring, running Monit directly on the host (not in Docker) is simpler.

What alerting options does Monit support?

Email alerts via SMTP (built-in), custom script execution on any event (pipe to Slack, PagerDuty, webhooks), and M/Monit for centralized alerting. The exec action can run any script, so you can integrate with any notification service.

Comments