# GuruRMM Session Log - 2026-04-01 ## Session Summary Major review and update session for the GuruRMM project. Verified all infrastructure references, fixed several issues, and implemented the on-demand site-code-based installer system. ### Key Accomplishments 1. **Infrastructure audit** - Verified all references across the gururmm-agent project docs 2. **Identified active repo** - `azcomputerguru/gururmm` (53 commits) is active, not `guru-rmm` (2 commits, documentation copy) 3. **SSH key deployed** - Generated ed25519 key on DESKTOP-0O8A1RL, deployed to 172.16.3.30 via plink 4. **Hardcoded credentials removed** - Replaced in 3 Python scripts with SOPS vault calls 5. **API route verification** - Compared docs against actual source (65 routes found) 6. **Project docs updated** - Fixed 5 discrepancies across 4 documentation files 7. **NPM proxy host added** - `rmm.azcomputerguru.com` was missing from Nginx Proxy Manager, causing TLS errors 8. **On-demand installer system** - Designed and implemented site-code-based installers (no API keys in install flow) ### Key Decisions - Site codes (e.g., SWIFT-CLOUD-6910) used as the sole identifier for installers, not API keys - New install endpoints at root level `/install/:site_code/*` (not under `/api/`) to be fully public - Embedded config reuses existing binary-patching mechanism, just puts site_code in the api_key field - Agent WS auth already recognizes site codes -- zero transport changes needed - Old `?key=` endpoints preserved for backward compatibility --- ## Infrastructure ### GuruRMM Server (172.16.3.30) - **OS:** Ubuntu 22.04 LTS - **SSH:** user `guru`, ed25519 key from DESKTOP-0O8A1RL deployed - **API:** Port 3001 (GuruRMM Rust/Axum server) - **ClaudeTools API:** Port 8001 (FastAPI, separate service) - **Nginx:** Reverse proxy on port 80, serves dashboard from /var/www/gururmm/dashboard - **WebSocket:** /ws proxied to 3001 with upgrade headers - **CI/CD webhook:** /webhook/ proxied to port 9000 - **Database:** PostgreSQL 14 on port 5432, database `gururmm`, user `gururmm` ### NPM (Nginx Proxy Manager) - 172.16.3.20:7818 - **Container:** On Jupiter - **Version:** v2.13.5 (v2.14.0 available) - **7 Proxy Hosts configured:** - connect.azcomputerguru.com -> 172.16.3.30:3002 - emby.azcomputerguru.com -> 172.16.2.99:8096 - git.azcomputerguru.com -> 172.16.3.20:3000 - plexrequest.azcomputerguru.com -> 172.16.3.31:5055 - rmm-api.azcomputerguru.com -> 172.16.3.30:80 - rmm.azcomputerguru.com -> 172.16.3.30:80 [NEW - added this session] - sync.azcomputerguru.com -> 172.16.3.20:8082 - unifi.azcomputerguru.com -> 172.16.3.28:8443 ### Credentials Used - **GuruRMM Server SSH:** guru@172.16.3.30 (password from vault: `infrastructure/gururmm-server.sops.yaml`) - **NPM Login:** mike@azcomputerguru.com / r3tr0gradE99\! (from vault: `services/npm.sops.yaml`) - **NPM Alt:** admin@azcomputerguru.com / Window123\!@# - **Cloudflare API Token:** U1UTbBOWA4a69eWEBiqIbYh0etCGzrpTU4XaKp7w (from NPM vault entry) - **GuruRMM Dashboard:** admin@azcomputerguru.com / GuruRMM2025 (from vault: `projects/gururmm/dashboard.sops.yaml`) - **GuruRMM DB:** PostgreSQL at 172.16.3.30:5432, db `gururmm`, user `gururmm` (password in vault: `projects/gururmm/database.sops.yaml`) - **GuruRMM JWT Secret:** In vault at `projects/gururmm/api-server.sops.yaml` - **Entra SSO App:** ID `18a15f5d-7ab8-46f4-8566-d7b5436b84b6`, client secret expires 2026-12-21 ### SSH Key Deployed - **Machine:** DESKTOP-0O8A1RL (Windows 11) - **Key:** C:\Users\guru\.ssh\id_ed25519 (ed25519, comment: guru@DESKTOP-0O8A1RL) - **Fingerprint:** SHA256:ZVbowRHhxPX47eKy9FyMwjvIKPzTf3Dwx3BCsBrP4ds - **Deployed to:** guru@172.16.3.30:~/.ssh/authorized_keys (via plink with vault password) - **Verified:** Key-based auth works (PasswordAuthentication=no test passed) --- ## Gitea Repos | Repo | Status | Notes | |------|--------|-------| | `azcomputerguru/gururmm` | ACTIVE | 53 commits, primary development repo | | `azcomputerguru/guru-rmm` | INACTIVE | 2 commits, restructured documentation copy | | `azcomputerguru/guru-connect` | Related | ScreenConnect-like remote desktop for GuruRMM | --- ## Code Changes ### Commit d3a047e - "feat: Site-code-based on-demand agent installers" **Pushed to:** `azcomputerguru/gururmm` main branch **Files changed (4 files, +625, -92):** 1. **server/src/api/install.rs** - 5 new public endpoint handlers: - `site_install_landing` - HTML landing page with OS detection - `site_install_script_windows` - PowerShell install script - `site_install_script_linux` - Bash install script - `download_site_windows` - Pre-configured Windows binary - `download_site_linux` - Pre-configured Linux binary - Refactored `build_configured_binary()` shared helper - `validate_site_code()` helper 2. **server/src/main.rs** - Route registration at root level: - `/install/:site_code` (landing page) - `/install/:site_code/windows` (PS script) - `/install/:site_code/linux` (bash script) - `/install/:site_code/download/windows` (binary) - `/install/:site_code/download/linux` (binary) 3. **dashboard/src/pages/Sites.tsx** - EnrollmentModal overhaul: - URLs now use site codes instead of API keys - Added public install link with copy button - Removed API key dependency from enrollment flow - Simplified handleEnrollDevices (no key regeneration needed) 4. **agent/src/config.rs** - Added `#[serde(alias = "site_code")]` to api_key field ### Project Doc Updates (earlier, in claudetools repo) Updated 4 files in `projects/gururmm-agent/`: - Fixed `/api/agents/{id}/stats` -> `/api/agents/stats` - Removed bogus `/logs` endpoint references - Clarified `claude_task` is a new command type (not existing) - Added active Gitea repo reference - Added WebSocket command delivery notes - Verified all use `/api/` not `/api/v1/` ### Credential Cleanup (earlier, in claudetools repo) - Created `projects/gururmm-agent/scripts/vault_utils.py` - shared vault helper - Updated `check_record_counts.py` - DB password from vault - Updated `create_jwt_token.py` - JWT secret from vault - Updated `test_gururmm_api.py` - API creds from vault, password masked in output --- ## API Route Summary (65 total from source) Key routes: - `POST /api/auth/login` - JWT login - `GET/POST /api/clients` - Client CRUD - `GET/POST /api/sites` - Site CRUD - `GET/POST /api/agents` - Agent management - `POST /api/agents/:id/command` - Send command (delivered via WebSocket) - `GET /ws` - WebSocket for agent connections - `GET /health` - Health check - NEW: `/install/:site_code/*` - Public installer endpoints Full route list documented in plan file at `C:\Users\guru\.claude\plans\rippling-marinating-pebble.md` --- ## Settings Fix `~/.claude/settings.json` was missing `permissions.defaultMode: bypassPermissions`. Fixed to: ```json { "autoUpdatesChannel": "latest", "permissions": { "defaultMode": "bypassPermissions" }, "skipDangerousModePermissionPrompt": true, "voiceEnabled": true } ``` --- ## Pending / Next Steps 1. **Build and deploy** - Commit is pushed but needs to be built on the server (Rust toolchain not on this Windows machine). CI/CD webhook at 172.16.3.30/webhook/build may handle this automatically. 2. **Test installer endpoints** - Once deployed, test `/install/SITE-CODE/download/windows` end-to-end 3. **HTML escaping** - Code review noted landing page uses `format!()` without HTML escaping for site_name/client_name. Low risk (admin-controlled) but worth hardening. 4. **Rate limiting** - Public install endpoints have no rate limiting. Future hardening. 5. **AD2 connectivity** - Hostname doesn't resolve from DESKTOP-0O8A1RL. Need IP or DNS fix to verify agent deployment target. 6. **GuruRMM agent integration** - The claude_task command type from gururmm-agent project still needs to be integrated into the actual agent codebase. --- ## Reference - **Vault paths:** `infrastructure/gururmm-server.sops.yaml`, `projects/gururmm/api-server.sops.yaml`, `projects/gururmm/database.sops.yaml`, `projects/gururmm/dashboard.sops.yaml`, `services/npm.sops.yaml` - **Nginx config on server:** `/etc/nginx/sites-enabled/gururmm` - **Dashboard build:** React/Vite, served from `/var/www/gururmm/dashboard` - **Agent binaries:** `/var/www/gururmm/downloads/` (served by download endpoints) - **Plan file:** `C:\Users\guru\.claude\plans\rippling-marinating-pebble.md` --- ## Update: 20:00 - Continued Session ### Additional Accomplishments 1. **Command management system** - Added cancel, delete, and clear history for commands - `POST /api/commands/:id/cancel` - Cancel pending/running commands - `DELETE /api/commands/:id` - Delete any command - `DELETE /api/commands` - Bulk clear finished commands - Dashboard buttons for cancel (pending/running), delete (all), clear history - Cancelled status badge (orange/amber) 2. **Dashboard metrics made clickable** - Total Agents -> /agents - Online -> /agents?status=online - Offline -> /agents?status=offline - Errors -> /agents?status=error - Recent Activity items link to /agents/:id - Quick Actions replaced with navigation cards (View Agents, Add Client, Deploy Agent, Command History) - Agents page supports ?status= URL param for deep-linking 3. **Dark theme restoration** - Root cause: `npm run build` was silently failing (missing @rollup/rollup-linux-x64-gnu native module) - All previous deploys were using stale dist/ from before our changes - Fixed with `rm -rf node_modules package-lock.json && npm install` - Vite strips `class="dark"` from index.html during build -- using `sed` post-build to inject it - Dark CSS variables defined in index.css `.dark` block 4. **Premium design overhaul** - Added Google Fonts: JetBrains Mono (branding/nav) + Plus Jakarta Sans (body) - Branded sidebar: GURURMM logo icon + "MISSION CONTROL" subtitle in JetBrains Mono - Uppercase monospace nav labels with wider tracking - Richer dark theme with cyan/teal accents (--primary: 199 89% 48%) - Card hover border glow effect (hover:border-[hsl(var(--primary))]/30) - Custom dark scrollbar styling - Login page branded header matching sidebar - SSO button themed with CSS variables 5. **Server tooling fixes** - Installed missing npm dependencies on 172.16.3.30 - Node.js v20.20.0 confirmed working - Cargo/Rust toolchain at ~/.cargo/bin/cargo ### Git Commits (gururmm repo) | Commit | Description | |--------|-------------| | d3a047e | feat: Site-code-based on-demand agent installers | | 24d4417 | feat: Command cancel, delete, and clear history | | b5626c0 | feat: Make dashboard metrics clickable with navigation | | cc4b9b7 | fix: Restore dark theme and fix Tailwind v4 class compatibility | | 6ace258 | fix: Dark theme persistence - add class to index.html, post-build inject | | defeb01 | design: Premium dark theme overhaul with branded sidebar | ### Build & Deploy Process (reference) ```bash # On 172.16.3.30 as guru: cd /home/guru/gururmm git pull origin main # Build server cd server && source ~/.cargo/env && cargo build --release sudo systemctl stop gururmm-server sudo cp target/release/gururmm-server /opt/gururmm/gururmm-server sudo systemctl start gururmm-server # Build agent binaries sudo bash /opt/gururmm/build-agents.sh # Build dashboard cd /home/guru/gururmm/dashboard npm run build # CRITICAL: Inject dark class post-build (Vite strips it) sed -i 's///' dist/index.html sudo rm -rf /var/www/gururmm/dashboard/* sudo cp -r dist/* /var/www/gururmm/dashboard/ ``` ### Nginx Config Updated Added `/install/` location block to proxy to Rust server (was being caught by SPA fallback): ```nginx location /install/ { proxy_pass http://127.0.0.1:3001; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } ``` ### Known Issues 1. **Stashed local changes on server** - `git stash list` shows uncommitted work from before our session (simplified API client, modified WS handler, removed SSO/policies/alerts code). This stash represents a different development direction. Need to decide whether to incorporate or discard. 2. **Tailwind v4 class compatibility** - `no-underline` and `text-inherit` are Tailwind v3 classes. Replaced with `[text-decoration:none]` and `[color:inherit]` arbitrary property syntax. 3. **Dark theme post-build injection** - Vite + @tailwindcss/vite strips `class="dark"` and inline `