diff --git a/.gitignore b/.gitignore index 6c7ec55..1a394a1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ __pycache__/ # Runtime files status.json +config.local.json # IDE .vscode/ diff --git a/README.md b/README.md index 16a3fbf..4576a78 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,17 @@ A minimalist system status monitor that uses ASCII emotes to display server health on an old phone. -![Status: Optimal](https://img.shields.io/badge/status-(%20%5E___%5E)-brightgreen) +![Status: Optimal]() ## Why? Turn an old phone (with its OLED screen) into a glanceable ambient display for your home server. Instead of graphs and numbers, see a happy face `( ^_^)` when things are good, and a worried face `( o_o)` when they're not. +## TODO + +- Figure out way to update installation in /opt/kao when git updates. Maybe run a git pull on service startup? +- Think about ways of implementing noises. + ## Features - **OLED-optimized** — Pure black background, saves battery @@ -34,24 +39,24 @@ Open http://localhost:5100 on your phone (use Fully Kiosk Browser for best resul ## Status Faces -| State | Emote | Meaning | -|-------|-------|---------| -| Optimal | `( ^_^)` | All systems healthy | -| Warning | `( o_o)` | Something needs attention | -| Critical | `( x_x)` | Immediate action required | -| Notify | `( 'o')` | Transient notification | -| Sleeping | `( -_-)zzZ` | Sleep mode active | -| Disconnected | `( ?.?)` | Can't reach server | +| State | Emote | Meaning | +| ------------ | ----------- | ------------------------- | +| Optimal | `( ^_^)` | All systems healthy | +| Warning | `( o_o)` | Something needs attention | +| Critical | `( x_x)` | Immediate action required | +| Notify | `( 'o')` | Transient notification | +| Sleeping | `( -_-)zzZ` | Sleep mode active | +| Disconnected | `( ?.?)` | Can't reach server | ## Built-in Detectors -| Detector | Monitors | -|----------|----------| -| **disk_space** | Disk usage on all drives | -| **cpu** | CPU utilization | -| **memory** | RAM usage | -| **service** | Whether processes are running | -| **network** | Host reachability (ping) | +| Detector | Monitors | +| -------------- | ----------------------------- | +| **disk_space** | Disk usage on all drives | +| **cpu** | CPU utilization | +| **memory** | RAM usage | +| **service** | Whether processes are running | +| **network** | Host reachability (ping) | ## Configuration @@ -59,19 +64,19 @@ Edit `config.json` to enable/disable detectors and set thresholds: ```json { - "aggregator_url": "http://localhost:5100", - "detectors": [ - { - "name": "disk_space", - "enabled": true, - "script": "detectors/disk_space.py", - "env": { - "CHECK_INTERVAL": "300", - "THRESHOLD_WARNING": "85", - "THRESHOLD_CRITICAL": "95" - } - } - ] + "aggregator_url": "http://localhost:5100", + "detectors": [ + { + "name": "disk_space", + "enabled": true, + "script": "detectors/disk_space.py", + "env": { + "CHECK_INTERVAL": "300", + "THRESHOLD_WARNING": "85", + "THRESHOLD_CRITICAL": "95" + } + } + ] } ``` @@ -91,6 +96,7 @@ curl -X POST http://localhost:5100/event \ - `ttl` — Auto-expire after N seconds (for heartbeat pattern) Clear an event: + ```bash curl -X POST http://localhost:5100/clear \ -d '{"id": "my_check"}' @@ -131,15 +137,15 @@ automation: ## API Reference -| Endpoint | Method | Description | -|----------|--------|-------------| -| `/` | GET | Web UI | -| `/status` | GET | Current state as JSON | -| `/events` | GET | List all active events | -| `/event` | POST | Register an event | -| `/clear` | POST | Clear an event by ID | -| `/sleep` | POST | Enter sleep mode | -| `/wake` | POST | Exit sleep mode | +| Endpoint | Method | Description | +| --------- | ------ | ---------------------- | +| `/` | GET | Web UI | +| `/status` | GET | Current state as JSON | +| `/events` | GET | List all active events | +| `/event` | POST | Register an event | +| `/clear` | POST | Clear an event by ID | +| `/sleep` | POST | Enter sleep mode | +| `/wake` | POST | Exit sleep mode | ## Personality diff --git a/install.sh b/install.sh index 4772a76..8a8d4b9 100644 --- a/install.sh +++ b/install.sh @@ -1,6 +1,7 @@ #!/bin/bash # Kao Installation Script -# Installs to /opt/kao and sets up systemd service +# Clones from git to /opt/kao and sets up systemd service +# Updates automatically via git pull on service restart set -e @@ -17,7 +18,6 @@ echo " Kao Installer" echo "====================================" echo "Install directory: $INSTALL_DIR" echo "Running as user: $CURRENT_USER" -echo "Source: $SCRIPT_DIR" echo "" # Check if running as root @@ -40,34 +40,58 @@ if ! command -v python3 &> /dev/null; then exit 1 fi -# Check source files exist -if [ ! -f "$SCRIPT_DIR/kao.py" ]; then - echo "Error: Source files not found in $SCRIPT_DIR" - echo "Run this script from the Kao repository directory" +# Check for git +if ! command -v git &> /dev/null; then + echo "Error: git not found" + echo "Install with: sudo apt install git" exit 1 fi -# Create install directory -echo "[1/5] Creating install directory..." -mkdir -p "$INSTALL_DIR" -cp "$SCRIPT_DIR/aggregator.py" "$INSTALL_DIR/" -cp "$SCRIPT_DIR/kao.py" "$INSTALL_DIR/" -cp "$SCRIPT_DIR/index.html" "$INSTALL_DIR/" -cp "$SCRIPT_DIR/config.json" "$INSTALL_DIR/" -cp "$SCRIPT_DIR/requirements.txt" "$INSTALL_DIR/" -cp -r "$SCRIPT_DIR/detectors" "$INSTALL_DIR/" +# Get git remote URL from source repo +if [ -d "$SCRIPT_DIR/.git" ]; then + REPO_URL=$(git -C "$SCRIPT_DIR" remote get-url origin 2>/dev/null || echo "") +fi -# Set ownership before venv creation +if [ -z "$REPO_URL" ]; then + echo "Error: Could not detect git remote URL" + echo "Run this script from within the Kao git repository" + exit 1 +fi + +echo "Git remote: $REPO_URL" +echo "" + +# Remove existing installation if present +if [ -d "$INSTALL_DIR" ]; then + echo "[1/6] Removing existing installation..." + systemctl stop kao.service 2>/dev/null || true + rm -rf "$INSTALL_DIR" +else + echo "[1/6] No existing installation found" +fi + +# Clone repository (as root since /opt requires elevated permissions) +echo "[2/6] Cloning repository..." +git clone "$REPO_URL" "$INSTALL_DIR" + +# Set ownership to target user (so they can git pull, create venv, etc.) chown -R "$CURRENT_USER:$CURRENT_GROUP" "$INSTALL_DIR" +# Create local config for production customization +echo "[3/6] Creating local config..." +if [ ! -f "$INSTALL_DIR/config.local.json" ]; then + cp "$INSTALL_DIR/config.json" "$INSTALL_DIR/config.local.json" + echo "Created config.local.json - edit this for production settings" +fi + # Create virtual environment as target user -echo "[2/5] Creating virtual environment..." +echo "[4/6] Creating virtual environment..." sudo -u "$CURRENT_USER" python3 -m venv "$INSTALL_DIR/venv" sudo -u "$CURRENT_USER" "$INSTALL_DIR/venv/bin/pip" install --upgrade pip -q sudo -u "$CURRENT_USER" "$INSTALL_DIR/venv/bin/pip" install -r "$INSTALL_DIR/requirements.txt" -q -# Create systemd service -echo "[3/5] Creating systemd service..." +# Create systemd service with git pull on start +echo "[5/6] Creating systemd service..." cat > "$SERVICE_FILE" << EOF [Unit] Description=Kao - System Status Monitor @@ -78,6 +102,7 @@ Type=simple User=$CURRENT_USER Group=$CURRENT_GROUP WorkingDirectory=$INSTALL_DIR +ExecStartPre=/usr/bin/git -C $INSTALL_DIR pull --ff-only ExecStart=$INSTALL_DIR/venv/bin/python $INSTALL_DIR/kao.py Restart=always RestartSec=5 @@ -87,12 +112,9 @@ WantedBy=multi-user.target EOF # Reload systemd and enable service -echo "[4/5] Enabling service..." +echo "[6/6] Enabling and starting service..." systemctl daemon-reload systemctl enable kao.service - -# Start service -echo "[5/5] Starting Kao..." systemctl start kao.service echo "" @@ -103,9 +125,11 @@ echo "" echo "Kao is now running at http://$(hostname -I | awk '{print $1}'):5100" echo "" echo "Commands:" -echo " sudo systemctl status kao # Check status" -echo " sudo systemctl restart kao # Restart" -echo " sudo systemctl stop kao # Stop" -echo " sudo journalctl -u kao -f # View logs" +echo " sudo systemctl status kao # Check status" +echo " sudo systemctl restart kao # Restart (auto-pulls latest code)" +echo " sudo systemctl stop kao # Stop" +echo " sudo journalctl -u kao -f # View logs" +echo "" +echo "Config: $INSTALL_DIR/config.local.json" +echo "To update: push changes to git, then 'sudo systemctl restart kao'" echo "" -echo "Config file: $INSTALL_DIR/config.json" diff --git a/kao.py b/kao.py index d98a4df..6d2b447 100644 --- a/kao.py +++ b/kao.py @@ -242,10 +242,18 @@ def main(): else: config_path = sys.argv[1] - # Resolve config path + # Resolve config path - prefer config.local.json if it exists + base_dir = Path(__file__).parent config_path = Path(config_path) + if not config_path.is_absolute(): - config_path = Path(__file__).parent / config_path + # Check for local config override first + local_config = base_dir / "config.local.json" + if local_config.exists() and config_path.name == "config.json": + config_path = local_config + print(f"Using local config: {config_path}") + else: + config_path = base_dir / config_path if not config_path.exists(): print(f"Config file not found: {config_path}")