Introduces docs/manager/ with two design documents: - README.md: high-level architecture for bm, a single-binary operational control plane that ships as both a direct CLI and a long-running `bm server` exposing an HTTP API and embedded web UI. Covers the product model, distribution and packaging strategy, agentless SSH cluster management, and a phased delivery plan (Phase 1 manager foundation, Phase 2 CLI, Phases 3-4 progressive mc replacement). Implementation-level subsystems, task model, storage, and repository layout are kept in an appendix so the high-level design reads cleanly. - phase1-web-ui.md: wireframe-level web UI design for the first release, scoped to the two operator journeys that only bm can serve — deploying a new Buckit cluster on fresh hosts, and migrating an existing MinIO deployment in place via binary swap. Includes screen catalog, supporting operational surfaces, an out-of-scope list that defers to the per-cluster Buckit console for data-plane operations, and appendices covering the MinIO compatibility surface and the package install path.
49 KiB
Buckit Manager — Phase 1 Web UI Design
Background
The Buckit Manager (bm) is the operational control plane for Buckit
deployments. The full design — single binary with CLI, HTTP API, and embedded
web UI frontends; agentless SSH orchestration; durable task model — is
described in README.md. This document covers the web UI for
the first phase of that design.
Problem and scope
The MinIO ecosystem has no operator-friendly cluster manager. mc admin
exposes some cluster-scoped operations (upgrade, restart, decommission) but
is awkward to drive and doesn't help with installation or deployment at all.
The per-cluster Buckit web console — served by the buckit binary itself —
covers in-cluster operations like bucket browsing, IAM, and metrics.
Everything else, including bootstrap and deploy, falls to hand-rolled
Ansible or shell scripts.
bm fills that gap. The console is the layer inside a cluster; bm
is the layer around it. Phase 1 invests in the two things only bm
can do: produce a new cluster, and migrate from MinIO.
Purpose
This document specifies the Phase 1 web UI for bm server. It is scoped to two
primary user wizards:
- Deploy a new Buckit cluster to a set of fresh hosts.
- Migrate an existing MinIO deployment to Buckit via in-place binary swap.
Once a cluster exists, the UI also provides the surfaces to operate it: cluster list, cluster detail, node detail, and a tasks center.
This is a wireframe-level specification. It defines screens, layout regions, primary components, and state transitions. It does not prescribe visual styling or final copy.
Audience
Operators deploying Buckit to bare metal or VMs over SSH, and operators migrating from MinIO. Single local admin account; no multi-user workflows.
Site Map
/
├── /welcome first-run, no clusters exist
├── /clusters cluster list (default landing after onboarding)
├── /clusters/new wizard: deploy a new Buckit cluster
├── /clusters/migrate wizard: migrate from MinIO (in-place)
├── /clusters/:id cluster detail
│ ├── /overview health, capacity, version, recent activity
│ ├── /nodes node table
│ ├── /nodes/:nodeId per-node detail
│ ├── /services service controls (start/stop/rolling restart)
│ ├── /tasks cluster-scoped tasks
│ └── /settings cluster-scoped settings (SSH creds, version pin)
├── /tasks global task center
├── /tasks/:id task detail + live log
├── /settings manager settings (admin, TLS, audit)
└── /login local admin login
Both wizards share /clusters/new and /clusters/migrate as separate routes
but reuse the same underlying step components where possible (node entry,
discovery, preflight, deploy log).
Global Chrome
All authenticated pages outside the wizards share the same shell.
┌────────────────────────────────────────────────────────────────────────────┐
│ [Buckit Manager] Cluster: [prod-east ▾] [⟳ 2 tasks] [admin ▾]│
├──────────┬─────────────────────────────────────────────────────────────────┤
│ │ │
│ Clusters │ │
│ Tasks │ {page content} │
│ Settings │ │
│ │ │
│ ───── │ │
│ Docs ↗ │ │
│ v0.1.0 │ │
└──────────┴─────────────────────────────────────────────────────────────────┘
- Top bar: product name, active cluster selector (also acts as a breadcrumb when inside a cluster), running-task badge (click → task center), user menu.
- Left sidebar: top-level navigation. Collapsible on small viewports.
- Task badge: animated when ≥1 task is
running. Hover shows a 3-item popover with the most recent active tasks.
The wizards (/clusters/new, /clusters/migrate) replace the global chrome
with a wizard-specific chrome (see below) to keep focus on the linear flow.
Wizard Chrome
┌────────────────────────────────────────────────────────────────────────────┐
│ Deploy a new Buckit cluster [✕ Save & exit] │
├────────────────────────────────────────────────────────────────────────────┤
│ ① Basics — ② Nodes — ③ Discover — ④ Topology — ⑤ Preflight — … │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ {step content area} │
│ │
├────────────────────────────────────────────────────────────────────────────┤
│ [← Back] [Save draft] [Next →]│
└────────────────────────────────────────────────────────────────────────────┘
- Stepper: current step is bold; completed steps are clickable to revisit; future steps are disabled until prerequisites are met.
- Save & exit: persists the draft cluster row and returns to
/clusters. Drafts are visible in the cluster list with aDraftbadge. - Save draft: explicit save without exit (auto-save also fires on every step transition).
- The wizard never blocks navigation away mid-step — leaving stores partial state.
Screen Catalog
Screen 0 — Login
┌─────────────────────────────────────┐
│ Buckit Manager │
│ │
│ Username [____________________] │
│ Password [____________________] │
│ │
│ [ Sign in ] │
│ │
│ First time? See setup guide ↗ │
└─────────────────────────────────────┘
- Local admin only in Phase 1.
- Failed login: inline error under the form, no enumeration of which field was wrong.
- After login, redirect target depends on state:
- 0 clusters →
/welcome - ≥1 cluster →
/clusters
- 0 clusters →
Screen 1 — Welcome / First Run
Shown when the manager has no clusters and no drafts. This is the entry point for both journeys.
┌─────────────────────────────────────────────────────────────────────┐
│ Welcome to Buckit Manager │
│ │
│ Let's get your first cluster running. │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ 🟦 │ │ 🟧 │ │
│ │ Deploy a new cluster │ │ Migrate from MinIO │ │
│ │ │ │ │ │
│ │ Install Buckit on fresh │ │ Replace an existing │ │
│ │ hosts and form a new │ │ MinIO deployment with │ │
│ │ cluster over SSH. │ │ Buckit on the same │ │
│ │ │ │ disks (in-place swap). │ │
│ │ [ Get started → ] │ │ [ Get started → ] │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
│ │
│ Need help? See the install guide ↗ │
└─────────────────────────────────────────────────────────────────────┘
- Two equally-weighted entry cards.
- "Migrate from MinIO" card includes a small
In-placechip to set expectations on the strategy.
Screen 2 — Clusters List
Default landing page after at least one cluster (or draft) exists.
┌────────────────────────────────────────────────────────────────────────────┐
│ Clusters [+ New ▾] │
│ ├ New cluster │
│ └ Migrate from MinIO │
├────────────────────────────────────────────────────────────────────────────┤
│ NAME NODES VERSION HEALTH LAST ACTIVITY STATUS │
│ prod-east 6 v1.0.0 ● Healthy 12m ago Active │
│ staging 4 v1.0.0 ● Healthy 2h ago Active │
│ prod-west-new — — ○ — 5m ago Draft │
│ legacy-migrate 8 v1.0.0 ⚠ Degraded just now Migrating│
└────────────────────────────────────────────────────────────────────────────┘
- Row click → cluster detail.
- Draft rows: click resumes the wizard at the last completed step.
- Migrating rows: link goes to the running migration wizard.
+ Newis a split button so both flows are one click from this page.- Filter chips above table:
All / Active / Draft / Migrating / Failed.
New Cluster Wizard
Route: /clusters/new. Eight steps.
N1 — Basics
Cluster name [prod-east_____________________]
Description [Customer-facing production_____]
Intended use ◉ Production ○ Staging ○ Dev/Test
Buckit version [v1.0.0 (latest stable) ▾]
- Name validation: DNS-safe, unique within the manager.
- Version selector lists known release tags from the manager's release index. An advanced toggle reveals "Custom URL" for air-gapped installs.
N2 — Add Nodes
Add hosts [Paste list]
┌───────────────────────────────────────────────────────────┐
│ HOSTNAME / IP SSH PORT LABEL (optional) │
│ [node1.example.com_____] [22___] [_________________] ✕│
│ [node2.example.com_____] [22___] [_________________] ✕│
│ [+ Add row] │
└───────────────────────────────────────────────────────────┘
SSH credentials
○ Use SSH agent (recommended)
◉ Upload private key [ Choose file ] (no key uploaded)
○ Password [____________________]
SSH user [buckit____________________]
Privilege escalation ☑ Use sudo (passwordless)
- "Paste list" opens a textarea accepting one host per line; parses into rows.
- Credentials are entered once per wizard; per-node overrides available via a row expander.
- "Next" runs an SSH reachability probe in parallel and shows per-row
status pills (
✓ Reachable/✗ Auth failed/✗ Timeout). Cannot proceed with any failing rows except by removing them.
N3 — Discovery
Discovering nodes… ▓▓▓▓▓▓▓▓▓░░░ 6 / 8 complete
NODE OS CORES RAM DISKS STATUS
node1.example.com Ubuntu 24.04 16 64Gi 12 × 16Ti ✓ Done
node2.example.com Ubuntu 24.04 16 64Gi 12 × 16Ti ✓ Done
node3.example.com Ubuntu 24.04 16 64Gi 12 × 16Ti ⟳ …
...
node8.example.com — — — — ✗ Timeout
[Retry]
- Per-node row expands to show: kernel version, NIC + advertised speed,
free space per disk, time skew vs manager, listening ports, whether a
prior
buckitorminiobinary/service was detected. - A node with detected existing services shows a
⚠ Existing servicechip and the user must explicitly acknowledge "stop and replace" or remove the node. - Discovery is a backend task — the page is a live view of that task. Closing the tab does not stop it.
N4 — Topology
The most opinionated step. The UI computes a default layout and lets the operator adjust.
Proposed topology
Pool 1
Nodes 8
Drives/node 12 (□ select drives)
Set size 16 (recommended for 8×12 layout)
Parity EC:4 (◉ default ○ EC:2 ○ EC:3 ○ EC:6 ○ EC:8)
Usable ~864 Ti out of 1.15 Pi raw
[+ Add another pool]
Disk selection (click "select drives" above to override)
┌──────────────────────────────────────────────────────────┐
│ NODE DRIVES │
│ node1 ☑ /dev/sda ☑ /dev/sdb … ☐ /dev/sdm (boot) │
│ node2 ☑ /dev/sda ☑ /dev/sdb … │
└──────────────────────────────────────────────────────────┘
⚠ Boot drives are excluded by default.
ℹ Parity EC:4 tolerates loss of up to 4 drives per set.
- Real-time recompute: changing parity updates usable capacity and tolerance.
- Validation: drive count per node must be uniform within a pool; set size must divide total drive count; mount paths must be writable (verified by discovery).
- Advanced disclosure for: storage class config, custom mount path template, per-pool networking interface.
N5 — Preflight
Running preflight checks…
CHECK NODES RESULT
SSH reachability 8 / 8 ✓ Pass
Sudo (passwordless) 8 / 8 ✓ Pass
Time sync (skew < 1s) 8 / 8 ✓ Pass
Free space on selected drives 8 / 8 ✓ Pass
Inter-node port reachability 8 / 8 ✓ Pass
↳ Verified ports: 9000, 9001
DNS / hostname resolution 7 / 8 ⚠ Warning
↳ node5 cannot resolve node8.example.com
Package manager available (dnf) 8 / 8 ✓ Pass
buckit-1.0.0.rpm reachable ✓ Pass
↳ https://github.com/buckit-io/buckit/releases/...
Existing buckit package 0 / 8 ✓ Pass
Existing minio service 1 / 8 ⚠ Warning
↳ node3 has minio installed but not running
Conflicting listeners on 9000/9001 8 / 8 ✓ Pass
Kernel ulimit (nofile ≥ 65536) 8 / 8 ✓ Pass
[Re-run] [Continue with warnings]
- Failures block; warnings require acknowledgment to continue.
- Per-row expansion shows raw output captured from the check command.
N6 — Review
Review your plan
[Download plan ⤓]
Cluster: prod-east (v1.0.0)
8 nodes · 1 pool · 96 drives · EC:4 · ~864 Ti usable
Install method: dnf install (RHEL 9 detected on all 8 nodes)
[Override for individual nodes…]
Systemd unit (provided by buckit-1.0.0.rpm)
┌──────────────────────────────────────────────────────────┐
│ [Unit] │
│ Description=Buckit Object Storage │
│ After=network-online.target │
│ ... │
│ EnvironmentFile=/etc/default/minio │
│ ExecStart=/usr/local/bin/buckit server $MINIO_OPTS \ │
│ $MINIO_VOLUMES │
│ User=buckit │
│ Group=buckit │
└──────────────────────────────────────────────────────────┘
Environment file written by manager (/etc/default/minio)
┌──────────────────────────────────────────────────────────┐
│ MINIO_ROOT_USER=… (auto-generated, shown post-deploy) │
│ MINIO_ROOT_PASSWORD=… │
│ MINIO_VOLUMES="https://node{1...8}.example.com/data/... │
│ MINIO_OPTS="--console-address :9001" │
└──────────────────────────────────────────────────────────┘
ℹ The unit, binary, and buckit user/group come from the package.
The manager writes only the env file at /etc/default/minio (same path
used by migrated nodes — they remain byte-identical at the config
layer). The path and MINIO_* var names are kept MinIO-compatible.
What will happen
1. Manager fetches buckit-1.0.0.rpm from GitHub Release (one-time, cached)
2. scp the rpm to each node (~3s/node parallel)
3. ssh node 'dnf install -y /tmp/buckit-1.0.0.rpm'
Package provides: /usr/local/bin/buckit,
/lib/systemd/system/buckit.service,
buckit user and group
4. Manager writes /etc/default/minio with cluster values
5. systemctl daemon-reload && enable --now buckit
6. Wait for cluster health-ready (timeout 5m)
☑ I have backed up any existing data on selected drives.
- "Download plan" exports the full plan as a YAML file for offline review.
- Root credentials are generated server-side and revealed only on the Done screen.
N7 — Deploy
Deploying prod-east ● Running · started 1m23s ago
Overall progress ▓▓▓▓▓▓▓░░░░░ 62 %
NODE STATE ELAPSED LAST EVENT
node1 ✓ Service healthy 1m05s Started buckit.service
node2 ✓ Service healthy 1m08s Started buckit.service
node3 ⟳ Starting service 58s systemctl start buckit
node4 ⟳ Writing config 42s Wrote /etc/buckit/buckit.env
node5 ⟳ Installing binary 21s Extracted to /usr/local/bin
node6 ⟳ Installing binary 20s Extracted to /usr/local/bin
node7 ⟳ Downloading 15s Fetching v1.0.0 (45 MiB)
node8 ⟳ Downloading 15s Fetching v1.0.0 (45 MiB)
Live log [Filter: all ▾] [⏸ Pause]
┌──────────────────────────────────────────────────────────────────┐
│ 12:03:18 node1 ✓ systemctl start buckit │
│ 12:03:19 node1 ✓ health probe http://localhost:9000/minio/health│
│ 12:03:20 node2 ✓ systemctl start buckit │
│ 12:03:21 node3 $ systemctl daemon-reload │
│ ... │
└──────────────────────────────────────────────────────────────────┘
[Cancel deploy]
- Log stream via SSE/WebSocket from the task engine.
- Per-node row click filters log to that node.
- "Cancel deploy" triggers a controlled abort that stops in-flight steps but does not roll back completed nodes (manual cleanup required; surfaced in a banner with a follow-up "Tear down what was installed" task).
N8 — Done
✓ prod-east is up
Console URL https://node1.example.com:9000
Root username admin [Copy]
Root password s3cr3t-generated-value-here [Copy] [Reveal]
Recommended next step
bm alias set prod-east https://node1.example.com:9000 admin <password>
[Copy]
Quick checks
● 8 / 8 nodes healthy
● 1 / 1 pool online
● Read/write smoke test passed
[Go to cluster overview]
- Root credentials shown exactly once; subsequent visits replace with "Credentials previously revealed at · [Rotate]".
- "Quick checks" runs three lightweight probes; failures here surface a banner with a "Run remediation" task.
MinIO Migration Wizard
Route: /clusters/migrate. Nine steps. Strategy is in-place binary swap
only.
M1 — Basics
Same as N1, with the addition of a banner explaining the in-place model and its tradeoffs:
ℹ In-place migration
Buckit will stop minio.service on each node, install the buckit binary
alongside the existing minio binary, and start a new buckit.service that
reads the same /etc/default/minio env file and the same data drives. The
on-disk format (xl.meta, .minio.sys/) is unchanged and no data is copied.
Your existing MinIO config is preserved as-is:
· /etc/default/minio — not modified
· MINIO_* env vars — read directly by Buckit
· .minio.sys/ on disks — read directly by Buckit
· TLS certs, KMS, IAM — picked up unchanged
Expect a brief write-unavailable window during cutover on each node. A
rollback option is available until you click "Finalize" at the end of the
wizard; rollback simply re-enables minio.service.
M2 — Add Nodes (or Import)
Same component as N2 with one extra affordance at the top:
[Import nodes from a running MinIO alias]
Alias [prod ▾] or mc alias [https://_______] [AK] [SK]
[Probe]
- Probing
mc admin info <alias>reveals the existing pool layout and node hostnames; the user confirms before populating the host table. - After import, SSH credentials are still required (the manager talks to hosts directly).
M3 — Discovery + MinIO Detection
Identical to N3, but each row's detail panel additionally reports:
node1.example.com
MinIO binary /usr/local/bin/minio v2024-12-01
MinIO service minio.service (active, enabled)
MinIO env /etc/default/minio
MINIO_VOLUMES="https://node{1...8}:9000/data/disk{1...12}"
MINIO_ROOT_USER=…
MINIO_OPTS="--console-address :9001"
Detected pools 1 pool, 8×12 drives, EC:4
- All eight nodes must report a consistent MinIO topology, or the wizard blocks with an explanatory diff view.
M4 — Snapshot
Snapshot of current MinIO state
Buckets 142 [View list ▾]
Largest logs-archive (412 Ti)
With versioning 38
With lifecycle rules 21
With object lock 4
IAM
Users 17
Groups 3
Policies (custom) 11
Service accounts 42
STS sessions (skipped — short-lived)
Bucket-level config
Bucket policies 57
Notification configs 9
Lifecycle rules 21
Replication targets 3 ⚠ Review
⚠ Replication targets detected
This cluster replicates to external targets. Buckit will preserve the
configuration; the targets must remain reachable post-migration.
[Re-run snapshot] [Download snapshot ⤓]
- Snapshot is captured via the MinIO admin API using the existing root credentials (collected in M2 import or M3 detection if not already known).
- The snapshot is stored as a versioned artifact in the manager DB and referenced by the migration task. It is also used to validate post-cutover.
M5 — Plan
Migration plan
Install method: dnf install (RHEL 9 detected on all nodes;
minio package installed via rpm)
For each node, in sequence:
1. Wait for cluster quorum (other nodes must be healthy)
2. systemctl stop minio
3. scp buckit-1.0.0.rpm to /tmp/ on the node
4. dnf install -y /tmp/buckit-1.0.0.rpm
(minio package is NOT removed — kept installed for rollback)
5. systemctl disable minio
6. systemctl enable --now buckit
Buckit's unit reads /etc/default/minio (same env file as MinIO)
7. Wait for node-healthy probe (timeout 2m)
8. Wait for cluster-healthy probe (timeout 5m) before next node
What is NOT touched on any node:
· /etc/default/minio — env file kept as-is, read by buckit.service
(the buckit package does not ship this file)
· /etc/minio/ — TLS certs, KMS config kept as-is
· .minio.sys/ — on-disk cluster state kept as-is
· /data/disk* — data drives untouched
· minio package — installed and disabled; removed only on Finalize
Rolling order
◉ Sequential (safest)
○ Two at a time (faster, requires EC parity ≥ 2)
Estimated downtime per node ~30–90 s
Estimated total migration time ~12 min (8 nodes × ~90 s)
Rollback
Until you click "Finalize" on step 9, a [Rollback] button remains
available. Rollback per node is symmetric: stop buckit, disable
buckit.service, re-enable minio.service. The env file, certs, and
on-disk state are unchanged throughout, so rollback is fast and safe.
☑ I understand each node will briefly stop serving writes during cutover.
M6 — Preflight
Same component as N5, with MinIO-specific checks added:
MinIO admin API reachable on all nodes 8 / 8 ✓ Pass
Current MinIO cluster healthy ✓ Pass
xl.meta format version compatible ✓ Pass
.minio.sys/ readable on all drives 8 / 8 ✓ Pass
/etc/default/minio present and readable 8 / 8 ✓ Pass
Package manager available (dnf) 8 / 8 ✓ Pass
buckit-1.0.0.rpm reachable ✓ Pass
minio installed via package manager 8 / 8 ✓ Pass
↳ Required for clean "dnf remove minio" on Finalize.
Tarball-installed minio falls back to manual cleanup.
No package conflicts (minio ↔ buckit) 8 / 8 ✓ Pass
↳ Verified buckit package does not claim /etc/default/minio
Root credentials valid ✓ Pass
No in-flight admin operations ✓ Pass
↳ No active healing, decommission, or rebalance jobs
- A failing "current cluster healthy" check is a hard block — migrating an already-degraded cluster is not supported in Phase 1.
M7 — Cutover
Migrating legacy-east → Buckit ● Running · 4m12s elapsed
Overall progress ▓▓▓▓▓░░░░░░░ 3 / 8 nodes
NODE STATE CUTOVER START DURATION RESULT
node1 ✓ Buckit healthy 12:00:01 58s ✓
node2 ✓ Buckit healthy 12:01:02 61s ✓
node3 ⟳ Waiting cluster-healthy 12:02:04 — —
node4 · Pending — — —
...
Cluster health (live)
Quorum: ✓ maintained throughout cutover
Read availability: 100 %
Write availability: 87 % ↑ recovers when node3 finishes
Live log [⏸ Pause]
┌──────────────────────────────────────────────────────────┐
│ 12:02:04 node3 $ systemctl stop minio │
│ 12:02:05 node3 ✓ minio stopped │
│ 12:02:05 node3 $ scp buckit-1.0.0.rpm node3:/tmp/ │
│ 12:02:06 node3 ✓ uploaded (45 MiB) │
│ 12:02:06 node3 $ dnf install -y /tmp/buckit-1.0.0.rpm │
│ 12:02:07 node3 ✓ installed buckit-1.0.0 │
│ provides /usr/local/bin/buckit, │
│ buckit.service, buckit user/group │
│ 12:02:07 node3 $ systemctl disable minio │
│ 12:02:07 node3 $ systemctl enable --now buckit │
│ 12:02:08 node3 ✓ buckit.service active │
│ 12:02:08 node3 i reading EnvironmentFile= │
│ /etc/default/minio (unchanged) │
│ 12:02:09 node3 ✓ health probe /minio/health/live │
│ ... │
└──────────────────────────────────────────────────────────┘
[Pause after current node] [Rollback all completed]
- "Pause after current node" lets the operator stop the rolling cutover cleanly at a node boundary — useful if the cluster shows distress.
- "Rollback all completed" is always available during cutover. It reverses
switched nodes in reverse order and restores
minio.service.
M8 — Verify
Post-migration verification
Cluster health ● Healthy
Node count 8 / 8 reporting
Bucket count 142 / 142
Object count (sampled, 1000 objects) 1000 / 1000 readable
IAM
Users 17 / 17 present
Groups 3 / 3 present
Policies 11 / 11 present
Service accounts 42 / 42 present
Bucket configs
Policies 57 / 57 match snapshot
Lifecycle rules 21 / 21 match snapshot
Notification configs 9 / 9 match snapshot
Smoke test
PUT 1 KiB to __buckit_migration_probe ✓
GET back, content match ✓
DELETE ✓
All checks passed.
[Re-run verification] [Download report ⤓]
- Any failed verification check leaves the wizard on this screen with a
prominent
[Rollback]action. - The verification report is archived against the cluster record for audit.
M9 — Finalize
You're about to finalize the migration of legacy-east.
After finalizing:
· dnf remove minio (or apt remove minio) on each node, removing the
minio binary, minio.service unit, and minio user/group cleanly via
the package manager
· Buckit retains the minio .rpm/.deb in the manager DB for 30 days
for emergency rollback (manual reinstall)
· The wizard's [Rollback] option is removed
· Cluster status moves from "Migrating" to "Active"
If MinIO was originally installed via tarball rather than a package,
finalize falls back to removing /usr/local/bin/minio and the
minio.service unit file directly. The wizard surfaces which mode
applies per node.
What is preserved (not modified by finalize):
· /etc/default/minio — buckit.service continues to read it
· /etc/minio/ — TLS certs, KMS config
· .minio.sys/, xl.meta — on-disk cluster state and data
· MINIO_* env var names — read directly by the buckit binary
These paths and names are intentionally kept MinIO-compatible. Fresh
Buckit deployments use the same layout, so post-migration nodes are
byte-identical to a fresh install at every layer except the binary
and the unit name.
[← Back to verify] [Finalize migration]
Finalize migrationtriggers a final task that performs the irreversible cleanup steps and flips cluster state.- Before finalize, the cluster appears in the cluster list as
Migratingwith a yellow chip. After finalize, it appears asActivewith amigrated_from: minio@v2024-12-01chip on the cluster overview.
Cluster Detail
Route: /clusters/:id. Top-level tabs.
Overview
prod-east [↗ Open Buckit console] [⟳ Actions ▾]
v1.0.0 · 8 nodes · 1 pool · EC:4 · Migrated from MinIO 2024-12-01
┌─────────────────────┬─────────────────────┬─────────────────────┐
│ Health │ Capacity │ Activity │
│ ● Healthy │ 412 Ti / 864 Ti │ Last task │
│ 8/8 nodes online │ ▓▓▓▓▓░░░░░ 47% │ Rolling restart │
│ 96/96 drives ready │ │ 2h ago · ✓ Success │
└─────────────────────┴─────────────────────┴─────────────────────┘
Recent tasks [View all →]
✓ Rolling restart 2h ago · 4m12s
✓ Health probe 4h ago · 2s
✓ Deploy v1.0.0 3d ago · 9m34s
**Open Buckit console**opens the cluster's built-in web console (served by thebuckitbinary on its console port) in a new tab. This is the entry point for bucket browsing, IAM, metrics, and other data-plane operations thatbmdeliberately does not duplicate.Actions ▾menu: Rolling restart, Stop cluster, Start cluster, Upgrade…, Rotate root credentials, Tear down cluster (destructive, double-confirm).
Nodes
NODE STATE VERSION DRIVES FREE UPTIME
node1.example.com ● Online v1.0.0 12/12 ready 55% 3d
node2.example.com ● Online v1.0.0 12/12 ready 54% 3d
...
node5.example.com ⚠ Online v1.0.0 11/12 ready 53% 3d
↳ /dev/sdh degraded — healing
node8.example.com ● Online v1.0.0 12/12 ready 56% 3d
- Row click → node detail.
Node Detail (/clusters/:id/nodes/:nodeId)
node5.example.com [Restart] [⟳ Actions ▾]
Online · Buckit v1.0.0 · uptime 3d
System
OS Ubuntu 24.04 LTS
Kernel 6.8.0-31-generic
CPU / RAM 16 cores · 64 GiB
Network eno1 (10 GbE)
Service
Unit buckit.service (active, enabled)
Listen :9000, :9001
Last restart 3 days ago
Drives
MOUNT DEVICE SIZE USED STATUS
/data/disk1 /dev/sda 16 Ti 55% ● Ready
/data/disk2 /dev/sdb 16 Ti 54% ● Ready
...
/data/disk8 /dev/sdh 16 Ti 53% ⚠ Healing (37 %)
...
Recent log lines (last 50) [Tail →]
Services Tab
Cluster service control
State ● Running on all 8 nodes
Version v1.0.0
[Rolling restart] [Stop all] [Start all]
[Upgrade…] [Rotate root credentials]
Rolling restartopens a small confirmation modal withConcurrency: Sequential / Two at a timeand an estimated duration.Upgrade…opens an upgrade wizard (out of scope to detail in this doc but reuses the deploy log component).
Cluster Tasks Tab
Same component as the global task center, scoped to this cluster.
Cluster Settings Tab
SSH credentials [Rotate] [View]
Buckit version pin v1.0.0 [Change…]
Health probe Every 30 s [Edit]
Audit log retention 30 days [Edit]
[Tear down cluster…] (destructive)
Tasks Center
Route: /tasks. Global queue across all clusters.
Tasks [Filter: all ▾] [Cluster: all ▾]
STATE NAME CLUSTER STARTED DURATION
⟳ Running Migrate legacy-east legacy-east 3m ago 3m12s
⟳ Running Health probe prod-east 20s ago 20s
✓ Success Rolling restart prod-east 2h ago 4m12s
✗ Failed Deploy v1.0.0 staging 1d ago 12m
↳ node3: SSH timeout
○ Canceled Discover nodes prod-west-new 1d ago 45s
- Row click → task detail.
- Failed tasks expose a
Retrybutton on the detail page when the task type supports it; not all do (e.g., a one-shot finalize is not retryable).
Task Detail (/tasks/:id)
Migrate legacy-east ⟳ Running
Started 12:00:01 · running 3m12s
Cluster legacy-east · Triggered by admin
Steps
✓ Snapshot MinIO state · 18s
✓ Preflight · 22s
⟳ Cutover (3/8 nodes) · 2m32s
✓ node1 · 58s
✓ node2 · 61s
⟳ node3 · 33s
· node4 pending
...
· Verify (pending)
· Finalize (pending)
Live log [Filter: all ▾] [⏸]
┌──────────────────────────────────────────────────────────────┐
│ ... │
└──────────────────────────────────────────────────────────────┘
[Pause after current step] [Cancel] [Download log ⤓]
- Tasks are first-class resources. Every long-running action in the UI lands here, and every wizard "deploy" / "cutover" screen is just an inline view of the corresponding task.
Manager Settings
Route: /settings. Minimal in Phase 1.
Admin
Username admin
Password ●●●●●●●● [Change]
Session timeout 8 hours [Edit]
TLS
Listener :9443
Certificate /etc/bm/cert.pem (expires 2026-08-12)
Private key /etc/bm/key.pem
[Replace certificate…]
Storage
Database SQLite at /var/lib/bm/bm.db
Backups Daily at 03:00 UTC [Edit]
[Download backup now]
Audit log
Retention 90 days
[View log →] [Export ⤓]
Cross-Cutting States
Empty states
- Cluster list, no clusters and no drafts → redirect to
/welcome. - Cluster list, only drafts → cluster list with prominent banner: "You have 1 draft cluster. [Resume] [Discard]".
- Node detail, drives empty → "No drives detected. Re-run discovery."
- Tasks center, no tasks → "No tasks yet. Tasks created by wizards and cluster actions will appear here."
Loading states
- Skeleton rows for tables, with shimmer animation.
- For wizard steps that run a backend task before content is available (discovery, preflight, snapshot, verify), show a per-row progress view rather than a single global spinner.
Error states
- SSH failure mid-wizard → inline row error with
[Retry], plus a link to the full task log. - Lost connection to manager → global banner: "Connection to manager lost. Retrying in 5 s…" Auto-resumes when connection returns.
- Task failed → cluster status changes to a yellow
Action neededchip; clicking opens the failed task with remediation suggestions.
Confirmation modals (always double-confirm)
- Tear down cluster
- Rollback migration
- Stop all nodes
- Rotate root credentials
The modal pattern: title, what will happen, what won't happen, a typed confirmation (e.g., "Type the cluster name to confirm: ____"), and the destructive button is red.
Component Inventory
Components reused across screens. A frontend engineer should build these once and compose them throughout.
| Component | Used in |
|---|---|
WizardShell |
All wizards |
Stepper |
All wizards |
NodeTable |
N2, N3, M2, M3, cluster nodes tab |
SSHCredentialsForm |
N2, M2, cluster settings |
DiscoveryRow |
N3, M3 |
PreflightTable |
N5, M6 |
TopologyBuilder |
N4 |
PlanReview |
N6, M5 |
TaskLogStream |
N7, M7, task detail |
TaskStepsTimeline |
Task detail |
RollingProgress |
N7, M7, rolling restart, upgrade |
ConfirmModal |
All destructive actions |
CapacityCard, HealthCard, ActivityCard |
Cluster overview |
API Contract Sketch
The wireframes assume a backend that exposes:
POST /api/v1/clusters— create draft cluster.PATCH /api/v1/clusters/:id— update draft (basics, nodes, topology).POST /api/v1/clusters/:id/discover— start discovery task.POST /api/v1/clusters/:id/preflight— start preflight task.POST /api/v1/clusters/:id/deploy— start deploy task.POST /api/v1/clusters/:id/migration/snapshot— start MinIO snapshot.POST /api/v1/clusters/:id/migration/cutover— start cutover task.POST /api/v1/clusters/:id/migration/verify— start verify task.POST /api/v1/clusters/:id/migration/rollback— start rollback task.POST /api/v1/clusters/:id/migration/finalize— finalize migration.GET /api/v1/tasks/GET /api/v1/tasks/:id— list/inspect tasks.GET /api/v1/tasks/:id/events— SSE stream of task events.
Every long-running action returns a task ID. The UI never blocks on these endpoints; it always renders against the task stream.
Accessibility & Responsiveness
- Keyboard navigation through wizard steps (Tab/Shift-Tab, Enter to advance, Esc to cancel modals).
- Color is never the only indicator of state — all status pills carry an icon and a text label.
- Live regions for task log updates (with a pause control for screen-reader users).
- Minimum supported viewport: 1280 × 800. The wizard collapses gracefully to 1024 × 768. Mobile is not a target for Phase 1.
Out of Scope for Phase 1
The following are intentionally excluded and should not appear in the bm UI.
Already provided by the per-cluster Buckit web console (served by the
buckit binary itself; bm should link out to it from the cluster overview,
not reimplement it):
- Bucket browser, object upload/download
- IAM user/group/policy editor (a read-only view in M8 verify is fine)
- Metrics and Prometheus-style dashboards
- Bucket-level configuration (lifecycle, replication, notifications)
Deferred to a later phase of bm itself:
- Kubernetes as a deployment target (a separate operator-oriented path, per
the phased plan in
README.md)
What Comes After Phase 1
Subsequent phases build on the same shared core (task engine, cluster store,
SSH layer) introduced by Phase 1. See README.md for the full plan.
- Phase 2 — Manager CLI. A terminal frontend over the same API:
bm cluster deploy,bm cluster status, remote manager targeting via--manager. Makesbmusable without the UI. - Phase 3 —
mcadmin replacement. Move Buckit-specific admin operations (admin info, user/policy/alias, profile management) intobm. - Phase 4 — Broader
mcreplacement. Selected data-path commands (ls,cp,mirror, bucket/object helpers) once the internal command model is stable.
Kubernetes as a deployment target is a separate, later track and is not gated on Phases 2–4.
Open UI Questions
- Should the wizards support resuming on a different browser/session, or is "same browser" acceptable for Phase 1? (Draft state lives server-side, so either is technically feasible.)
- For the in-place migration, do we expose the "two at a time" rolling concurrency in v1, or hide it behind an advanced flag until we have field data on its safety?
- How long should the rollback window stay open after verify passes but before finalize? Current draft assumes "until the user clicks Finalize" with no timeout — should we add a soft 24-hour reminder?
- Should the task log offer client-side text search across the live stream, or only on the archived log after the task ends?
Appendix A — MinIO compatibility surface
The wizards rely on a fixed split between operator-facing names (Buckit-branded) and internal names that remain MinIO-compatible so fresh and migrated nodes are byte-identical at the storage and config layer.
| Surface | Name | Owner |
|---|---|---|
| Binary | /usr/local/bin/buckit |
Buckit (package) |
| Systemd unit | /lib/systemd/system/buckit.service |
Buckit (package) |
buckit user/group |
Created by package postinstall | Buckit (package) |
| Env file | /etc/default/minio |
Manager (writes on fresh; preserves on migration) |
| Env var names | MINIO_* |
Read directly by the buckit binary |
| On-disk state | .minio.sys/, xl.meta |
MinIO format, unchanged |
The env file path stays MinIO-named so a fresh-deployed node and a
migrated-from-MinIO node have identical layouts, and so the migration wizard
never has to translate env vars. A future release may add BUCKIT_* aliases
with MINIO_* as a deprecated fallback; that's out of scope here.
Appendix B — Package install path
Packages are produced by the existing release pipeline (see
packaging/nfpm.yaml) and contain the binary, the unit file, and the
postinstall/preremove/postremove scripts that create the buckit user.
The manager installs them by local file: fetch the artifact once from
the GitHub Release, scp it to each node, then run
dnf install -y /tmp/buckit.rpm (or the apt/apk equivalent) on the
node. No yum/apt repository infrastructure is required.
| Target distro family | Install command on node |
|---|---|
| RHEL / Rocky / Alma / Fedora | dnf install -y /tmp/buckit.rpm |
| Debian / Ubuntu | apt install -y /tmp/buckit.deb |
| Alpine | apk add --allow-untrusted /tmp/... |
| Other / detection failed | scp raw binary; manager writes the unit and creates the user itself |
The package owns the binary, unit, and user; the manager only ever writes
/etc/default/minio with cluster-specific values (and, rarely, a systemd
drop-in for a cluster-level override).