- Update clone URL in README quick start - Update install script URLs to Gitea raw format - Update TYTO_REPO to use somegit.dev domain - Update systemd service documentation URL 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tyto
A real-time Linux system monitoring dashboard with multi-device support
Named after Tyto alba, the barn owl — nature's silent, watchful guardian
Features • Quick Start • Multi-Device Setup • Authentication • API • 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)
# Clone the repository
git clone https://somegit.dev/vikingowl/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:
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):
database:
type: sqlite
path: /var/lib/tyto/tyto.db
PostgreSQL (for high availability):
database:
type: postgres
url: postgres://user:pass@localhost:5432/tyto?sslmode=require
Data Retention
Configure metric retention with tiered aggregation:
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:
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:
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Systemd Service Monitoring
Mount the D-Bus socket to enable systemd service monitoring:
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
- Deploy on each host you want to monitor:
# On remote-host-1 (e.g., 192.168.1.100)
docker compose up -d
- Configure CORS (if accessing from a different origin):
The backend allows cross-origin requests by default. Ensure ports are accessible.
- 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).
# Create initial admin user during setup
tyto setup --admin-user admin --admin-pass <password>
# 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:
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 dashboardagents:view,agents:manage- Agent managementalerts:view,alerts:acknowledge,alerts:configure- Alert handlingusers:view,users:manage- User managementroles:view,roles:manage- Role managementmetrics:export,metrics:query- Metrics accesspki: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:
{
"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
# 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
# Backend (Go)
cd backend
go mod download
go run ./cmd/server
# Frontend (SvelteKit)
cd frontend
npm install
npm run dev
Running Tests
# 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
# 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:
# Server installation
curl -fsSL https://somegit.dev/vikingowl/tyto/raw/branch/main/scripts/install.sh | sudo bash
# Agent installation
curl -fsSL https://somegit.dev/vikingowl/tyto/raw/branch/main/scripts/install.sh | \
sudo TYTO_MODE=agent bash
PKI Setup (mTLS)
For secure multi-device deployments, set up mTLS certificates:
# 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:
# /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:
# 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:
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
- Open the Alerts card
- Click "Configure Thresholds"
- Set warning and critical percentages for each metric type
- Click "Save Configuration"
Desktop Notifications
- Enable the "Desktop Notifications" toggle in the Alerts card
- Allow browser notification permission when prompted
- 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:
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
- Check if backend is running:
docker compose ps - Verify volume mounts:
docker inspect sysmon-backend - 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-smiavailable in PATH- For Docker:
--gpus allor 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:
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:
volumes:
- /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:ro
License
MIT License - see LICENSE for details.