5.8 KiB
shepherd-config
Configuration parsing and validation for Shepherd.
Overview
This crate handles loading, parsing, and validating the TOML configuration that defines what entries are available, when they're available, and for how long. It provides:
- Schema definitions - Raw configuration structure as parsed from TOML
- Policy objects - Validated, ready-to-use policy structures
- Validation - Detailed error messages for misconfiguration
- Hot reload support - Configuration can be reloaded at runtime
Configuration Format
Shepherd uses TOML for configuration. Here's a complete example:
config_version = 1
[service]
socket_path = "/run/shepherdd/shepherdd.sock"
data_dir = "/var/lib/shepherdd"
default_max_run_seconds = 1800 # 30 minutes default
# Internet connectivity check (optional)
[service.internet]
check = "https://connectivitycheck.gstatic.com/generate_204"
interval_seconds = 10
timeout_ms = 1500
# Global volume restrictions
[service.volume]
max_volume = 80
allow_unmute = true
# Default warning thresholds (seconds before expiry)
[[service.default_warnings]]
seconds_before = 300 # 5 minutes
severity = "info"
[[service.default_warnings]]
seconds_before = 60 # 1 minute
severity = "warn"
[[service.default_warnings]]
seconds_before = 10
severity = "critical"
message_template = "Closing in {remaining} seconds!"
# Entry definitions
[[entries]]
id = "minecraft"
label = "Minecraft"
icon = "minecraft"
kind = { type = "snap", snap_name = "mc-installer" }
[entries.internet]
required = true
[entries.availability]
[[entries.availability.windows]]
days = "weekdays"
start = "15:00"
end = "18:00"
[[entries.availability.windows]]
days = "weekends"
start = "10:00"
end = "20:00"
[entries.limits]
max_run_seconds = 1800 # 30 minutes per session
daily_quota_seconds = 7200 # 2 hours per day
cooldown_seconds = 600 # 10 minutes between sessions
[[entries]]
id = "educational-game"
label = "GCompris"
icon = "gcompris-qt"
kind = { type = "process", command = "gcompris-qt" }
[entries.availability]
always = true # Always available
[entries.limits]
max_run_seconds = 3600 # 1 hour
Usage
Loading Configuration
use shepherd_config::{load_config, parse_config, Policy};
use std::path::Path;
// Load from file (typically ~/.config/shepherd/config.toml)
let policy = load_config("config.toml")?;
// Parse from string
let toml_content = std::fs::read_to_string("config.toml")?;
let policy = parse_config(&toml_content)?;
// Access entries
for entry in &policy.entries {
println!("{}: {:?}", entry.label, entry.kind);
}
Entry Kinds
Entries can be of several types:
# Regular process
kind = { type = "process", command = "/usr/bin/game", args = ["--fullscreen"] }
# Snap application
kind = { type = "snap", snap_name = "mc-installer" }
# Steam game (via Steam snap)
kind = { type = "steam", app_id = 504230 }
# Virtual machine (future)
kind = { type = "vm", driver = "qemu", args = { disk = "game.qcow2" } }
# Media playback (future)
kind = { type = "media", library_id = "movies" }
# Custom type
kind = { type = "custom", type_name = "my-launcher", payload = { ... } }
Time Windows
Time windows control when entries are available:
[entries.availability]
[[entries.availability.windows]]
days = "weekdays" # or "weekends", "all"
start = "15:00"
end = "18:00"
[[entries.availability.windows]]
days = ["sat", "sun"] # Specific days
start = "09:00"
end = "21:00"
Limits
Control session duration and frequency:
[entries.limits]
max_run_seconds = 1800 # Max duration per session
daily_quota_seconds = 7200 # Total daily limit
cooldown_seconds = 600 # Wait time between sessions
Internet Requirements
Entries can require internet connectivity. When the device is offline, those entries are hidden.
[service.internet]
check = "https://connectivitycheck.gstatic.com/generate_204"
interval_seconds = 300
timeout_ms = 1500
[entries.internet]
required = true
# Optional per-entry override:
# check = "tcp://1.1.1.1:53"
Validation
The configuration is validated at load time. Validation catches:
- Duplicate entry IDs - Each entry must have a unique ID
- Empty commands - Process entries must specify a command
- Invalid time windows - Start time must be before end time
- Invalid thresholds - Warning thresholds must be less than max run time
- Negative durations - All durations must be positive
- Unknown kinds - Entry types must be recognized (unless Custom)
use shepherd_config::{parse_config, ConfigError};
let result = parse_config(toml_str);
match result {
Ok(policy) => { /* Use policy */ }
Err(ConfigError::ValidationFailed { errors }) => {
for error in errors {
eprintln!("Config error: {}", error);
}
}
Err(e) => eprintln!("Failed to load config: {}", e),
}
Hot Reload
Configuration can be reloaded at runtime via the service's ReloadConfig command or by sending SIGHUP to the service process. Reload is atomic: either the new configuration is fully applied or the old one remains.
Active sessions continue with their original time limits when configuration is reloaded.
Key Types
Policy- Validated policy ready for the core engineEntry- A launchable entry definitionAvailabilityPolicy- Time window rulesLimitsPolicy- Duration and quota limitsWarningPolicy- Warning threshold configurationVolumePolicy- Volume restrictions
Design Philosophy
- Human-readable - TOML is easy to read and write
- Strict validation - Catch errors at load time, not runtime
- Versioned schema -
config_versionenables future migrations - Sensible defaults - Minimal config is valid
Dependencies
toml- TOML parsingserde- Deserializationchrono- Time typesthiserror- Error types