Self-hosted Docker monitoring dashboard for viewing container logs, health/status, resource usage, alerts, incidents, and public status pages.
- Container Monitoring - Real-time container status, health checks, and restart tracking
- Log Viewer - Live tail and historical logs with regex search and severity highlighting
- Metrics Dashboard - CPU, memory, network, and I/O metrics per container
- Event Timeline - Docker events with correlation to alerts and incidents
- Stack Detection - Auto-detect Docker Compose projects
- Advanced Alert Rules - Configurable alerts with multiple condition types:
health_status- Container health state changescontainer_status- Container stopped/paused/dead detectionrestart_count- Restart loop detection with configurable thresholdsresource_threshold- CPU/memory percentage alertslog_pattern- Regex pattern matching on container logs
- Container Filtering - Target specific containers with wildcard support (e.g.,
plex,*arr,flaresolverr*) - Deduplication - Per-alert dedup windows to prevent notification spam
- Duration-based Conditions - Time-based persistence before triggering
- Incident Management - Group alerts, track lifecycle (Open β Investigating β Resolved)
- Discord Notifications - Rich embed alerts with severity colors and container details
- Linear Ticketing - Auto-create tickets from incidents
- Webhook Support - Custom webhook integrations
- Public Status Page - Beautiful public-facing status page at
/status - Custom Domain Support - Host your status page on a subdomain (e.g.,
status.example.com) - Service Grouping - Organize services by category (Media, Indexing, Infrastructure, etc.)
- Impact Levels - Critical, Major, Minor severity for each service
- Per-Container Control - Enable/disable individual containers from the status page
- Uptime Tracking - Historical uptime percentages (24h, 7d, 30d)
- Incident Display - Show active and resolved incidents on the status page
- Built-in Auth - Local username/password authentication
- Session Management - Secure cookie-based sessions
- Status Page Bypass - Public status page accessible without login
- Media Server Support - Built-in detection for Plex, Jellyfin, Sonarr, Radarr, etc.
- Service Grouping - Auto-categorize Media, Indexers, Automation, Infrastructure
- Predefined Alerts - Smart defaults for common media server issues
- Framework: Next.js 15 (App Router)
- Language: TypeScript
- Styling: TailwindCSS 4
- UI Components: ShadCN UI
- Database: SQLite (Drizzle ORM)
- Docker API: dockerode
- Configuration: YAML
services:
controlyze:
image: ghcr.io/moderniselife/controlyze:latest
container_name: controlyze
restart: unless-stopped
user: "1001:1001"
group_add:
- "${DOCKER_GID:-999}"
ports:
- "3100:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data:/app/data
environment:
- TZ=Your/Timezone
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
- LINEAR_API_KEY=${LINEAR_API_KEY}
- LINEAR_TEAM_ID=${LINEAR_TEAM_ID}
- ADMIN_PASSWORD_HASH=${ADMIN_PASSWORD_HASH}- Node.js 18+ or Bun
- Docker running locally or accessible via TCP/SSH
# Clone the repository
git clone https://github.com/moderniselife/controlyze.git
cd controlyze
# Install dependencies
bun install
# Generate database
bun run db:generate
bun run db:push
# Start development server
bun run devOpen http://localhost:3000 in your browser.
# Build for production
bun run build
# Start production server
bun run startControlyze can be configured via the web UI or a YAML config file at ./data/controlyze.yml.
version: "1"
docker:
connection:
type: socket
socketPath: /var/run/docker.sock
stacks:
profiles:
schrostack:
enabled: true
services:
media: [plex, jellyfin, tunarr, overseerr, tautulli]
indexers: [prowlarr, jackett, flaresolverr*]
automation: [schrodrive, watchtower, pd_zurg]
infrastructure: [cloudflare-tunnel, gluetun]
alerts:
rules:
# Generic alerts for all containers
- name: container_unhealthy
enabled: true
condition:
type: health_status
status: unhealthy
duration: 30s
severity: warning
routing:
discord: true
# Container-specific alerts
- name: plex_down
enabled: true
description: "Plex media server is not running"
condition:
container: plex
type: container_status
status: exited
severity: critical
routing:
discord: true
autoTicket: true
- name: zurg_mount_failed
enabled: true
condition:
container: pd_zurg
type: health_status
status: unhealthy
duration: 60s
severity: critical
routing:
discord: true
# Resource monitoring
- name: plex_high_memory
enabled: true
condition:
container: plex
type: resource_threshold
metric: memory_percent
threshold: 85
duration: 5m
severity: warning
# Log pattern matching
- name: schrodrive_errors
enabled: true
condition:
container: schrodrive
type: log_pattern
pattern: "(?i)(error|failed|exception)"
excludePattern: "(?i)(retry|expected)"
severity: warning
dedupWindow: 10m
defaults:
cooldown: 5m
dedupEnabled: true
discord:
enabled: true
webhookUrl: ${DISCORD_WEBHOOK_URL}
ticketing:
provider: linear
linear:
apiKey: ${LINEAR_API_KEY}
teamId: ${LINEAR_TEAM_ID}
auth:
enabled: true
provider: local
local:
users:
- username: admin
passwordHash: ${ADMIN_PASSWORD_HASH}
statusPage:
enabled: true
title: "System Status"
domain: status.example.com
ui:
theme: dark
refreshInterval: 5s| Variable | Description |
|---|---|
DATABASE_PATH |
SQLite database path (default: ./data/controlyze.db) |
CONFIG_PATH |
Configuration file path (default: ./data/controlyze.yml) |
DISCORD_WEBHOOK_URL |
Discord webhook URL for alerts |
LINEAR_API_KEY |
Linear API key for ticketing |
LINEAR_TEAM_ID |
Linear team ID |
ADMIN_PASSWORD_HASH |
Bcrypt hash of admin password |
AUTH_DISABLED |
Set to true to disable authentication |
STATUS_PAGE_DOMAIN |
Domain for status page (alternative to YAML config) |
| Page | Description |
|---|---|
/ |
Overview dashboard with health summary |
/login |
Authentication page |
/status |
Public status page |
/stacks |
Docker Compose stacks |
/containers |
Container list with actions |
/logs |
Live log viewer |
/metrics |
Resource usage metrics |
/events |
Docker event timeline |
/alerts |
Alert rules configuration |
/incidents |
Incident management |
/tickets |
Ticket tracking |
/integrations |
Discord & ticketing setup |
/connections |
Docker connection settings |
/settings |
Application settings (auth, status page, alerts) |
GET /api/docker/containers- List containersGET /api/docker/containers/[id]- Container detailsGET /api/docker/containers/[id]/logs- Container logsGET /api/docker/containers/[id]/stats- Container statsPOST /api/docker/containers/[id]/start- Start containerPOST /api/docker/containers/[id]/stop- Stop containerPOST /api/docker/containers/[id]/restart- Restart containerGET /api/docker/stacks- List stacksGET /api/docker/events- Docker events
GET /api/public/status- Public status page dataGET /api/public/health- Health check endpoint
POST /api/auth/login- Login with credentialsPOST /api/auth/logout- Logout and clear session
Controlyze has built-in support for media server stacks like SchroStack. When detected, it provides:
- Service Grouping - Media, Indexers, Automation, Infrastructure, Storage
- Auto-Detection - Recognizes Plex, Jellyfin, Sonarr, Radarr, Prowlarr, etc.
- Smart Defaults - Predefined alert rules and impact levels
- Quick Actions - Restart services, view logs, check health
Want to deploy the entire media server stack? Use the included docker-SchroStack.example.yml:
# Copy and customize the example
cp docker-SchroStack.example.yml docker-SchroStack.yml
# Edit with your settings (API keys, paths, timezone, etc.)
nano docker-SchroStack.yml
# Deploy the stack
docker compose -f docker-SchroStack.yml up -dThe stack includes: Plex/Jellyfin, Overseerr, Prowlarr, Jackett, FlareSolverr pool, Tunarr, Tautulli, SchroDrive, pd_zurg, Cloudflare Tunnel, Gluetun VPN, and Controlyze itself.
# Run development server
bun run dev
# Run linting
bun run lint
# Generate database migrations
bun run db:generate
# Push database changes
bun run db:push
# Build Docker image
docker build -t controlyze .src/
βββ app/ # Next.js pages
β βββ api/ # API routes
β βββ containers/ # Container management
β βββ logs/ # Log viewer
β βββ alerts/ # Alert rules
β βββ ...
βββ components/
β βββ ui/ # ShadCN components
β βββ dashboard/ # Dashboard components
βββ lib/
β βββ db/ # Database schema
β βββ docker/ # Docker API
β βββ config/ # Configuration
β βββ integrations/ # Discord, ticketing
β βββ schrostack/ # SchroStack profile
βββ stores/ # Zustand stores
βββ types/ # TypeScript types
MIT License - see LICENSE for details.
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
- ShadCN UI for the beautiful components
- dockerode for Docker API access
- Drizzle ORM for database management