Silo 20260806 Released
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 (silorpm/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.sysformat, 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--maintenancepre-drain gate — no shell,curl, ormcrequired in the container. - Distroless image pilot:
pgsty/silo:<RELEASE>-distrolessships exactly one program — thesilobinary — ongcr.io/distroless/static, with an exec-formHEALTHCHECKbaked in and/datacreated writable in the image layer. - The classic image does not change behavior: same entrypoint, same bundled tools,
mc ready localkeeps working, and noHEALTHCHECKwas added to it. It now bundlesmcli20260806. - 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-pkg3.11.0,mcli20260806, 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_*.apk | MINIO_* 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,”readyadds KMS/etcd reachability when configured, and theclusterpair evaluates write/read quorum across every erasure set. - Exit codes are
0(healthy) and1(anything else) — never the Docker-reserved2. One diagnostic line decodes the server’sx-minio-server-statusand quorum headers fordocker inspect;--jsonemits 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 frompublic.crt+private.keyin 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 clusteranswers the pre-drain question: exit0means the node can be taken down without losing HA; HTTP 412 (exit1) means it cannot.- Certificate verification is skipped, matching the kubelet’s documented behavior for HTTPS probes, and the transport ignores
HTTP_PROXYso 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/passwdwith anonroot(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-formHEALTHCHECKrunningsilo healthcheck readyis baked in (interval 30s, timeout 10s, start-period 2m, retries 3), so Compose users get workingdepends_on: condition: service_healthywith zero configuration. /datais 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,--userincluded. This fixes, for the distroless variant, the non-root failure documented in #55.- Not supported in this variant: the deprecated
MINIO_USERNAME/MINIO_GROUPNAMEprivilege-drop path (use--useror KubernetesrunAsUser),docker exec <c> shdebugging (use ephemeral-container tooling), and in-imagemc(use the releasedmclior 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, setMINIO_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
Distributed migrations must switch all nodes together.
Cluster bootstrap verifies that every node runs the same binary (by checksum). A mixed cluster — some nodes on Silo, some still on MinIO — does not form: the new node stays in activating, logging Expected Silo binary checksum ... seen: ... and Waiting for at least 1 remote servers with valid configuration, indefinitely. Stop MinIO on all nodes, then start Silo on all nodes (near-simultaneously). Once every node runs Silo, rolling restarts work normally — gate each one with silo healthcheck --maintenance cluster.
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-consolewhile preserving thegithub.com/minio/consoleimport path. silo-pkg3.11.0 — retains the policy/LDAP/certificate fixes including the LDAP-over-TLS repair tracked in #15.mcli20260806 — 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
HEALTHCHECKsurvives into the image config (it is a Docker extension outside the OCI spec),/dataships world-writable, no shell and no/usr/bin/minioexist, 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 verifyagainst 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
- Package upgrades are a takeover, not an in-place update. Install
silo, keep/etc/default/minioas is (it is inherited), enablesilo.service; starting it stopsminio.servicevia the conflict relation. Data is untouched. - Keep data ownership stable with the legacy-user drop-in above; do not chown storage or move certificates during migration.
- Distributed clusters: full-stop switchover only. See the warning above — mixed Silo/MinIO nodes do not form a cluster.
- Container users: the image is now
docker.io/pgsty/silo;docker.io/pgsty/miniostays frozen at 20260804 as an archive. The classic image’s behavior is unchanged — includingmc ready localhealth checks — and the distroless variant is strictly opt-in. - Distroless differences are deliberate: no shell, no in-image
mc, noMINIO_USERNAMEpath; health is native; servers configured via CLI arguments needMINIO_HEALTHCHECK_URLfor the baked-in probe. - Helm users: chart 7.0.1’s defaults now pull this release; override
image.tagexplicitly if you pin versions. - Known and unchanged: the classic image still does not create
/datain the layer, so fully non-rootdocker runagainst 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). - Pair with
mcli20260806 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,
clusterreports 503 withwrite-quorum=5whilecluster-readandlivestay 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 -9fault 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-00Zatpgsty/silo, with checksummed platform archives, provenance attestations, and RPM/DEB/APK packages (GPG-signed RPMs); docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Zandlatest;docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distrolessanddistroless— published on demand from the finished release;- companion releases:
mcli20260806,silo-pkg3.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 services15ab10833: rename the delivery artifacts to silo and complete the package payload30749911b: ship the silo binary in the image and translate the legacy argv commande071bb77e: replace the minio chart with a silo chart that preserves identitybd8df5166: gate the rebrand on compatibility, packaging, and provenance evidence6613c2a3c: pin the external test fixtures and run the suites against the silo binaryfd2ca1c6d,c46b16ec6,c47733abc,f1c77d5a2: cut over to pgsty/silo and main; document the archived branch6740e6978: move the workflow actions onto the Node 24 runtimeb57275be3: adopt the no-CLA plus DCO policy and fix copyright terms62717d7bf,a6d6d9b02: update the embedded Console to 2.1.0, then 2.1.16bd9cf77e: regenerate CREDITS from the linked module set and guard it in CI219670d31: ship LICENSE and NOTICE in every package and image2ff594f4b: add the nativesilo healthchecksubcommand4c34d2309: add the distroless image variant as a pilotb6d47b739,9462cce16: harden both per adversarial review; lint cleanup16b78eb4e: bundle mcli 20260806 and point the Helm defaults at this release062a91bee: pin the CREDITS module closure to the shipped linux target467931455: unify the rpm and deb release segment as1PGSTYb14ea22aa: match checksum manifest entries exactly in the image publish lane3be10fcc1: 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.