Document the container A/B on the corrected single-pool rig (one 16-drive
EC:4 set, 2 MiB non-inlined objects):
- single-trip proven directly: with xl.meta and the canonical data dir
deleted on all drives, FAST_GET=1 still serves byte-exact from the shadow
(multi-pool returned 404).
- cold single-stream TTFB ~26% lower (server-side trace) / ~21% (curl),
captured paired on the same requests; saturated throughput flat on the
seek-free loopback medium.
- record the two rig traps (multi-pool xl.meta pre-read; inline cutoff is
per-shard, so EC:4 inlines everything below ~1.5 MiB).
Design note: the on-disk shadow header should be variable-length with a
self-describing payload so fields can evolve without lockstep; the fixed
1024-byte positional header is a phase-1 shortcut.
cluster.sh emitted one endpoint arg per node, which brought the rig up as
four independent server pools. Multi-pool GET resolves the owning pool via
getLatestObjectInfoWithIdx (a per-pool xl.meta read) before the set-level
fast path runs, so BUCKIT_FAST_GET=1 still read xl.meta and the single-trip
path was never exercised.
Emit a single pool spanning all nodes (http://node{1...4}:9000/data/...)
so SinglePool() is true and GET dispatches straight to the set, letting the
fast path bypass xl.meta. Regenerated docker-compose.yml reflects the change.
Address security review: specify the exact epoch-key derivation scheme
(deterministic KMS MAC, or random-and-wrap) since cloud KMS GenerateDataKey
is random by default and would otherwise make keys unrecoverable. Promote
authenticated metadata binding, basic token scoping, a minimal revocation
path, and bounded historical cache into MVP requirements; keep full replay
protection and coordinated revocation as phase-2. Add the accepted-residual-
risk note and a multi-instance proxy section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switch the design to a true-HSM model where the master key never leaves
the KMS, unlike KES/MinKMS which load it into memory. The KMS produces an
epoch key per window; bucket and object keys derive locally. Adds the
two-window model (12h epoch + ~15min Buckit cache TTL), corrected near-zero
cost analysis, the bounded-compromise security framing, and clarifies that
only the bucket key is cached.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Design for replacing deprecated MinIO KES with an open-source approach:
a cached per-cluster encryption key in Buckit (L1) plus a stateless
KMS-auth proxy (Fargate, L2) that holds the cloud credentials so they
never live in Buckit. Covers cost analysis, the two-tier cache, security
boundary (credential isolation vs. key-material exposure), and open
decisions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolves govulncheck failures flagged in CI:
- GO-2026-5013..5023 (golang.org/x/crypto/ssh) — fixed in v0.52.0
- GO-2026-5026 (golang.org/x/net/idna) — fixed in v0.55.0
x/sys bumped to v0.45.0 as a transitive dependency.
Pulls in buckit-io/console@f8ce35f8, which replaces the
CSP-blocked Google Fonts <link> with a 6.7 KB embedded
Montserrat subset for the BuckitLogo wordmark.
- update-gh-pages: remove zip_binary/publish_package/trim_archives; only write
4 buckit.sha256sum files for self-update; generate release/index.html with
per-platform download links and archives/index.html from GitHub API listing
all stable releases; add force_orphan to prevent git history bloat
- gh-pages-index.yml: skip server/buckit/release and server/buckit/archives
so the auto-indexer does not overwrite the custom HTML pages
Binaries exceed GitHub's 100MB git push limit so they cannot be stored
in the gh-pages branch. Two changes to fix this:
- release.yml: stop copying binaries/minisig to gh-pages; write
buckit.sha256sum files with the release tag embedded in the filename
field (e.g. 'buckit.RELEASE.xxx') so the Go code can construct the
versioned GitHub Releases URL.
- update.go / admin-handlers.go: getBinaryURL now constructs a
github.com/releases/download URL when the checksum source is github.io
and the sha256sum filename contains a release tag. Fixes two dead-code
bugs in both admin handlers where 'if updateURL == ""' was always
false after updateURL had already been set.
- packaging/scripts: convert 4-space indentation to tabs (shfmt)
- docs/distributed/decom*.sh: add consistent trailing slashes to
mc ls bucket paths so before/after diffs compare identical formats
Add docs/manager/backend-design.md — companion to ui-architecture.md
covering the backend that replaces the in-memory mock: package
layout, bbolt schema, REST surface derived from the UI, unified
operation orchestration pipeline, security model, SSH layer,
and on-demand refresh.
Lays out the fork strategy for the MinIO Go ecosystem. bm aims for
full mc CLI parity, so we fork wholesale rather than selectively
port. One coordinated pass forks Tier 1 (mc, madmin-go, minio-go,
pkg, cli) and Tier 2 (selfupdate, colorjson, kms-go) under
buckit-io/* — no upstream rebase obligation thereafter. CLI uses
the forked urfave/cli framework; HTTP backend uses the forked
madmin-go directly. Tier 3 specialised libraries stay as upstream
deps. Includes an alias bridge so forked mc commands resolve
cluster names from the bm store.
ui-architecture.md updated to match the simplified History page:
single source (UI-initiated mutable actions), structured row shape
(opKind/opLabel/clusterId/clusterName/hostScope/result), status
filter chips, no CLI source column.
phase1-implementation.md picks up TODOs from prior design rounds:
M8 cutover writes a systemd drop-in to run buckit as MinIO's
user/group; rollback-to-MinIO becomes a cluster Action visible when
migratedFrom is set.
- request-flow.md § 10.1: OS-level environment file as the layer that
feeds the process before .minio.sys is reachable. Covers the three
conventional paths (/etc/default/minio, /etc/minio/config.env,
/etc/sysconfig/minio), what lives there (root creds, MINIO_VOLUMES,
KMS bootstrap), and why those can't move into config.json.
- phase1-implementation.md: TODOs for M5 preflight (stale
.minio.sys/format.json detection, hostname pattern + drive
uniformity), drive preparation wizard deferred to M6.5 with full
safety requirements, and auto-save of bm alias to ~/.bm/config.json
(separate from mc's ~/.mc) on successful deploy/import. Data-key
bootstrap section corrects the path from /etc/bm/data.key to
~/.config/bm/data.key for personal-tool framing.
Adds four documents that form the Buckit Manager design corpus
alongside the existing README.md and phase1-web-ui.md:
- phase1-implementation.md: Phase 1 milestone plan (M0-M9), repo
layout, locked stack decisions, and a Progress section that tracks
what's landed in github.com/buckit-io/bm so work can resume cleanly
in a new session.
- ui-architecture.md: data flow (admin API + per-node connectivity
probes + SSH facts), the on-demand fetch pipeline with failure
isolation, REST contract sketch, per-page details for Clusters
list, Cluster detail, History, and Manager Settings, and the
proposed HostInfo extension to madmin.ServerProperties to surface
OS / CPU / Memory / Network in /admin/info.
- metrics.md: spec for the per-cluster Metrics tab (Info, Usage,
Traffic, Resources) — referenced by ui-architecture.md as the
source-of-truth for the existing /admin/info shape.
- authentication.md: notes on Console + mc CLI auth flows.
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.
Mirrors the earlier release.yml switch to nfpm. The local `make hotfix`
flow now downloads nfpm v2.46.3 (matching CI), stages the binary at
dist/buckit, computes a numeric PKG_VERSION from the RELEASE tag with
the same transformation CI uses (and additionally strips the
.hotfix.<sha> suffix that hotfix-vars appends), and builds rpm/deb/apk
from packaging/nfpm.yaml. Resulting packages are copied into the
existing buckit-release/$(GOOS)-$(GOARCH)/ directory so hotfix-push
keeps working unchanged.
clean target updated to remove nfpm_*.deb and the new dist/ directory.
release-process-plan.md table row updated to reflect the tool change.
Note: no Go-module dependency on pkger ever existed; pkger was only a
CI/Make-time download.
The previous packaging step used minio/pkger, which is hardcoded for
MinIO's portfolio: its nfpm template only attaches a systemd unit when
the binary name matches "minio", "aistor", or "sidekick". Invoking it
with --appName buckit silently dropped the unit (and the maintainer/
homepage fields stayed MinIO-branded) — the published .rpm/.deb shipped
only /usr/local/bin/buckit with no service definition.
Switch to nfpm directly, driven by a config in packaging/nfpm.yaml that
we own. The packages now contain:
/usr/local/bin/buckit
/lib/systemd/system/buckit.service (Type=notify, LimitNOFILE=1048576,
OOMScoreAdjust=-1000, etc.)
A postinstall script creates the buckit system user/group idempotently;
preremove stops the service; postremove reloads systemd but deliberately
leaves the user in place to avoid orphaning data on attached storage.
The unit is modeled on MinIO's production unit but reads
EnvironmentFile=-/etc/default/minio (leading - = optional), keeping
fresh buckit nodes byte-compatible with the env file MinIO already
ships, so the manager's in-place migration story works without any
config translation.
Verified locally by building rpm/deb/apk against the published
RELEASE.2026-05-11T17-20-40Z binary and inspecting the output.