# Insight Updater - Project Prompt ## Overview Build a self-hosted update orchestration tool for Windows (CAU/WSUS) and Linux servers via WinRM/SSH. Web UI to manage servers, trigger updates, monitor progress live via WebSocket. ## Target Stack - **Backend**: FastAPI + Python 3.11+, SQLAlchemy + SQLite/PostgreSQL, structlog, python-winrm, paramiko - **Frontend**: Vue 3 + TypeScript + Vite, Pinia, VueUse, Tailwind CSS, Socket.io client - **Infra**: Docker Compose (backend, frontend, db, redis), Traefik labels for reverse proxy - **CI/CD**: Gitea Actions / Woodpecker CI for build & deploy to monitoring (10.0.2.105) ## Core Features 1. **Server Inventory** - Add/edit/delete servers (Windows/WinRM, Linux/SSH, CAU-Cluster) 2. **Live Update Streaming** - WebSocket log stream with progress, status per node 3. **CAU Cluster Orchestration** - Trigger `Invoke-CauRun`, show per-node phases 4. **Linux Patch Management** - `apt/dnf/yum update` via SSH with sudo 5. **Audit Log** - Structured JSON logs: who, when, what server, outcome 5. **Health Checks** - `/health` endpoint, WinRM/SSH connectivity test 6. **LDAP-ready Auth** - JWT tokens, LDAP config schema prepared, local admin fallback ## Non-Goals - No WSUS/SCCM replacement, no approval workflows - No agent deployment (agentless WinRM/SSH only) - No multi-tenancy / RBAC beyond admin/user ## Success Criteria - Add server → see "Online/Offline", last patch date - Click "Update" → live WebSocket log stream → final status Success/Failed - CAU: Trigger cluster update, see per-node Pre/Post/Reboot phases - Linux: Add SSH creds, trigger update, see apt/dnf output - `docker compose up -d` → all healthy in <5 min on fresh VM - Deploy to monitoring (10.0.2.105) via `git push` + CI works - LDAP config schema exists, service stub wired, functional later ## Verification Commands ```bash curl -f http://localhost:8000/health curl -f http://localhost:3000/ # frontend docker compose ps # all healthy ``` ## Deployment Target - **Host**: monitoring.insight.local (10.0.2.105) - **User**: b0rbor4d (sudo via Vaultwarden) - **Docker**: Podman/Docker Compose v2 - **Reverse Proxy**: Traefik (labels on compose services) - **Git Remote**: ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git ## Security - Credentials encrypted at rest (Fernet/AES-GCM, key from env) - WinRM: NTLM/Kerberos, HTTPS preferred, Cert validation configurable - SSH: Key-based auth preferred, password fallback encrypted - JWT: RS256, short expiry, refresh token rotation - Audit log: immutable append-only (SQLite WAL / PG) ## Project Structure ``` ~/projects/insight-updater/ ├── backend/ │ ├── app/ │ │ ├── api/ # FastAPI routes │ │ ├── core/ # config, security, db │ │ ├── models/ # SQLAlchemy models │ │ ├── schemas/ # Pydantic schemas │ │ ├── services/ # business logic (winrm, ssh, cau, audit) │ │ ├── websocket/ # Socket.io / FastAPI WS handlers │ │ └── main.py │ ├── tests/ │ ├── Dockerfile │ ├── requirements.txt │ └── pyproject.toml ├── frontend/ │ ├── src/ │ │ ├── components/ │ │ ├── views/ │ │ ├── stores/ │ │ ├── api/ │ │ └── main.ts │ ├── Dockerfile │ ├── package.json │ └── vite.config.ts ├── docker-compose.yml ├── docker-compose.prod.yml ├── .env.example ├── .gitignore ├── README.md ├── AGENTS.md └── PROMPT.md ``` ## Key Libraries - `fastapi`, `uvicorn`, `sqlalchemy[asyncio]`, `alembic` - `python-winrm[kerberos]`, `paramiko`, `asyncssh` - `python-socketio[asyncio]`, `redis`, `structlog` - `cryptography`, `python-jose[cryptography]`, `passlib[bcrypt]` - `pydantic-settings`, `pydantic[email]` - `pytest`, `pytest-asyncio`, `httpx` ## Environment Variables (.env.example) ```env # Core APP_ENV=development SECRET_KEY=change-me-32-chars-min ENCRYPTION_KEY=change-me-32-chars-base64 JWT_ALGORITHM=RS256 JWT_PRIVATE_KEY_PATH=/app/keys/private.pem JWT_PUBLIC_KEY_PATH=/app/keys/public.pem # Database DATABASE_URL=sqlite+aiosqlite:///./data/app.db # DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/updater # Redis REDIS_URL=redis://redis:6379/0 # WinRM WINRM_TRANSPORT=ntlm WINRM_CERT_VALIDATION=ignore # LDAP (stub) LDAP_ENABLED=false LDAP_URI=ldaps://dc.insight.local:636 LDAP_BIND_DN=CN=svc_updater,OU=Services,DC=insight,DC=local LDAP_BIND_PASSWORD= LDAP_USER_SEARCH_BASE=OU=Users,DC=insight,DC=local LDAP_USER_FILTER=(sAMAccountName={username}) # Frontend VITE_API_URL=http://localhost:8000 VITE_WS_URL=ws://localhost:8000 ``` ## Development Workflow ```bash # Local dev cd backend && pip install -e . && uvicorn app.main:app --reload cd frontend && npm install && npm run dev # Docker dev docker compose up -d --build # Tests cd backend && pytest cd frontend && npm run test ``` ## Remote Deploy (monitoring) ```bash # On monitoring host git clone ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git cd insight-updater cp .env.example .env # fill secrets docker compose -f docker-compose.prod.yml up -d --build ```