clawdie-iso/ADMIN-PANEL.md

549 lines
20 KiB
Markdown
Raw Normal View History

# Clawdie Admin Panel — System Management UI
**Purpose:** bsddialog-based system administration interface for Lumina desktop users
**Philosophy:** Pure shell + bsddialog (no external GUI toolkits), inspired by PC-BSD warden's CLI approach
---
## Overview
**clawdie-admin** is a lightweight terminal UI that lets users manage:
- **Clawdie service** — start/stop, view status
- **Jails** — list, start/stop, open console (jexec)
- **ZFS snapshots** — create, list, restore (inspired by Life-Preserver)
- **System health** — CPU, RAM, disk usage, pool status
- **Logs** — tail service and jail logs
- **Configuration** — change assistant name, timezone, LLM provider
---
## Entry Points
### 1. Lumina Panel Applet (Right-click)
```
Right-click system tray
└─ "Clawdie Admin"
└─ Launches /usr/local/bin/clawdie-admin
```
### 2. CLI (Terminal)
```bash
$ clawdie-admin
# Opens interactive menu
```
### 3. Desktop Launcher
Double-click `~/.local/share/applications/clawdie-admin.desktop` in Lumina file manager.
---
## Menu Structure
### Main Menu
```
┌─ Clawdie Admin Panel ──────────────────────────────────────┐
│ │
│ Quick Status │
│ ├─ Clawdie service: ✓ Running (pid 42315) │
│ ├─ ZFS pool (zroot): 15.2 GB / 100 GB (15% used) │
│ ├─ Memory: 2.3 GB / 8.0 GB (29%) │
│ └─ CPU Load: 0.24 (1 min avg) │
│ │
│ [ System Health ] [ Jails ] [ Snapshots ] │
│ [ Logs ] [ Config ] [ Quit ] │
│ │
└─────────────────────────────────────────────────────────────┘
```
### System Health Submenu
```
┌─ System Health ────────────────────────────────────────┐
│ │
│ CPU Load │
│ │ 1-min: 0.24 │
│ │ 5-min: 0.18 │
│ │ 15-min: 0.12 │
│ │ │
│ Memory Usage │
│ │ Used: 2.3 GB │
│ │ Free: 5.7 GB │
│ │ Cache: 0.8 GB │
│ │ │
│ ZFS Pool: zroot │
│ │ Used: 15.2 GB │
│ │ Free: 84.8 GB │
│ │ Pool health: ✓ ONLINE │
│ │ │
│ Clawdie Service │
│ │ Status: ✓ Running │
│ │ PID: 42315 │
│ │ Memory: 145 MB │
│ │ │
│ [ Back ] │
│ │
└────────────────────────────────────────────────────────┘
```
### Jails Submenu
```
┌─ Clawdie Jails ────────────────────────────────────────┐
│ │
│ (N) Name Status Process Count IP Address │
│ 1) worker Running 4 10.0.0.101 │
│ 2) db Running ✓ Healthy 10.0.0.102 │
│ 3) cms Running ✓ Ready 10.0.0.103 │
│ 4) mgmt Stopped -- 10.0.0.104 │
│ │
│ Manage jail: │
│ [ Boot All ] [ Stop All ] [ Back ] │
│ │
│ Select jail number (1-4) to manage: │
│ >_ │
│ │
└────────────────────────────────────────────────────────┘
# After selecting jail (e.g., "1" for worker):
┌─ Jail: worker ──────────────────────────────────────────┐
│ │
│ Status: ✓ Running │
│ IPv4: 10.0.0.101 │
│ PID: 42350 │
│ Memory: 234 MB │
│ │
│ [ Start ] [ Stop ] [ Restart ] │
│ [ Console (jexec) ] [ Back ] │
│ │
└─────────────────────────────────────────────────────────┘
```
### Snapshots Submenu
```
┌─ ZFS Snapshots ────────────────────────────────────────┐
│ │
│ Snapshot Management │
│ [ Create Snapshot ] │
│ [ List Snapshots ] │
│ [ Restore Snapshot ] │
│ │
│ Auto-Backup Status │
│ │ Last backup: 2026-03-23 18:45 UTC │
│ │ Interval: Daily at 02:00 │
│ │ Retention: 7 days │
│ │ Status: ✓ Enabled │
│ │
│ [ Back ] │
│ │
└────────────────────────────────────────────────────────┘
# After selecting "List Snapshots":
┌─ ZFS Snapshots on zroot ──────────────────────────────┐
│ │
│ Snapshot Created Size │
│ zroot@auto-2026-03-23 2026-03-23 02:00 2.3 GB │
│ zroot@auto-2026-03-22 2026-03-22 02:00 2.1 GB │
│ zroot@manual-20260323_1842 2026-03-23 18:42 1.8 GB │
│ zroot@manual-20260323_1200 2026-03-23 12:00 1.7 GB │
│ │
│ Total snapshots: 4 │
│ Total space: 7.9 GB │
│ │
│ Select snapshot to restore: (or press Back) │
│ >_ │
│ │
└────────────────────────────────────────────────────────┘
# After selecting snapshot:
┌─ Restore zroot@manual-20260323_1842 ──────────────────┐
│ │
│ ⚠ WARNING: This will rollback ZFS to the snapshot │
│ point. All changes since creation will be lost. │
│ │
│ Created: 2026-03-23 18:42 UTC │
│ Size: 1.8 GB │
│ Systems affected: postgres, apps │
│ │
│ [ Confirm Restore ] [ Cancel ] │
│ │
└────────────────────────────────────────────────────────┘
```
### Logs Submenu
```
┌─ System Logs ──────────────────────────────────────────┐
│ │
│ View logs from: │
│ [ Clawdie Service (syslog) ] │
│ [ Clawdie Service (stdout/stderr) ] │
│ [ Worker Jail Console ] │
│ [ Database Jail Console ] │
│ [ System Messages (/var/log/messages) ] │
│ │
│ [ Back ] │
│ │
└────────────────────────────────────────────────────────┘
# After selecting log:
┌─ Clawdie Service Log (last 50 lines) ──────────────────┐
│ │
│ [2026-03-23 23:15:22] Agent startup complete │
│ [2026-03-23 23:15:21] Jails ready: worker, db, cms │
│ [2026-03-23 23:15:18] PostgreSQL health check: OK │
│ [2026-03-23 23:15:15] Nginx config validated │
│ ... │
│ [2026-03-23 23:15:01] rc.d clawdie service start │
│ │
│ [ Refresh ] [ Tail (follow mode) ] [ Back ] │
│ │
└────────────────────────────────────────────────────────┘
```
### Config Submenu
```
┌─ Configuration ────────────────────────────────────────┐
│ │
│ Current Settings │
│ ├─ Assistant Name: Clawdie │
│ ├─ Domain: clawdie.local │
│ ├─ Timezone: Europe/Ljubljana │
│ ├─ LLM Provider: Anthropic │
│ └─ Telegram: ✓ Configured │
│ │
│ [ Change Assistant Name ] │
│ [ Change Timezone ] │
│ [ Change LLM Provider ] │
│ [ Export .env ] │
│ [ View .env (sensitive) ] │
│ [ Back ] │
│ │
└────────────────────────────────────────────────────────┘
```
---
## Implementation (clawdie-admin.sh)
### File Locations
```
/usr/local/bin/clawdie-admin ← wrapper script (user-callable)
/usr/local/libexec/clawdie-admin.sh ← main menu logic (sourced)
/usr/local/libexec/clawdie-lib-admin.sh ← helper functions (jail, snap, log ops)
```
### Wrapper Script
```bash
#!/bin/sh
# /usr/local/bin/clawdie-admin
# Make sure we're running as clawdie user (or via doas for root ops)
if [ "$(id -u)" != 1001 ]; then
# If run as root, switch to clawdie user
if [ "$(id -u)" = 0 ]; then
exec su - clawdie -c "clawdie-admin"
fi
echo "Error: must run as clawdie user or root"
exit 1
fi
# Source main menu
. /usr/local/libexec/clawdie-admin.sh
# Start menu
clawdie_admin_main_menu
```
### Main Menu Function
```bash
#!/bin/sh
# /usr/local/libexec/clawdie-admin.sh
. /usr/local/libexec/clawdie-lib-admin.sh
clawdie_admin_main_menu() {
while true; do
# Refresh status each iteration
STATUS=$(clawdie_admin_quick_status)
CHOICE=$(bsddialog --title "Clawdie Admin Panel" \
--menu "Quick Status:\n$STATUS" 20 70 0 \
"1" "System Health" \
"2" "Jails" \
"3" "Snapshots" \
"4" "Logs" \
"5" "Configuration" \
"0" "Quit" \
2>&1 >/dev/tty)
case $CHOICE in
1) clawdie_admin_health ;;
2) clawdie_admin_jails ;;
3) clawdie_admin_snapshots ;;
4) clawdie_admin_logs ;;
5) clawdie_admin_config ;;
0) break ;;
*) ;;
esac
done
}
clawdie_admin_quick_status() {
# Returns 4-line status string for main menu display
# Check if clawdie service running
if service clawdie status > /dev/null 2>&1; then
PID=$(service clawdie status | grep -oP 'pid \K\d+' || echo "?")
SERVICE_STATUS="✓ Running (pid $PID)"
else
SERVICE_STATUS="✗ Stopped"
fi
# ZFS pool usage
POOL_USAGE=$(zfs list -H -o used,available zroot 2>/dev/null | awk '{
used = $1 / 1024 / 1024 / 1024
avail = $2 / 1024 / 1024 / 1024
total = used + avail
pct = int(used / total * 100)
printf "%.1f GB / %.1f GB (%d%%)", used, total, pct
}')
# Memory usage
MEM=$(free -m | grep "^Mem:" | awk '{
used = $3
total = $2
pct = int(used / total * 100)
printf "%.1f GB / %.1f GB (%d%%)", used/1024, total/1024, pct
}')
# CPU load
LOAD=$(uptime | sed 's/.*load average: //' | awk '{print $1}')
echo "Clawdie: $SERVICE_STATUS"
echo "ZFS pool (zroot): $POOL_USAGE"
echo "Memory: $MEM"
echo "CPU Load: $LOAD (1 min)"
}
```
### Helper Library Functions
```bash
#!/bin/sh
# /usr/local/libexec/clawdie-lib-admin.sh
# Jail operations
clawdie_jail_list() {
jls -N name hostname state ip4.addr 2>/dev/null | grep -E "^(worker|db|cms|mgmt)" || echo "No jails found"
}
clawdie_jail_status() {
local jail=$1
jls -j "$jail" state 2>/dev/null || echo "unknown"
}
clawdie_jail_start() {
local jail=$1
service jail onestart "$jail" 2>&1 | tail -5
}
clawdie_jail_stop() {
local jail=$1
service jail onestop "$jail" 2>&1 | tail -5
}
clawdie_jail_console() {
local jail=$1
jexec "$jail" /bin/sh
}
# ZFS operations
clawdie_snapshot_create() {
local label=$1
local snapshot="zroot@manual-$(date +%Y%m%d_%H%M)"
zfs snapshot "$snapshot" 2>&1
echo "Created: $snapshot"
}
clawdie_snapshot_list() {
zfs list -t snapshot -r zroot 2>/dev/null | grep "^zroot" || echo "No snapshots"
}
clawdie_snapshot_restore() {
local snapshot=$1
bsddialog --title "Confirm Restore" \
--yesno "Restore $snapshot? This will rollback all changes since creation." 0 0
if [ $? -eq 0 ]; then
zfs rollback "$snapshot" 2>&1 | head -20
echo "Rollback complete. System restart recommended."
fi
}
# Log operations
clawdie_log_service() {
tail -50 /var/log/clawdie.log 2>/dev/null || echo "No log found"
}
clawdie_log_jail() {
local jail=$1
jexec "$jail" tail -50 /var/log/messages 2>/dev/null || echo "No jail log"
}
# Config operations
clawdie_config_read_env() {
# Read current .env without exposing secrets
grep -E "^(ASSISTANT_NAME|AGENT_DOMAIN|TZ|LLM_PROVIDER)" \
/home/clawdie/clawdie-ai/.env 2>/dev/null || echo "Config not found"
}
clawdie_config_change_name() {
bsddialog --title "Change Assistant Name" \
--inputbox "Enter new assistant name:" 0 0 "$CURRENT_NAME" 2>&1 | \
xargs -I {} sed -i '' "s/^ASSISTANT_NAME=.*/ASSISTANT_NAME={}/" \
/home/clawdie/clawdie-ai/.env
}
```
---
## Usage Examples
### Example 1: Start Worker Jail
```bash
# User: Jails → select "1" (worker) → [Start]
clawdie_jail_start worker
# Output: "Jail worker started"
```
### Example 2: View Recent Logs
```bash
# User: Logs → [Clawdie Service] → shows tail -50 /var/log/clawdie.log
tail -50 /var/log/clawdie.log
```
### Example 3: Create Manual Snapshot
```bash
# User: Snapshots → [Create Snapshot]
clawdie_snapshot_create "manual"
# Output: "Created: zroot@manual-20260323_2145"
```
---
## Integration with Lumina
### Tray Applet
**Binary:** `/usr/local/libexec/clawdie-tray-applet` (shell script)
```bash
#!/bin/sh
# Updates tray icon every 5 seconds
RUNNING_ICON="/usr/local/share/icons/clawdie-running.png"
STOPPED_ICON="/usr/local/share/icons/clawdie-stopped.png"
while true; do
if service clawdie status > /dev/null 2>&1; then
echo "ICON:$RUNNING_ICON"
echo "LABEL:Clawdie"
else
echo "ICON:$STOPPED_ICON"
echo "LABEL:Clawdie (offline)"
fi
sleep 5
done
```
**Right-click binding:** `Exec=/usr/local/bin/clawdie-admin`
---
## Permissions & Security
### User (clawdie) Operations
- Jail status queries: via `jls` (unprivileged)
- Logs: read `/var/log/clawdie.log` (user-owned)
- Config: read `.env` (user-owned)
### Privileged Operations (via doas)
- Jail start/stop: requires root via `doas service jail ...`
- ZFS snapshot/rollback: requires root via `doas zfs ...`
- System restart: requires root via `doas shutdown ...`
**doas Setup (automatic in firstboot.sh):**
```bash
# /etc/doas.conf
permit nopass clawdie as root cmd /usr/local/libexec/clawdie-lib-admin.sh
permit nopass clawdie as root cmd /usr/sbin/service
permit nopass clawdie as root cmd /usr/sbin/zfs
permit nopass clawdie as root cmd /usr/bin/killall
```
---
## Accessibility
- **Keyboard navigation:** bsddialog supports tab/arrow keys, Enter
- **High contrast:** Inherits Lumina theme settings
- **No mouse required:** All functions accessible via keyboard
- **Screen reader:** Standard bsddialog output readable by screen readers
---
## Performance Considerations
- **Startup:** <200 ms (pure shell, no Java/Python startup overhead)
- **Refresh rate:** 5-second poll for status (minimal CPU)
- **Memory:** <5 MB footprint
- **Concurrency:** Lock file prevents multiple instances (`/tmp/clawdie-admin.lock`)
---
## Testing Checklist
- [ ] `clawdie-admin` launches from Lumina tray
- [ ] `clawdie-admin` launches from terminal
- [ ] System Health displays correct CPU/memory/disk stats
- [ ] Jails submenu lists all jails (worker, db, cms)
- [ ] Can toggle jail start/stop with doas confirmation
- [ ] Can open jail console via jexec
- [ ] Snapshots create/list/restore work with doas
- [ ] Logs display correctly (tailed, not truncated)
- [ ] Config display matches current .env
- [ ] No secrets logged to console
- [ ] Multiple concurrent instances prevented (lock file)
- [ ] Menu navigation works with keyboard only
---
## Future Enhancements
1. **Backup scheduling UI** — configure daily/weekly backups
2. **Network config** — change IP addresses, DNS
3. **Service management** — start/stop nginx, PostgreSQL within jails
4. **Metrics export** — export system stats to Grafana
5. **Terminal multiplexing** — tmux split for multiple jails open simultaneously