Files
buckit/docs/manager/phase1-web-ui.md
abuckit df162d630f docs: add Buckit Manager design — architecture and Phase 1 web UI
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.
2026-05-11 19:13:18 -04:00

49 KiB
Raw Permalink Blame History

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:

  1. Deploy a new Buckit cluster to a set of fresh hosts.
  2. 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 a Draft badge.
  • 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

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-place chip 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.
  • + New is 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 buckit or minio binary/service was detected.
  • A node with detected existing services shows a ⚠ Existing service chip 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      ~3090 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 migration triggers a final task that performs the irreversible cleanup steps and flips cluster state.
  • Before finalize, the cluster appears in the cluster list as Migrating with a yellow chip. After finalize, it appears as Active with a migrated_from: minio@v2024-12-01 chip 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 the buckit binary on its console port) in a new tab. This is the entry point for bucket browsing, IAM, metrics, and other data-plane operations that bm deliberately 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 restart opens a small confirmation modal with Concurrency: Sequential / Two at a time and 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 Retry button 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 needed chip; 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. Makes bm usable without the UI.
  • Phase 3 — mc admin replacement. Move Buckit-specific admin operations (admin info, user/policy/alias, profile management) into bm.
  • Phase 4 — Broader mc replacement. 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 24.

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).