# Tyto
![Go Version](https://img.shields.io/badge/Go-1.23-00ADD8?style=flat-square&logo=go) ![SvelteKit](https://img.shields.io/badge/SvelteKit-2.0-FF3E00?style=flat-square&logo=svelte) ![Tailwind CSS](https://img.shields.io/badge/Tailwind-3.4-06B6D4?style=flat-square&logo=tailwindcss) ![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?style=flat-square&logo=docker) ![License](https://img.shields.io/badge/License-MIT-green?style=flat-square) **A real-time Linux system monitoring dashboard with multi-device support** *Named after Tyto alba, the barn owl — nature's silent, watchful guardian* [Features](#features) • [Quick Start](#quick-start) • [Multi-Device Setup](#multi-device-monitoring) • [Authentication](#authentication) • [API](#api-reference) • [Development](#development)
--- ## Overview Tyto is a lightweight, containerized monitoring solution that provides real-time visibility into your Linux systems. Built with a Go backend for efficient metric collection and a SvelteKit frontend for a responsive, modern UI. ### Key Highlights - **Real-time streaming** via Server-Sent Events (SSE) - **Zero dependencies** on the host system (runs in Docker) - **Multi-host support** for monitoring multiple machines from one dashboard - **Desktop notifications** for critical alerts - **Process management** with kill/pause/resume functionality - **Dark/Light themes** with responsive mobile design --- ## Features | Category | Features | |----------|----------| | **System** | Hostname, kernel version, uptime, architecture | | **CPU** | Per-core usage, frequency, load averages | | **Memory** | RAM usage, buffers, cache, swap | | **Disk** | Mount points, usage, I/O rates | | **Network** | Interface stats, bandwidth rates, TCP connections | | **Processes** | Top by CPU/Memory, detailed view, signal control | | **Temperature** | Hardware sensors via hwmon | | **GPU** | Multi-vendor support: NVIDIA, AMD, Intel (utilization, VRAM, power, clocks) | | **Docker** | Container stats (CPU, memory, status) | | **Systemd** | Service status monitoring | | **Alerts** | Configurable thresholds with desktop notifications | | **History** | Sparkline charts for CPU, memory, network, disk I/O | | **Export** | CSV and JSON export of current metrics | | **Logs** | Centralized log collection from journal, files, Docker | | **Authentication** | Local accounts and LDAP/AD integration | | **RBAC** | Role-based access control with customizable permissions | | **Multi-Device** | Central server with lightweight agents via mTLS | --- ## Quick Start ### Using Docker Compose (Recommended) ```bash # Clone the repository git clone https://github.com/yourusername/tyto.git cd tyto # Start the containers docker compose up -d # Access the dashboard open http://localhost:9847 ``` ### Ports | Service | Port | Description | |---------|------|-------------| | Frontend | 9847 | Web dashboard | | Backend | 9848 | API server (internal) | --- ## Configuration ### Operational Modes Tyto supports three operational modes: | Mode | Description | |------|-------------| | `standalone` | Single-host monitoring, no database required (default) | | `server` | Central server for multi-device monitoring with database | | `agent` | Lightweight agent that reports to a central server | Set the mode via environment variable or config file: ```bash TYTO_MODE=server tyto ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `TYTO_MODE` | `standalone` | Operational mode | | `TYTO_REFRESH_RATE` | `5` | Metric collection interval (seconds) | | `TYTO_LOG_LEVEL` | `info` | Log level (debug, info, warn, error) | | `TYTO_DB_TYPE` | `sqlite` | Database type (sqlite, postgres) | | `TYTO_DB_PATH` | `/data/tyto.db` | SQLite database path | | `TYTO_DB_URL` | | PostgreSQL connection string | | `PORT` | `8080` | HTTP server port | | `PROC_PATH` | `/proc` | Path to proc filesystem | | `SYS_PATH` | `/sys` | Path to sys filesystem | | `MTAB_PATH` | `/etc/mtab` | Path to mount table | | `DOCKER_SOCKET` | `/var/run/docker.sock` | Docker socket path | ### Database Configuration **SQLite** (default, recommended for single server): ```yaml database: type: sqlite path: /var/lib/tyto/tyto.db ``` **PostgreSQL** (for high availability): ```yaml database: type: postgres url: postgres://user:pass@localhost:5432/tyto?sslmode=require ``` ### Data Retention Configure metric retention with tiered aggregation: ```yaml database: retention: raw: 24h # Full resolution one_minute: 168h # 7 days five_minute: 720h # 30 days hourly: 8760h # 1 year logs: 168h # 7 days ``` ### Required Volume Mounts For the backend to collect host metrics, these mounts are required: ```yaml volumes: - /proc:/host/proc:ro # Process information - /sys:/host/sys:ro # Hardware sensors, GPU info - /etc/mtab:/host/etc/mtab:ro # Disk mount information ``` ### Optional Features
Docker Monitoring Mount the Docker socket to enable container monitoring: ```yaml volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ```
Systemd Service Monitoring Mount the D-Bus socket to enable systemd service monitoring: ```yaml volumes: - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro ```
--- ## Multi-Host Monitoring System Monitor supports monitoring multiple hosts from a single dashboard. Each host runs its own backend container, and the frontend can switch between them. ### Setting Up Remote Hosts 1. **Deploy on each host** you want to monitor: ```bash # On remote-host-1 (e.g., 192.168.1.100) docker compose up -d ``` 2. **Configure CORS** (if accessing from a different origin): The backend allows cross-origin requests by default. Ensure ports are accessible. 3. **Add hosts in the dashboard**: - Click the **host selector** dropdown in the header - Click **"Add Remote Host"** - Enter a name (e.g., "Web Server") and URL (e.g., `http://192.168.1.100:9847`) ### Network Diagram ``` ┌─────────────────────────────────────────────────────────────┐ │ Your Browser │ │ http://localhost:9847 │ └──────────────────────────┬──────────────────────────────────┘ │ ┌──────────────┼──────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ Host A │ │ Host B │ │ Host C │ │ (local) │ │ :9847 │ │ :9847 │ │ Frontend + │ │ Frontend + │ │ Frontend + │ │ Backend │ │ Backend │ │ Backend │ └────────────┘ └────────────┘ └────────────┘ ``` ### Host Configuration Storage Host configurations are stored in browser localStorage under the key `tyto-hosts`. The active host is stored in `tyto-active-host`. --- ## Authentication Tyto supports multiple authentication methods for securing access to the dashboard. ### Local Authentication Local user accounts with username/password stored in the database (bcrypt hashed). ```bash # Create initial admin user during setup tyto setup --admin-user admin --admin-pass # Or via API after setup curl -X POST http://localhost:9847/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{"username": "admin", "password": "secret", "email": "admin@example.com"}' ``` ### LDAP/Active Directory Configure LDAP authentication in `config.yaml`: ```yaml auth: ldap: enabled: true url: ldap://ad.example.com:389 base_dn: dc=example,dc=com bind_dn: cn=readonly,dc=example,dc=com bind_password: ${LDAP_BIND_PASSWORD} user_filter: (sAMAccountName=%s) group_mappings: "CN=Tyto Admins,OU=Groups,DC=example,DC=com": admin "CN=Tyto Operators,OU=Groups,DC=example,DC=com": operator ``` ### Role-Based Access Control (RBAC) Tyto includes a flexible permission system with three built-in roles: | Role | Permissions | |------|-------------| | **Administrator** | Full system access (`*`) | | **Operator** | Manage agents, alerts, view/export metrics | | **Viewer** | Read-only dashboard access | Custom roles can be created via the Admin panel with granular permissions: - `dashboard:view` - View dashboard - `agents:view`, `agents:manage` - Agent management - `alerts:view`, `alerts:acknowledge`, `alerts:configure` - Alert handling - `users:view`, `users:manage` - User management - `roles:view`, `roles:manage` - Role management - `metrics:export`, `metrics:query` - Metrics access - `pki:manage` - Certificate management --- ## API Reference ### Endpoints #### Metrics & Monitoring | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/v1/stream` | SSE stream of real-time metrics | | `GET` | `/api/v1/history` | Historical metric data (1 hour) | | `GET` | `/api/v1/alerts` | Current alerts and configuration | | `POST` | `/api/v1/alerts/config` | Update alert thresholds | | `POST` | `/api/v1/alerts/:id/acknowledge` | Acknowledge an alert | | `GET` | `/api/v1/processes/:pid` | Detailed process information | | `POST` | `/api/v1/processes/:pid/signal` | Send signal to process | | `POST` | `/api/v1/settings/refresh` | Update refresh interval | | `GET` | `/api/v1/export/metrics?format=csv\|json` | Export current metrics | | `GET` | `/health` | Health check endpoint | #### Authentication | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/api/v1/auth/login` | Login with username/password | | `POST` | `/api/v1/auth/logout` | Logout (invalidate session) | | `POST` | `/api/v1/auth/register` | Register new user (if enabled) | | `GET` | `/api/v1/auth/me` | Get current user info | | `PUT` | `/api/v1/auth/me` | Update current user profile | | `PUT` | `/api/v1/auth/me/password` | Change password | #### User & Role Management | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/v1/users` | List all users | | `POST` | `/api/v1/users` | Create new user | | `GET` | `/api/v1/users/:id` | Get user details | | `PUT` | `/api/v1/users/:id` | Update user | | `DELETE` | `/api/v1/users/:id` | Disable user | | `GET` | `/api/v1/roles` | List all roles | | `POST` | `/api/v1/roles` | Create custom role | | `PUT` | `/api/v1/roles/:id` | Update role | | `DELETE` | `/api/v1/roles/:id` | Delete custom role | #### Agent Management | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/v1/agents` | List all agents | | `GET` | `/api/v1/agents/:id` | Get agent details | | `POST` | `/api/v1/agents` | Add agent manually | | `DELETE` | `/api/v1/agents/:id` | Remove agent | | `POST` | `/api/v1/agents/:id/revoke` | Revoke agent certificate | | `GET` | `/api/v1/agents/pending` | List pending registrations | | `POST` | `/api/v1/agents/pending/:id/approve` | Approve agent | | `POST` | `/api/v1/agents/pending/:id/reject` | Reject agent | #### Logs | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/v1/logs` | Query logs with filters | | `GET` | `/api/v1/logs/stream` | SSE stream of live logs | ### SSE Stream Format The `/api/v1/stream` endpoint sends JSON messages with this structure: ```json { "timestamp": "2024-01-15T10:30:00Z", "system": { "hostname": "...", "kernel": "...", "uptime": 12345 }, "cpu": { "cores": [...], "totalUsage": 15.5, "loadAverage": {...} }, "memory": { "total": 16000000000, "used": 8000000000, ... }, "disk": { "mounts": [...], "io": [...] }, "network": { "interfaces": [...], "connectionCount": 42 }, "processes": { "topByCpu": [...], "topByMemory": [...], "total": 200 }, "temperature": { "sensors": [...] }, "gpu": { "available": true, "utilization": 45, ... }, "docker": { "available": true, "containers": [...] }, "systemd": { "available": true, "services": [...] } } ``` ### Process Signal API ```bash # Send SIGTERM (graceful termination) curl -X POST http://localhost:9847/api/v1/processes/1234/signal \ -H "Content-Type: application/json" \ -d '{"signal": 15}' # Send SIGKILL (force kill) curl -X POST http://localhost:9847/api/v1/processes/1234/signal \ -H "Content-Type: application/json" \ -d '{"signal": 9}' ``` --- ## Development ### Prerequisites - **Go 1.23+** - **Node.js 22+** - **Docker & Docker Compose** (for containerized development) ### Local Development ```bash # Backend (Go) cd backend go mod download go run ./cmd/server # Frontend (SvelteKit) cd frontend npm install npm run dev ``` ### Running Tests ```bash # Backend tests cd backend go test ./... # Frontend tests cd frontend npm test ``` ### Project Structure ``` tyto/ ├── backend/ │ ├── cmd/ │ │ ├── server/ # HTTP/SSE server entry point │ │ ├── agent/ # Lightweight agent entry point │ │ └── tyto/ # CLI tool (pki, setup) │ ├── internal/ │ │ ├── api/ # HTTP handlers and routes │ │ ├── alerts/ # Alert management │ │ ├── auth/ # Authentication (local, LDAP) │ │ ├── collectors/ # Metric collectors │ │ │ ├── gpu/ # Multi-vendor GPU support │ │ │ └── logs/ # Log collectors │ │ ├── config/ # Configuration │ │ ├── database/ # SQLite/PostgreSQL abstraction │ │ ├── history/ # Historical data storage │ │ ├── models/ # Data structures │ │ ├── pki/ # Certificate management │ │ ├── server/ # gRPC hub for agents │ │ └── sse/ # Server-Sent Events broker │ ├── proto/ # gRPC protocol definitions │ └── Dockerfile ├── frontend/ │ ├── src/ │ │ ├── lib/ │ │ │ ├── api/ # API clients │ │ │ ├── components/ # Svelte components │ │ │ │ ├── auth/ # Login, UserMenu │ │ │ │ └── admin/ # User/Role management │ │ │ ├── stores/ # Svelte stores │ │ │ ├── types/ # TypeScript types │ │ │ └── utils/ # Utility functions │ │ └── routes/ # SvelteKit routes │ │ ├── admin/ # Admin pages │ │ ├── login/ # Login page │ │ └── logs/ # Log viewer │ └── Dockerfile ├── scripts/ │ └── install.sh # One-line installer ├── docker-compose.yml # Base configuration └── docker-compose.prod.yml # Production overrides ``` ### Building Docker Images ```bash # Build both images docker compose build # Build specific service docker compose build backend docker compose build frontend ``` --- ## Deployment ### One-Line Installation Install Tyto on any Linux system: ```bash # Server installation curl -fsSL https://raw.githubusercontent.com/vikingowl/tyto/main/scripts/install.sh | sudo bash # Agent installation curl -fsSL https://raw.githubusercontent.com/vikingowl/tyto/main/scripts/install.sh | \ sudo TYTO_MODE=agent bash ``` ### PKI Setup (mTLS) For secure multi-device deployments, set up mTLS certificates: ```bash # Initialize Certificate Authority (on server) tyto pki init-ca --cn "Tyto CA" --out /etc/tyto/pki/ # Generate server certificate tyto pki gen-server --ca-dir /etc/tyto/pki/ --dns tyto.example.com # Generate agent certificates tyto pki gen-agent --ca-dir /etc/tyto/pki/ --agent-id web-server-01 tyto pki gen-agent --ca-dir /etc/tyto/pki/ --agent-id db-server-01 # List certificates tyto pki list --ca-dir /etc/tyto/pki/ # Revoke a compromised certificate tyto pki revoke --serial ABC123 --ca-dir /etc/tyto/pki/ ``` ### Agent Configuration Deploy the agent on each monitored host: ```yaml # /etc/tyto/config.yaml mode: agent agent: id: web-server-01 server_url: tyto-server.example.com:9849 interval: 5s tls: ca_cert: /etc/tyto/certs/ca.crt agent_cert: /etc/tyto/certs/agent.crt agent_key: /etc/tyto/certs/agent.key ``` ### Systemd Service Tyto installs as a systemd service: ```bash # Check status systemctl status tyto # View logs journalctl -u tyto -f # Restart systemctl restart tyto ``` ### Production Docker Compose Use the production overlay for resource limits: ```bash docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d ``` --- ## Keyboard Shortcuts | Key | Action | |-----|--------| | `T` | Toggle dark/light theme | | `R` | Cycle refresh rate | | `?` | Show keyboard shortcuts | | `Esc` | Close modals/panels | --- ## Alerts & Notifications ### Configuring Thresholds 1. Open the **Alerts** card 2. Click **"Configure Thresholds"** 3. Set warning and critical percentages for each metric type 4. Click **"Save Configuration"** ### Desktop Notifications 1. Enable the **"Desktop Notifications"** toggle in the Alerts card 2. Allow browser notification permission when prompted 3. Notifications will appear for new warning/critical alerts > **Note:** Critical alerts require manual dismissal; warnings auto-close after 10 seconds. --- ## Log Collection Tyto can collect and aggregate logs from multiple sources across all monitored hosts. ### Supported Sources | Source | Description | |--------|-------------| | **Systemd Journal** | System and service logs via journalctl | | **File** | Tail log files with format parsing | | **Docker** | Container stdout/stderr logs | ### Agent Log Configuration Configure log collection in the agent's `config.yaml`: ```yaml agent: logs: enabled: true buffer_size: 1000 flush_interval: 5s journal: enabled: true units: # Empty = all units - nginx.service - docker.service priority: 4 # 0=emerg to 7=debug files: - path: /var/log/nginx/access.log format: nginx - path: /var/log/app/*.log format: json docker: enabled: true containers: [] # Empty = all containers ``` ### Log Query Parameters ``` GET /api/v1/logs?agent_id=web-01&level=error,warn&limit=100 ``` | Parameter | Description | |-----------|-------------| | `agent_id` | Filter by agent | | `source` | Filter by source type (journal, file, docker) | | `source_name` | Filter by source name (unit, filename, container) | | `level` | Comma-separated levels (debug, info, warning, error, fatal) | | `q` | Full-text search in message | | `from`, `to` | Time range (ISO 8601) | | `limit`, `offset` | Pagination | --- ## Troubleshooting
No metrics displayed 1. Check if backend is running: `docker compose ps` 2. Verify volume mounts: `docker inspect sysmon-backend` 3. Check backend logs: `docker compose logs backend`
GPU not detected **AMD GPU** requires: - AMD GPU with amdgpu driver - `/sys/class/drm/card*/device/` accessible - Volume mount: `-v /sys:/host/sys:ro` **NVIDIA GPU** requires: - NVIDIA driver installed on host - `nvidia-smi` available in PATH - For Docker: `--gpus all` or nvidia-container-toolkit **Intel GPU** requires: - Intel GPU with i915 or xe driver - `/sys/class/drm/card*/` accessible - Volume mount: `-v /sys:/host/sys:ro`
Docker containers not showing Ensure Docker socket is mounted: ```yaml volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ```
Systemd services not showing Mount D-Bus socket and ensure the container can access it: ```yaml volumes: - /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro ```
--- ## License MIT License - see [LICENSE](LICENSE) for details. ---
**[Back to top](#tyto)**