FIRST STABLE RELEASE of CannonadeCommand — every pre-release folded into this one.
Shoots your commands where you need them — and that very nicely.
Start-plan orchestration
- Per-container start plan: declare dependencies ("start the app after its database"); the engine computes parallel start stages (Kahn topological sort) and releases each stage only when the previous one is READY, not merely running.
- Readiness probes per container: running (with grace period), TCP port, HTTP check (2xx/3xx, no redirects followed), log-line match, or a command executed inside the container.
- Failure policies per node: abort dependents, continue, or degrade.
- Dependencies on containers outside the plan are resolved implicitly by the engine at stage-build time — nothing is written into your stored plan, so disabling a referenced container sticks.
- Watchdog: auto-restart on crash or unhealthy state, rate-capped per hour, with honest pause-artifact grace (a container fresh out of pause gets 90s before "unhealthy" alarms).
- Time schedules: start/stop/restart at fixed times, per weekday.
- One-click apply runs the whole plan in dependency order; per-container start delay supported.
Live resource limits
- CPU limit (expressed as CpuQuota against the stored period — dockerd refuses NanoCpus when a quota is stored), RAM limit (with the required MemorySwap companion; unremovable-live limits are set to unlimited honestly) — applied via
docker update, no container restart, CI-proven against a real dockerd. - CPU pinning with the host's real topology (from /proc/cpuinfo, affinity-independent), including P/E-core detection on Intel hybrid CPUs; the picker adapts to the machine automatically.
- The editors read the applied values BACK from Docker and show a green verified line ("✓ Angewendet · RAM … · template ok") or the exact refusal — plus a diagnostics card with the engine's recent limit operations.
- Limits are dual-written into the Unraid template so a container re-create keeps them.
Bandwidth limits (kernel-safe)
- Upload: tbf shaper on the container's interface inside its own network namespace.
- Download: pure netfilter policing (iptables hashlimit on the container's INPUT chain). A tc ingress qdisc is never created — the
sch_ingressmodule freezes some Unraid kernels, and a unit test enforces that the download path cannot even emit a tc command. - Works identically for bridge, ipvlan and macvlan networks (no host-side veth needed — the rules live inside the container's netns, entered via nsenter).
- Quirk compensation, all CI-proven: legacy iptables (≥ 1.8.12) applies byte rates as bits → detected via
iptables --versionand compensated ×8; hashlimit's minimum-burst rule honoured (burst = 2× rate); explicit byte units (the kb/mb prefixes parse differently across builds). - Immediate apply: saving kicks the monitor (no 30s tick wait); the editor stays open and shows the LIVE rule read back from the container — target state, actual tc + netfilter state, and the monitor's last apply attempt with the exact error if any. A silent no-op is impossible.
- The shaping interface is auto-detected from the container's default route (Settings can override); shaping is skipped for host-network / shared-netns containers.
The Docker tab
- Actions column between application and version: WebUI, log, edit, restart, pause/resume, stop/start as icon buttons (two rows, tooltips), plus a "…" expander with the container's Tailscale-WebUI / project / support / donate / read-me links — all harvested positionally from Unraid's own page registrations, never guessed.
- Badges for state (with transition feedback and honest unhealthy-grace), network, container IP and LAN IP (click to copy), ports, volumes (narrow column with hover marquee), update status (up-to-date green, update amber pill, force-update accent) and per-container ID/image info.
- Live CPU / RAM / BW value badges with a filled gear each (accent-coloured when a limit is set) opening the matching editor.
- Card (grid) view with the same badges, actions and limit editors; container logos and live gauges.
- Instant paint: the last engine state is cached locally and rows are decorated the moment they appear; the live fetch corrects moments later.
- The native toggle row above the table is hidden from the first paint; the gear lives in the table header (menu: list/grid, basic/advanced, rainbow + icon-colour toggles, filter, badge selection, and the running UI/engine versions).
The Plugins tab
- Unraid's Plugins tab gets the same treatment (toggleable per section in the settings): author and version badges, a green/amber status pill, tinted icons and pill buttons for check/update/remove — accent or rainbow colours, enhanced in place on the native table.
Theming & settings
- One accent colour for everything — badges, toggles, buttons, action icons, gears — with automatic black/white text by luminance; or rainbow mode with an editable 8-colour palette, per-reload rotation (toggleable) and reset.
- Cross-origin settings sync: every UI setting is mirrored into the engine config (per-key merge, no clobbering) and adopted on every origin — IP, hostname and domain see the same configuration, and it survives cleared browser data.
- Settings page with logo hero, embedded colour picker (no popup), density and column defaults, bandwidth interface, notifications (Unraid + webhook) and the limits diagnostics card.
Engine & safety
- Single Go daemon on a local unix socket; the UI talks through a same-origin PHP proxy with a strict path allowlist; writes carry Unraid's csrf token (form-body — the only variant emhttp accepts).
- The proxy exposes only read + lifecycle verbs — never raw Docker create/exec/build.
- Plan and config persist on the flash and survive uninstall/reinstall; the installer migrates configs from the old plugin name automatically.
- CI on every push: package build, lint, and three hardware-truth proofs — real
docker updatelimit assertions, the policing rule applied + verified in a live container netns, and a real throughput measurement through the rule.
Branding
- The plugin is CannonadeCommand: cannon logo, white README banner (generated from vector paths — no font dependencies), full canonical README, and the settings hero with logo, wordmark and claim.