Silo 20260806 Released

The first release published under the Silo name: the completed rebrand with compatibility preserved, native health checking, a distroless image pilot, bundled mcli 20260806, full license compliance, and a provenance-gated release pipeline.

Version: RELEASE.2026-08-06T00-00-00Z · Commit: 3be10fcc1a44f6620ded0bd303461f9d688cca23

SILO 20260806 is the first release published under the Silo name. The previous release, 20260804, was the last one delivered as pgsty/minio; this release completes the cutover to github.com/pgsty/silo and renames every delivery surface — binary, packages, container images, systemd unit, Helm chart — while deliberately preserving every wire and configuration surface a MinIO deployment depends on. On top of the rename it adds native health checking (silo healthcheck), a single-binary distroless container image pilot, complete license-compliance materials in every artifact, and a release pipeline gated on compatibility snapshots and build provenance.

The release covers 28 commits after RELEASE.2026-08-04T00-00-00Z, changing 396 files with 27,188 insertions and 19,561 deletions. It passed a six-phase pre-release acceptance, including a real four-node TLS cluster migration from MinIO to Silo — with byte-verified data integrity, maintenance-gated rolling restarts, fault injection, and a full rollback rehearsal.

Highlights

  • The rebrand is complete, and compatibility is the contract. Repository, binary (/usr/bin/silo), packages (silo rpm/deb/apk), images (docker.io/pgsty/silo), and service (silo.service) are renamed; the S3 and admin APIs, /minio/* routes, MINIO_* environment variables, x-minio-* headers, on-disk .minio.sys format, and Go module paths are all preserved and frozen by a CI compatibility guard.
  • Native health checking: silo healthcheck [live|ready|cluster|cluster-read] probes the server’s own health API with correct exit codes, decoded quorum diagnostics, TLS auto-detection, and a --maintenance pre-drain gate — no shell, curl, or mc required in the container.
  • Distroless image pilot: pgsty/silo:<RELEASE>-distroless ships exactly one program — the silo binary — on gcr.io/distroless/static, with an exec-form HEALTHCHECK baked in and /data created writable in the image layer.
  • The classic image does not change behavior: same entrypoint, same bundled tools, mc ready local keeps working, and no HEALTHCHECK was added to it. It now bundles mcli 20260806.
  • Compliance completed: LICENSE and NOTICE ship in every package and image, CREDITS is regenerated from the actually-linked module set (291 modules) and guarded in CI, and the project adopts a no-CLA, DCO-based contribution policy.
  • Components refreshed: embedded SILO Console 2.1.1, silo-pkg 3.11.0, mcli 20260806, Go 1.26.5.
  • Provenance-gated releases: container images are built only from published, checksum- and attestation-verified release archives; image SBOMs and provenance attestations now cover the distroless variant too.

The rename

What changed, and what deliberately did not:

Renamed (delivery surface)Preserved (compatibility surface)
Repository: github.com/pgsty/silo (main branch)S3 API, admin API, and request signing behavior
Binary: /usr/bin/silo/minio/* routes, including /minio/health/* and metrics
Packages: silo-*.rpm, silo_*.deb, silo_*.apkMINIO_* environment variables and x-minio-* headers
Images: docker.io/pgsty/silo (+ -distroless)On-disk format (.minio.sys), erasure coding, versioning
Unit: silo.service (conflicts with, and supersedes, minio.service)Go module and import paths (github.com/minio/...)
Default config dir: ~/.silo (falls back to an existing ~/.minio)mc compatibility alias for the bundled mcli

The server presents its own identity — silo --version reports the AGPL-3.0 license, MinIO’s 2015-2025 copyright, PGSTY’s modification copyright, and the “based on MinIO technology” attribution — and every inherited connection to MinIO-operated services (the update feed and its signing key, SUBNET, telemetry) is severed rather than redirected. The container entrypoint translates the legacy minio argv token, so docker run pgsty/silo minio server /data keeps working.

A snapshot-based rebrand guard runs in CI: it fails on any drift, in either direction, across 334 route literals, 437 environment tokens, 84 headers, and 9,014 exported symbols.

Native health checking

The server binary can now probe its own health endpoints, which makes container health checks possible without any second binary — and is what the distroless image relies on:

silo healthcheck [FLAGS] [live|ready|cluster|cluster-read]
  • The check vocabulary maps 1:1 onto /minio/health/<path>; live (the default) answers “is this process serving,” ready adds KMS/etcd reachability when configured, and the cluster pair evaluates write/read quorum across every erasure set.
  • Exit codes are 0 (healthy) and 1 (anything else) — never the Docker-reserved 2. One diagnostic line decodes the server’s x-minio-server-status and quorum headers for docker inspect; --json emits a machine-readable verdict.
  • The probe target is derived the way the server derives its own listen address: --address / MINIO_ADDRESS, with HTTPS auto-detected from public.crt + private.key in the certs directory, or overridden wholesale with --url / MINIO_HEALTHCHECK_URL. The environment form exists because a probe process cannot see the server’s command line — if the server’s address or TLS comes from CLI arguments, one environment variable redirects the baked-in probe.
  • silo healthcheck --maintenance cluster answers the pre-drain question: exit 0 means the node can be taken down without losing HA; HTTP 412 (exit 1) means it cannot.
  • Certificate verification is skipped, matching the kubelet’s documented behavior for HTTPS probes, and the transport ignores HTTP_PROXY so loopback probes never route through a proxy.

Kubernetes needs none of this — kubelet httpGet probes hit /minio/health/live and /minio/health/ready from outside the container — and the cluster checks should stay out of per-container probes: they reflect cluster-wide quorum, not one process. The full design rationale, including verified endpoint semantics, is recorded in the health-check design note.

Distroless image pilot

Alongside the classic image, this release publishes a distroless variant: pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distroless, plus a rolling distroless tag.

  • Base is gcr.io/distroless/static-debian12: CA certificates, tzdata, /tmp, and an /etc/passwd with a nonroot (65532) entry — no shell, no package manager, no libc. On top of it, exactly one program: /usr/bin/silo (plus the license set under /licenses/). The image is 128 MB versus the classic 199 MB.
  • The binary is the ENTRYPOINT; an exec-form HEALTHCHECK running silo healthcheck ready is baked in (interval 30s, timeout 10s, start-period 2m, retries 3), so Compose users get working depends_on: condition: service_healthy with zero configuration.
  • /data is created in the image layer, world-writable — there is no entrypoint left to repair volume ownership at runtime, and this is what makes every privilege mode work, --user included. This fixes, for the distroless variant, the non-root failure documented in #55.
  • Not supported in this variant: the deprecated MINIO_USERNAME/MINIO_GROUPNAME privilege-drop path (use --user or Kubernetes runAsUser), docker exec <c> sh debugging (use ephemeral-container tooling), and in-image mc (use the released mcli or the client image).
  • TLS: mount certificates at /tmp/.silo/certs (the container’s default certs directory) and both the server and the baked-in probe derive HTTPS from the same location; for CLI-configured servers, set MINIO_HEALTHCHECK_URL.

The classic image remains the default and is unchanged. If the pilot proves out, the distroless variant becomes the recommended image later; the decision record lives in the design note above.

Container images

The classic image was diffed field by field against pgsty/minio:RELEASE.2026-08-04T00-00-00Z: entrypoint, exposed ports, volumes, working directory, user, and (absent) health-check configuration are identical. Exactly three differences exist, all deliberate: Cmd is ["silo"] instead of ["minio"], the upstream update-verification key variable MINIO_UPDATE_MINISIGN_PUBKEY is removed (updates through upstream channels are permanently disabled), and HOME=/tmp is declared to match the entrypoint’s writable-home guarantee.

The bundled client is upgraded to mcli RELEASE.2026-08-06T00-00-00Z (with the mc alias preserved), pinned by per-architecture SHA-256 digests and verified against the published checksums at build time. Interoperability of the released mcli 20260806 against this server — multipart, versioning, presigned URLs, metadata/tags, user and policy administration — was verified as part of release acceptance.

Helm chart

The chart ships as silo 7.0.1, preserving rendered resource identity with the legacy chart across a simulated upgrade (verified by the migration guard over 7 rendered resources). Its default image tag now points at this release — docker.io/pgsty/silo is a fresh repository, so the inherited default could never have pulled. The chart still ships no liveness/readiness/startup probes; adding them is planned, and documented, in the design note’s follow-up phase.

Packaging and migration

RPM, DEB, and APK packages install exactly six files: /usr/bin/silo, silo.service, a sysusers definition (creating the silo system user), /etc/default/silo (marked config/noreplace), LICENSE, and NOTICE. RPMs are GPG-signed with the PGSTY maintainer key (9592A7BC 7A682E73 33376E09 E7935D8D B9BD8B20). RPM and DEB now carry a unified, PGDG-style 1PGSTY release segment — silo-<version>-1PGSTY.<arch>.rpm and silo_<version>-1PGSTY_<arch>.deb — replacing the inherited bare -1 on RPM and the missing revision on DEB; APK names stay bare because Alpine pkgrel admits only -r<integer>.

silo.service is designed for takeover: Type=notify (readiness is signaled by the server itself), Conflicts=minio.service + After=minio.service (starting Silo stops a running MinIO unit), and two environment files — /etc/default/minio is read first and /etc/default/silo overrides it — so an existing MinIO configuration is inherited without editing. For existing deployments whose data is owned by the minio user, the documented drop-in keeps ownership untouched:

# /etc/systemd/system/silo.service.d/10-legacy-user.conf
[Service]
User=minio
Group=minio

Migration troubleshooting, from the acceptance run: if Silo starts as the packaged silo user against a deployment whose TLS certificates live under the minio user’s home, it fails with HTTPS specified in endpoints, but no TLS certificate is found and restart-loops until the systemd start limit — the legacy-user drop-in above is the fix. Keep the MinIO package and unit installed (disabled) during the migration window: the rollback path — stop Silo, start MinIO — was rehearsed and reads all data written during the Silo window, because the migration touches neither data ownership nor format.

Components and dependencies

  • SILO Console 2.1.1 — the embedded console, selected from pgsty/silo-console while preserving the github.com/minio/console import path.
  • silo-pkg 3.11.0 — retains the policy/LDAP/certificate fixes including the LDAP-over-TLS repair tracked in #15.
  • mcli 20260806 — bundled in the image and released separately; see its release notes.
  • Go 1.26.5 — toolchain unchanged from 20260804.

Build, CI, and release pipeline

  • Compatibility as a CI gate: the rebrand guard snapshots routes, environment tokens, headers, metrics, storage/policy identifiers, and exported symbols, and fails on any unreviewed drift; companion scripts assert the delivery surface (binary path, unit contents, image layout) and that no live upstream endpoint remains in runtime code.
  • Release-image gate: every release-pipeline run builds both container images and asserts, among others: the distroless HEALTHCHECK survives into the image config (it is a Docker extension outside the OCI spec), /data ships world-writable, no shell and no /usr/bin/minio exist, Docker’s health state turns healthy from the baked probe alone, and SIGTERM still stops the server gracefully as root and as --user 1001:1001.
  • Provenance chain: images are built from the published release archives after checksum verification and gh attestation verify against the exact tag; per-architecture SBOMs and provenance attestations are pushed for the classic and distroless images; the distroless health-check gate runs before the multi-arch manifests are promoted.
  • Workflow runtime moved to Node 24 across CI actions.

Compatibility and upgrade notes

  1. Package upgrades are a takeover, not an in-place update. Install silo, keep /etc/default/minio as is (it is inherited), enable silo.service; starting it stops minio.service via the conflict relation. Data is untouched.
  2. Keep data ownership stable with the legacy-user drop-in above; do not chown storage or move certificates during migration.
  3. Distributed clusters: full-stop switchover only. See the warning above — mixed Silo/MinIO nodes do not form a cluster.
  4. Container users: the image is now docker.io/pgsty/silo; docker.io/pgsty/minio stays frozen at 20260804 as an archive. The classic image’s behavior is unchanged — including mc ready local health checks — and the distroless variant is strictly opt-in.
  5. Distroless differences are deliberate: no shell, no in-image mc, no MINIO_USERNAME path; health is native; servers configured via CLI arguments need MINIO_HEALTHCHECK_URL for the baked-in probe.
  6. Helm users: chart 7.0.1’s defaults now pull this release; override image.tag explicitly if you pin versions.
  7. Known and unchanged: the classic image still does not create /data in the layer, so fully non-root docker run against a Docker-managed volume fails as before (#55, fixed in the distroless variant); the inherited Postgres/MySQL legacy notification-migration limitation from the 20260804 notes still applies (#53).
  8. Pair with mcli 20260806 for the client side; older clients continue to work over the unchanged wire protocol.

Verification

This release was verified in stages, each with recorded evidence:

  • unit and end-to-end matrices for the health-check command: target derivation and precedence (flag/env/derived), real-TLS auto-detection, exit-code contract, JSON schema, timeout bounds, usage errors;
  • cluster-semantics verification on a four-node cluster: with 2 of 4 nodes stopped, cluster reports 503 with write-quorum=5 while cluster-read and live stay 200 — the write/read quorum split observed live, matching the erasure math;
  • image acceptance: the classic image diffed field-by-field against the 20260804 baseline; the distroless image asserted down to file inventory, exact health-check configuration, and root/non-root/TLS/env-override runtime scenarios;
  • an adversarial model-based code review of the new code, with every confirmed finding fixed and re-verified;
  • a six-phase pre-release acceptance concluding in a real migration: a Pigsty-deployed four-node TLS MinIO 20260804 cluster (16 drives, EC:4) was migrated to Silo via the packaged takeover path — reference data (multipart, versioned, tagged objects) read back byte-identical, four maintenance-gated rolling restarts, kill -9 fault injection with the load balancer serving 23/24 continuous IO rounds (the only failure in the kill second), Prometheus metrics continuity, and a full rollback to MinIO and back, proving the migration reversible.

Validation boundaries

Not proven by this release and not to be inferred: external LDAP/OIDC/KMS/etcd services (the only case where ready diverges from live was not exercised against a live KMS); amd64 packages were cross-built and payload-checked but not installed on a physical x86-64 host; the renamed Docker publish workflow (including the new SBOM/attestation lanes) has its first production run at this release’s publication; Windows and Intel macOS were not tested.

Artifacts

  • GitHub release RELEASE.2026-08-06T00-00-00Z at pgsty/silo, with checksummed platform archives, provenance attestations, and RPM/DEB/APK packages (GPG-signed RPMs);
  • docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z and latest; docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distroless and distroless — published on demand from the finished release;
  • companion releases: mcli 20260806, silo-pkg 3.11.0, embedded SILO Console 2.1.1;
  • design record: Native Health Checks and the Distroless Image.

Selected changes

  • 15def34dc, 77bdc4c0c: drop upstream delivery residue; present Silo identity and close inherited upstream services
  • 15ab10833: rename the delivery artifacts to silo and complete the package payload
  • 30749911b: ship the silo binary in the image and translate the legacy argv command
  • e071bb77e: replace the minio chart with a silo chart that preserves identity
  • bd8df5166: gate the rebrand on compatibility, packaging, and provenance evidence
  • 6613c2a3c: pin the external test fixtures and run the suites against the silo binary
  • fd2ca1c6d, c46b16ec6, c47733abc, f1c77d5a2: cut over to pgsty/silo and main; document the archived branch
  • 6740e6978: move the workflow actions onto the Node 24 runtime
  • b57275be3: adopt the no-CLA plus DCO policy and fix copyright terms
  • 62717d7bf, a6d6d9b02: update the embedded Console to 2.1.0, then 2.1.1
  • 6bd9cf77e: regenerate CREDITS from the linked module set and guard it in CI
  • 219670d31: ship LICENSE and NOTICE in every package and image
  • 2ff594f4b: add the native silo healthcheck subcommand
  • 4c34d2309: add the distroless image variant as a pilot
  • b6d47b739, 9462cce16: harden both per adversarial review; lint cleanup
  • 16b78eb4e: bundle mcli 20260806 and point the Helm defaults at this release
  • 062a91bee: pin the CREDITS module closure to the shipped linux target
  • 467931455: unify the rpm and deb release segment as 1PGSTY
  • b14ea22aa: match checksum manifest entries exactly in the image publish lane
  • 3be10fcc1: add a manual finalize lane refreshing SBOMs and checksums for signed Draft packages

Acknowledgments

A first release under a new name is the right moment to thank everyone who has filed issues against this fork — bug reports, compatibility findings, and proposals alike, resolved and still open:

@mosesdd (#1), @Xavier-777 (#2, #17), @jiadzh (#3), @TLINDEN (#4), @AntonOfTheWoods (#5), @zylpsrs (#6), @nsanitate (#7), @makinikm (#9), @magicxor (#10), @spaceg00se-r (#11, #14), @heroes1412 (#13), @vampywiz17 (#15), @davinkevin (#20), @chalukyaj (#30), @cbornet (#31, #32), @jvasile (#33), @Kesavaambati (#35), @redfoxfox (#38), @kuldeep-link11 (#39, #40), @meesudzu (#42), @pmezhuev (#43), and @kh0mka (#51).

Several of this release’s headline items trace directly back to those reports: the bundled-client guarantee to #4 and #9, the LDAP-over-TLS repair to #15, the completed package payload to #33, GPG-signed RPMs to #43, the migration guide to #42, and the distroless /data fix to #55.

Code contributions deserve their own mention. @davinkevin’s distroless image PR (#21) anticipated this release’s pilot months in advance — the shipped variant supersedes that PR with the native health check built in, but the direction was proposed there first. Conformance PRs from @magicxor (#12) and @ycjlin (#37) are queued for review immediately after this release.