Repository navigation
Releases: WeirdBrains/itcmdr
Release list
itcmdr v1.0.0
itcmdr 1.0: self-healing IT for small offices, with no file share needed.
- Fresh install with no share, tested on the Windows VM: server and agent installed without a share or backup folder, the agent enrolled with only
/EnrollToken=and came online, a backup and the restore drill passed on the local backup folder, and no share path appears in any config, report or log. docs/INSTALL.md says how. - Deep-check reminder: the site keeps the date and result of the last
backup drill --deepand shows "Last deep check: N days ago" in the site app (Backup page), warning when it never ran, failed or is older than 90 days. Linked sites send only that date and result to adminsvr (SiteStatus.deep_check_ms/deep_check_result);itcmdr-admin site listand the admin app (Servers) show it and warn after the organization's limit (OrgPolicy.deep_check_max_days, default 90;itcmdr-admin org policy --deep-check-days N, owners only, audited). No migration (stored as settings on both databases). - The agent setup check no longer says that Run now needs the share (the Rust agent takes it over its link).
- README rewritten for 1.0 (what each part is, where to get it, docs, privacy and security).
- Versions 1.0.0 (app and admin app 1.0.0+38).
- Known limits: Windows installers are not Authenticode-signed, the macOS builds are not signed or notarized, and the Android admin app is debug-signed. adminsvr's own backup and restore runbook comes after 1.0 (site backups and the restore drill are covered).
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
itcmdr v0.22.0
The share is retired after the switch to the Rust agent, and backups get a restore drill.
- Share flows retired once a site has run
itcmdr-cli cutover switch --to agent: the server stops rewritingschedule-state.json(written once by the switch) andagent-settings.json(the agents get config over the link), and on-demand runs from the app and CLI go to the Rust agents over the link (RunNow) instead ofrequests\on the share. The PowerShell poller no longer readsrequests\in the agent state (it still keeps the nightly task disabled).itcmdr-cli cutover rollbackbrings all of it back. Sites that have not switched are unchanged. The share stays for backups whenbackup.dirpoints there, the PowerShell checks/plugins and log rotation; old share logs are still read. - Rust agents from 0.22.0 take
RunNowwith plugin*(every installed plugin). Older agents get one request per plugin they reported as installed, so Run now keeps working during a mixed upgrade; an older agent with no reported plugins gets nothing (upgrade it). - Restore drill:
itcmdr-cli backup drill [--deep]copies the newest archive to a temp folder, checks it (signature chain, this server's master key, hash, manifest, schema;--deepdecrypts with the words and checks every file), deletes the copy and records the result (auditbackup.drill). New adminsvr commandbackup.drill(itcmdr-admin backup drill <site>, admin app Restore drill button): the site runs it on-site and reports only ok/failed; adminsvr never sees an archive. Allowed by default for links still on the default allowlist. Monthly restore-test runbook in docs/BACKUP.md. - Fix: after a server upgrade was rolled back, the restored database still showed the upgrade as waiting, so the server staged the same broken release again and looped. The rollback result now marks it failed (Critical
server-upgradealert) and it is not retried. Found by the v0.22.0 VM test. - Admin app desktop builds: Windows (
itcmdr-admin-app-Setup-<v>.exe, built on Windows) and macOS (itcmdr-admin-app-<v>-macos-aarch64.zip, Swift Package Manager, no CocoaPods) are part of every release (docs/RELEASE-LOCAL.md).
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
itcmdr v0.21.0
Self-updating sites: agent and server upgrades with watchdogs and rollback, an update window, approve-once releases from adminsvr, and two-person approval as an organization option (off by default).
- Two-person approval is now an organization setting, off by default (owners only, audited
org.policy;itcmdr-admin org policy --second-approver on|off, admin app Plugins page). It covers every action that needed a second owner/admin before (plugin install/enable/disable from adminsvr) and release approvals. The setting is carried signed in each command (two_person) and checked by the site. Organizations with two or more active owners/admins keep it on through the upgrade (migration). The site settingadminsvr.requireTwoPersonnow defaults to false and means "always require two here". - Releases from adminsvr, approved once: an owner or admin signs a one-time approval of an exact server or agent release (name, version, checksum; two people with the setting on); adminsvr attaches the approvals to
release.rolloutcommands and the site checks them, the checksum and the owner signature before installing and starting the rollout. New RPCsGetOrgPolicy,SetOrgPolicy,ListReleases,ApproveRelease; CLIorg policy,release list|approve|rollout [--now]; admin app Releases list with Approve / Roll out.release.rolloutis off until the site owner allows it. Migration000005_release_approvals(Postgres and SQLite). - Automatic updates, on by default, in an update window:
updates.auto,updates.window(daily 01:00-04:00; daysMon-Fri/Sat,Sun, ranges past midnight belong to their start day),updates.timezone(IANA or local; DST-safe). Upgrades and ring advances start only inside the window; push-now (--now, adminsvrrelease rollout --now) ignores it. Off per site (updates.auto=false) or per machine (agent.upgrades=false). The window can be set from adminsvr (setting.setnow allows these two structured text settings). - Server self-upgrade:
itcmdr-cli upgrade server-start <v> [--now]/server-abort; the server takes a database safety copy, stages the new build and hands it toitcmdr-server-watchdog, which swaps, health-checks and rolls back (restoring the database withupgrade restore-db); failures raise a Criticalserver-upgradealert. Agent releases can require a server version (min_server); the server goes first. - Fixes: pre-release versions compare piece by piece (
pre2 < pre10 < rc1); an agent busy with an upgrade ignores new offers instead of refusing (which paused rollouts); the agent reports the watchdog's result as soon as it appears, not only on the next reconnect;upgrade statusno longer shows a pushed rollout as waiting for the window. - Agent releases: a service-plugin package named
itcmdr-agent-releasewith arelease.toml(version,min_from), signed by an owner key (an admin-signed release installs but cannot be rolled out). Releases are never pushed to agents as plugins. - Rollouts through rings (
agent.ringper machine: 0 = test VM/PC, 1 = one PC, 2 = everything, default 2):itcmdr-cli upgrade start|status|pause|resume|abort. Each ring gets anUpgradeOffer; once every agent in it runs the new version and was seen in the last 10 minutes, it soaks foragent.upgradeSoakMins(60) and the next ring starts. A failed apply or watchdog rollback, or a new Critical alert on a ring machine, pauses the rollout with a Critical alert.agent.upgrades = falseholds a machine (or every machine) back. - The agent checks the offer (server root endorsement that the signer is an owner, the owner's own package signature, every checksum,
min_from, no downgrade), stages it inagent\staged\<version>\and hands it to the newitcmdr-agent-watchdogservice, which swapscurrent\/previous\, waits up toagent.upgradeHealthSecs(300) for the new agent to link to the server and rolls back otherwise; the result is reported after the next connect. Between upgrades the watchdog restarts a stopped agent or one whosehealth.jsonis stale; the agent restarts a stopped watchdog and alerts (watchdog-missing). The watchdog is only replaced by the installer. - Agent installer: the Rust agent now runs from
agent\current\; adds theitcmdr-agent-watchdogservice. - Server watchdog: the server installer adds the
itcmdr-server-watchdogservice (delayed start). The server writeshealth.jsonevery 30 s once gRPC answers and the database opens; the watchdog starts a stopped server and restarts one whose health is stale. It also carries the swap/rollback for server upgrades (used once server upgrades land). - Site app Updates screen: the rollout in progress (ring, soak progress, what holds the ring), Pause/Abort (admin) and Roll out/Resume (owner, signed key only), installed agent releases (admin-signed ones flagged), each machine's ring (changeable), version and last upgrade result, and the rollout history. New RPCs
GetAgentUpgrades,StartAgentUpgrade,PauseAgentUpgrade,ResumeAgentUpgrade,AbortAgentUpgrade. - App: the navigation rail scrolls when the window is shorter than its entries.
- Settings:
agent.ring,agent.upgrades,agent.upgradeSoakMins,agent.upgradeHealthSecs(docs/SETTINGS.md).
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
Windows installers are unsigned (no code-signing certificate yet); the Android admin app APK is debug-signed; macOS builds are not notarized.
itcmdr v0.20.1
The Rust agent takes over: agent config over the link and a gated cutover switch --to agent.
- Agent config over the link (
ConfigUpdate): the cutover state and the machine's agent settings, endorsed by the server root key. The agent stores it inconfig.jsononly when the endorsement checks and re-checks it on every load; a tampered or broken file is deleted, the agent stays report-only, raisesconfig-rejectedand the server resends the config. The server records each agent's acknowledged version (agent_config). itcmdr-cli cutover switch --to agent: refused until the existing gate passes and every machine active in the last two days has a non-revoked Rust agent seen in the last 10 minutes that acknowledged the current config and has Rust-agent parity results with no mismatch. After it, the Rust agent runs plugins for real (not report-only) and the PowerShell agent is retired for scheduled runs, with no fallback (on-demand runs still work until v0.22.0).- Self-heal: in the agent state the Rust agent (and the PowerShell poller) keep the
itcmdr Agent Nightlytask disabled; re-enabling it by hand is undone and alerted (nightly-task-reenabled, raised by whichever heals it first; the poller queues it throughitcmdr-agent alert).itcmdr-cli cutover rollbackhands the nightly back to the task, the agent re-enables it and resolves that alert. A missing or rejectedconfig.jsonnever re-enables the task (only a signedtaskconfig does). A repeatedcutover switch --to agentis a no-op. - PowerShell:
agentcutover state incutover.json,Set-ItcmdrCutover.ps1 -To agent; upgrades keep the task disabled.
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
macOS (Apple silicon: CLI, admin CLI, adminsvr, app, admin app) and Android (admin app APK, debug-signed) builds were added after the first publish, built from the same tag.
itcmdr v0.20.0
Commands, configs and plugins from adminsvr with preview and two-person approval; no CocoaPods.
- Commands down from adminsvr:
setting.set(numbers, switches and times only; never link, auth, path or text settings),schedule.run/pause/resume(opaque schedule ids),plugin.install/enable/disable. Every command can be a dry run: the site answers with before/after and changes nothing. All kinds stay off until the site owner allows them (itcmdr-cli adminsvr allow); restore, keys and auth are never remote. - Two-person approval: plugin commands wait for a second owner or admin, whose key signs the approval; the site checks it itself (
adminsvr.requireTwoPerson, default on, site-only), so a compromised adminsvr cannot skip it (tested). - Global freeze (owners): nothing is sent to any site while it is on.
- Plugin catalog: owners/admins add signed packages to adminsvr (it cannot sign one); sites fetch the package over SiteLink (
FetchPackage, site-signed, only for a sent install command), validate it as for a local install and quarantine a bad one (only a reason code goes up). - Documents up: each site sends its configuration (values only for numbers, switches and times) and its plugin list when they change; status adds disk space and 24 h run/plugin-error/alert summaries.
- Admin CLI:
config show|set,schedule run|pause|resume,plugin catalog|upload|status|push|enable|disable,command show|approve|reject,freeze status|on|off,--dry-run. - itcmdr Admin: server Config and Plugins tabs (preview, then apply), Plugins page (catalog, approvals, freeze), freeze banner, 24 h summaries.
- No CocoaPods: both Flutter apps build their Rust bridge with flutter_rust_bridge native assets (cargokit removed) and use Swift Package Manager on iOS/macOS.
- Fix: command arguments are encoded in key order (two-argument commands could fail the request signature).
- Not in this release: agent settings over the link and
cutover switch --to agent(moved to v0.20.1).
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
v0.19.2
The itcmdr Admin app, push notifications for alerts, service scripts for every platform and a tested container image.
- itcmdr Admin (Flutter; Linux, macOS, Windows, Android): onboarding with a one-time code and the 24 words, every request signed by the device key over pinned TLS (the CLI's client through a Rust bridge), passkey touch prompt for step-up actions (desktop security keys via libfido2's tools), alert inbox with acknowledge/resolve, servers with status, configuration, per-machine versions and "update available", metrics history (6 h to 30 days), commands and remote backup start, user management per role (create, roles, disable, SRE scopes, device approval/revocation, passkey reset), step-up policy (owners), audit verify. No web build (gRPC over TLS sockets needs gRPC-web in browsers). The Android APK is signed with a debug key; iOS builds without signing and is not published.
- Push notifications: adminsvr pushes newly opened alerts (cautious and critical by default) over FCM (Android) and APNs (iOS/macOS) to the devices of users who may see the site. Payloads carry only the opaque site and alert ids and the severity; every send is audited; gone tokens are removed. Off until configured (
ITCMDR_ADMINSVR_FCM_SERVICE_ACCOUNT,ITCMDR_ADMINSVR_APNS_*,ITCMDR_ADMINSVR_PUSH_MIN_SEVERITY); tested against a local stub, not against Google or Apple (no accounts yet). The app shows in-app banners for new alerts; a push-enabled app build needs the Firebase/Apple setup listed in docs/ADMINSVR.md. - Metrics history: adminsvr keeps the status each site sends (numbers and enums only) for 30 days;
ListSiteMetrics,itcmdr-admin site metrics. - Services: systemd (kept), SysV init script (LSB headers, pidfile, start/stop/restart/status) and OpenRC script, chosen by
install.sh --init; macOS LaunchDaemon with install/uninstall scripts in a newitcmdr-adminsvr-<ver>-macos-aarch64.tar.gz; Windows serviceitcmdr-adminsvrwith restart-on-failure in the newitcmdr-adminsvr-Setup-<ver>.exe. New--env-file/ITCMDR_ADMINSVR_ENV_FILE. - Container: the Containerfile and compose file (SQLite by default, Postgres profile) are tested with rootless Podman (
scripts/container-smoke.sh). - Fixes: adminsvr now stops on SIGTERM (it only handled Ctrl-C, so service managers had to kill it); empty push/env-file values no longer fail flag parsing; log files are plain text (no color codes); the container image includes libssl3 (needed by the built-in libpq); the adminsvr package README says SQLite is the default.
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed, the macOS apps are not signed or notarized, and the Android APK is signed with a debug key (sideload only). iOS is build-checked only (not published).
itcmdr v0.19.1
adminsvr on Diesel with SQLite or Postgres, and passkeys / security keys as an optional second factor.
- Database: adminsvr's store moved from sqlx (Postgres only) to Diesel (
MultiConnection) with embedded migrations for both backends.ITCMDR_ADMINSVR_DB_URLpicks it:postgres://…for Postgres,sqlite://<path>(or a path) for SQLite; empty = SQLite at<data dir>/adminsvr.db(mode 0600), the new default for small installs. libpq and SQLite are built in (no system libraries). Databases made by v0.19.0 are picked up as they are. The adminsvr tests run on both backends. - Passkeys (WebAuthn; YubiKeys and other FIDO2 keys) as an optional second factor; the 24-word key stays the signing identity.
itcmdr-admin passkey add|list|remove|reset|lock|unlockandpolicy show|set. adminsvr checks attestation (none,packedself or x5c), RP id, origin, user presence (and verification when required) and the sign count. - Step-up: actions on the owner-editable list (default: role and status changes, user and device enrollment and revocation, key backup retrieval and opt-out, site create/revoke, passkey and policy changes) need a fresh touch from users who have a passkey. The challenge is bound to that exact request (
sha256("itcmdr-stepup/v1" || sha256(method, body) || single-use nonce)), so a touch can't be replayed or used for another request; every assertion, accepted or refused, is in the audit chain.policy set --required-roles ownermakes a passkey mandatory per role. - Unlock:
passkey add --unlock/passkey lockencrypts the CLI's device key with the security key's hmac-secret; every use then needs a touch. - Lost passkey: the user removes it, or an owner/admin resets it (with their own touch; admins not for owners); console
recover-owneralso clears the owner's passkeys. Audited. - The CLI drives security keys through libfido2's tools (
fido2-token,fido2-cred,fido2-assert; device fromITCMDR_FIDO2_DEVICEor the first key found). Platform passkeys (phone, Windows Hello) come with the admin app (v0.19.2). Tested with a software authenticator only: the hardware path (a real YubiKey) is untested in this release. - New adminsvr settings:
ITCMDR_ADMINSVR_RP_ID(default: the host of the public API address) andITCMDR_ADMINSVR_WEB_ORIGINS.
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
itcmdr v0.19.0
adminsvr core: the offsite admin server, the itcmdr-admin CLI and the site-side SiteLink, redacted by default. The SRE app and push move to v0.19.2.
- New
itcmdr-adminsvr(Linux, Postgres): admin API with the site's signed-request auth (itcmdr-keys; device keys certified by the user's 24-word master key), roles owner/admin/sre (new users are sre; admins cannot make or change owners), per-SRE site scopes, device approval, single-use enrollment codes, consoleinitandrecover-owner, and a hash-chained audit of every signed change (audit-verify,itcmdr-admin audit verify). - Encrypted user key backup, on by default: the device key is wrapped with a key derived from the 24 words (XChaCha20-Poly1305) and stored on adminsvr;
itcmdr-admin recoverrestores it on a new device.key-backup offopts out. - SiteLink: the site server dials adminsvr over pinned TLS + mTLS (
itcmdr-cli adminsvr enroll <token>in person on the site;status,unlink). Every message is signed with sequence numbers and acks; heartbeats and an unreachable-site alert on adminsvr. - Redaction on the site, deny by default: only opaque site-scoped IDs, alert codes built from a fixed vocabulary, check ids and plugin names, severity/state, counts and numeric rollups leave the site. No hostnames, IPs, paths, usernames or message text. Display names only with the per-site opt-in
itcmdr-cli adminsvr share-names on. Property tests prove it. - Backups never leave the site: adminsvr sees backup age/size/result and can ask for
backup.start; there is no restore command. Commands (backup.start,alert.ack,alert.resolve) carry the user's signature and the adminsvr root key's, are checked against the site's local allowlist (itcmdr-cli adminsvr allow), the never-remote list and expiry, and are audited on the site. - Site settings
adminsvr.enabled(kill switch, default true) andadminsvr.heartbeatSecs. Settings 51. - Packages:
itcmdr-adminsvr-<ver>-linux-x86_64.tar.gz(binary, systemd unit, install.sh/uninstall.sh, settings example, Containerfile and compose file, untested),itcmdr-admin-<ver>-<os>-<arch>.tar.gz(Linux, macOS) anditcmdr-admin-Setup-<ver>.exe(Windows). Verify with SHA256SUMS; installers are not code-signed yet. - Deferred v0.18 items (agent cutover switch, app runs UI) not included.
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
itcmdr v0.18.0
The Rust agent runs plugins and schedules (report-only), with run reports, artifacts and parity against the nightly.
- Plugin push: the server sends the plugins selected by the new setting
agent.plugins(per machine:all,noneor a comma list of names; defaultall) over the link, endorsed by the root key over the package checksum. The agent verifies the endorsement, name, version and every file checksum before installing, and removes plugins no longer selected or disabled. Each install/removal is reported back; a refused one raisesagent-plugin:<machine>:<name>. - Schedules: enabled schedules that name plugins (and the builtin nightly run) are pushed to the agent, which fires them in the schedule's time zone, also while the server is unreachable; a missed fire runs once at start when the schedule catches up.
itcmdr-cli agent run <machine> <plugin> [--arg k=v](RunNow),agent runs,agent plugins.- Agent runs are always report-only. Reports (stages, results, log lines, artifacts up to 1 MiB each / 4 MiB per run) travel through the durable queue, so offline runs are delivered later, once. Logs go to
plugin-logs/<plugin>/agents/<machine>.jsonl, artifacts to<data>/agent-artifacts/<run>/. A failing run raisesagent-run:<machine>:<plugin>. - Parity: each agent report is compared with the machine's latest nightly checks (36 h) and recorded as
agent:<run>in the parity tables. - New
PrepareRPC: the agent verifies the site CA and root key before enrolling, so a refused root key no longer leaves an enrolled machine on the server (the token is not used). - New
CheckRPC: a revoked agent learns it is revoked (it only saw handshake resets before), logs "enroll it again" and checks only every 15 min instead of reconnecting. - Agent package ships
itcmdr-plugin-ps.exe. Schema 9; settings 49.
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.
itcmdr v0.17.1
Agent certificates renewed over the link, revocation in the handshake, office hours, offline queue.
- Site CA certified: the server root key (certified by the master key) signs the agent site CA (
keys/agent-ca.sig); enrollment tokens carry the root public key and the agent verifies the server's key and the signature before trusting the CA. v0.17.0 tokens still work. - Certificate renewal over the link: new setting
agent.certLifetimeMins(server, default 129600 = 90 days); the agent renews at 2/3 of the lifetime with a new CSR (new TLS key), saves the certificate and reconnects; the replaced certificate is accepted for 24 h.itcmdr-cli agent renew <machine>asks for a renewal at the next heartbeat. - Expiry alerts
agent-cert:<machine>: Cautious under 14 days, Critical under 3 days, resolved by the renewal. - Revoked or replaced client certificates are refused in the TLS handshake (own acceptor with a client verifier that checks the serial against the agents table, reloaded every heartbeat pass and on enroll/renew/revoke).
- Office-hours heartbeat profile:
agent.officeHours(per machine, e.g.Mon-Fri 07:00-18:00): no alert outside the hours, misses counted from the start of the hours. - Offline queue:
itcmdr-agent alert <key> <title> [--level] [--detail] [--resolve]spools an alert; the service queues it with a durable sequence number and delivers it once (server dedupe + ack), also after an outage; capagent.queueMaxMib(default 256), informational items dropped first and the drop reported. - agent.proto:
Renew/AgentAlertfrom the agent,RenewNow/Renewed/bare acks from the server,Welcome.queue_max_mib,EnrollResponse.ca_signature/root_public_key. Schema 8 (agents:cert_issued_ms,prev_cert_fp,prev_serial,prev_until_ms,renew_requested,last_seq).
Built locally (not by Actions). Verify downloads with SHA256SUMS.
Windows installers are not Authenticode-signed and the macOS app is not signed or notarized yet.