build: rename the delivery artifacts to silo and complete the package payload

Everything a user installs is renamed, and the package finally installs enough
to be startable on a clean host.

Artifact names
- goreleaser.yml: build id, binary, archive and checksum manifest become silo_*.
  release.github.name stays "minio" with a comment - the GitHub repository has
  not been renamed yet, and pointing at pgsty/silo before the rename would 404.
  Also adds per-archive SPDX SBOMs and a keyless cosign signature over the
  checksum manifest, so the signed manifest covers archives and SBOMs together.
- nfpm.yml: package name silo, and the binary moves from /usr/local/bin/minio
  to /usr/bin/silo. /usr/local is not on the default PATH of a systemd unit and
  is not FHS-correct for a distribution package.
- package-release.sh, sign-release-rpms.sh and verify-build-provenance.sh follow
  the new names; the RPM signing script asserts NAME=silo and the new four-file
  payload. nfpm is now invoked from the repository root so relative script paths
  in the config resolve regardless of the caller's directory.

Package relationships are deliberately empty
No Provides, Obsoletes, Replaces or package-level Conflicts. Obsoletes: minio
cannot distinguish a pgsty package from upstream's own identically named one,
so an unattended dnf upgrade could silently swap a different vendor's product
for this one. With no relationships, both packages coexist, their file sets do
not overlap, and migration and rollback are single explicit commands. The
mutual exclusion lives in the unit instead: silo.service carries
Conflicts=minio.service plus After=minio.service.

Payload, from two files to four
- /usr/bin/silo
- /usr/lib/systemd/system/silo.service
- /etc/default/silo, installed config|noreplace
- /usr/lib/sysusers.d/silo.conf

The old package shipped a unit referencing an account nothing created, so a
clean install could not start. postinstall.sh now creates the silo system
account through systemd-sysusers, useradd or BusyBox adduser in that order and
runs daemon-reload. It never stops a service, never chowns data and never
touches /etc/default/minio. preremove.sh disables silo.service only on a real
removal - Debian "remove", RPM 0, Alpine's dotted version - so upgrades leave
the running service alone. lifecycle_test.sh exercises both against a stubbed
PATH, so a green run cannot create an account or touch the host.

silo.service reads /etc/default/minio then /etc/default/silo, in that order, so
an existing node's MINIO_* values keep working and the new file overrides them.
The packaged silo.env therefore ships comments only: any active assignment
would shadow the legacy file with an empty value.

Makefile: build/install/install-race produce ./silo, and the docker target now
assembles a context from a locally built linux binary plus Dockerfile.goreleaser
instead of the deleted Dockerfile. The hotfix, hotfix-push, docker-hotfix and
docker-hotfix-push targets are gone - they downloaded upstream's pkger, signed
with upstream's minisign key and scp'd to dl-N.minio.io. verifiers now depends
on a new rebrand-guard target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Feng Ruohang
2026-08-06 08:47:44 +08:00
parent 77bdc4c0cd
commit 15ab10833b
13 changed files with 402 additions and 102 deletions
+38 -6
View File
@@ -4,9 +4,9 @@ env:
- CGO_ENABLED=0
builds:
- id: minio
- id: silo
main: .
binary: minio
binary: silo
goos:
- linux
- darwin
@@ -23,18 +23,50 @@ builds:
- "{{ .Env.LDFLAGS }}"
archives:
- id: minio
- id: silo
ids:
- minio
name_template: "minio_{{ .Env.PKG_VERSION }}_{{ .Os }}_{{ .Arch }}"
- silo
name_template: "silo_{{ .Env.PKG_VERSION }}_{{ .Os }}_{{ .Arch }}"
checksum:
name_template: "minio_{{ .Env.PKG_VERSION }}_checksums.txt"
name_template: "silo_{{ .Env.PKG_VERSION }}_checksums.txt"
algorithm: sha256
# Generate one SPDX JSON document per platform archive. SBOMs are created
# before the checksum stage, so the signed checksum manifest covers both the
# archives and their corresponding software bills of materials.
sboms:
- id: silo-archives
artifacts: archive
# Avoid network-backed package enrichment: the release SBOM must be
# reproducible from the artifact alone and the PR gate must work offline.
args:
- "$artifact"
- "--output"
- "spdx-json=$document"
env:
- SYFT_FILE_METADATA_CATALOGER_ENABLED=true
- SYFT_CHECK_FOR_APP_UPDATE=false
# A keyless Sigstore bundle is the detached signature for the checksum
# manifest. Consumers can verify the whole archive/SBOM set without trusting a
# long-lived project key copied into the repository.
signs:
- id: silo-checksums
cmd: cosign
signature: "${artifact}.sigstore.json"
args:
- sign-blob
- "--bundle=${signature}"
- "${artifact}"
- --yes
artifacts: checksum
output: true
release:
github:
owner: pgsty
# Transitional until the irreversible GitHub repository rename.
name: minio
draft: true
prerelease: false
+23 -4
View File
@@ -1,4 +1,4 @@
name: minio
name: silo
arch: ${NFPM_ARCH}
platform: linux
version: ${PKG_VERSION}
@@ -7,26 +7,45 @@ release: ${NFPM_RELEASE}
section: utils
priority: optional
maintainer: "Ruohang Feng (@Vonng) <rh@vonng.com>"
description: S3-Interface Libre Object Storage, Community-maintained MinIO server fork.
description: S3-Interface Libre Object Storage, a community-maintained S3-compatible server.
vendor: PGSTY
homepage: https://silo.pgsty.com
license: AGPL-3.0-or-later
contents:
- src: ${NFPM_SOURCE}
dst: /usr/local/bin/minio
dst: /usr/bin/silo
expand: true
file_info:
mode: 0755
owner: root
group: root
- src: ${NFPM_UNIT}
dst: /usr/lib/systemd/system/minio.service
dst: /usr/lib/systemd/system/silo.service
expand: true
file_info:
mode: 0644
owner: root
group: root
- src: ${NFPM_DEFAULTS}
dst: /etc/default/silo
type: config|noreplace
expand: true
file_info:
mode: 0644
owner: root
group: root
- src: ${NFPM_SYSUSERS}
dst: /usr/lib/sysusers.d/silo.conf
expand: true
file_info:
mode: 0644
owner: root
group: root
scripts:
postinstall: buildscripts/package/postinstall.sh
preremove: buildscripts/package/preremove.sh
rpm:
group: Applications/File
+1
View File
@@ -2,6 +2,7 @@
cover.out
*~
minio
silo
!*/
site/
**/*.test
+47 -65
View File
@@ -7,8 +7,8 @@ GOARCH ?= $(shell go env GOARCH)
GOLANGCI_VERSION ?= v2.11.3
VERSION ?= $(shell git describe --tags)
REPO ?= quay.io/minio
TAG ?= $(REPO)/minio:$(VERSION)
REPO ?= docker.io/pgsty
TAG ?= $(REPO)/silo:$(VERSION)
GOLANGCI_DIR = .bin/golangci/$(GOLANGCI_VERSION)
GOLANGCI = $(GOLANGCI_DIR)/golangci-lint
@@ -33,10 +33,15 @@ getdeps: ## fetch necessary dependencies
sh "$$script" -b $(GOLANGCI_DIR) $(GOLANGCI_VERSION); \
fi
crosscompile: ## cross compile minio
crosscompile: ## cross compile Silo
@(env bash $(PWD)/buildscripts/cross-compile.sh)
verifiers: lint check-gen
verifiers: lint check-gen rebrand-guard
rebrand-guard: ## verify Silo branding and protected compatibility identifiers
@go run ./buildscripts/rebrand-guard
@env bash $(PWD)/buildscripts/verify-rebrand.sh
@env bash $(PWD)/dockerscripts/docker-entrypoint_test.sh
check-gen: ## check for updated autogenerated files
@go generate ./... >/dev/null
@@ -64,12 +69,12 @@ lint-fix: getdeps ## runs golangci-lint suite of linters with automatic fixes
@$(GOLANGCI) run --build-tags kqueue --timeout=10m --config ./.golangci.yml --fix
check: test
test: verifiers build ## builds minio, runs linters, tests
test: verifiers build ## builds Silo, runs linters, tests
@echo "Running unit tests"
@MINIO_API_REQUESTS_MAX=10000 CGO_ENABLED=0 go test -v -tags kqueue,dev ./...
test-root-disable: install-race
@echo "Running minio root lockdown tests"
@echo "Running Silo root lockdown tests"
@env bash $(PWD)/buildscripts/disable-root.sh
test-ilm: install-race
@@ -85,7 +90,7 @@ test-pbac: install-race
@env bash $(PWD)/docs/iam/policies/pbac-tests.sh
test-decom: install-race
@echo "Running minio decom tests"
@echo "Running Silo decom tests"
@env bash $(PWD)/docs/distributed/decom.sh
@env bash $(PWD)/docs/distributed/decom-encrypted.sh
@env bash $(PWD)/docs/distributed/decom-encrypted-sse-s3.sh
@@ -93,17 +98,17 @@ test-decom: install-race
@env bash $(PWD)/docs/distributed/decom-encrypted-kes.sh
test-versioning: install-race
@echo "Running minio versioning tests"
@echo "Running Silo versioning tests"
@env bash $(PWD)/docs/bucket/versioning/versioning-tests.sh
test-configfile: install-race
@env bash $(PWD)/docs/distributed/distributed-from-config-file.sh
test-upgrade: install-race
@echo "Running minio upgrade tests"
test-upgrade:
@echo "Running MinIO-to-Silo upgrade tests"
@(env bash $(PWD)/buildscripts/minio-upgrade.sh)
test-race: verifiers build ## builds minio, runs linters, tests (race)
test-race: verifiers build ## builds Silo, runs linters, tests (race)
@echo "Running unit tests under -race"
@(env bash $(PWD)/buildscripts/race.sh)
@@ -151,9 +156,9 @@ test-site-replication-oidc: install-race ## verify automatic site replication
@echo "Running tests for automatic site replication of IAM (with OIDC)"
@(env bash $(PWD)/docs/site-replication/run-multi-site-oidc.sh)
test-site-replication-minio: install-race ## verify automatic site replication
@echo "Running tests for automatic site replication of IAM (with MinIO IDP)"
@(env bash $(PWD)/docs/site-replication/run-multi-site-minio-idp.sh)
test-site-replication-silo: install-race ## verify automatic site replication
@echo "Running tests for automatic site replication of IAM (with Silo IDP)"
@(env bash $(PWD)/docs/site-replication/run-multi-site-silo-idp.sh)
@echo "Running tests for automatic site replication of SSE-C objects"
@(env bash $(PWD)/docs/site-replication/run-ssec-object-replication.sh)
@echo "Running tests for automatic site replication of SSE-C objects with SSE-KMS enabled for bucket"
@@ -169,11 +174,11 @@ test-timeout: install-race ## test multipart
@echo "Test server timeout"
@(env bash $(PWD)/buildscripts/test-timeout.sh)
verify: install-race ## verify minio various setups
verify: install-race ## verify Silo in various setups
@echo "Verifying build with race"
@(env bash $(PWD)/buildscripts/verify-build.sh)
verify-healing: install-race ## verify healing and replacing disks with minio binary
verify-healing: install-race ## verify healing and replacing disks with the Silo binary
@echo "Verify healing build with race"
@(env bash $(PWD)/buildscripts/verify-healing.sh)
@(env bash $(PWD)/buildscripts/verify-healing-empty-erasure-set.sh)
@@ -194,59 +199,38 @@ verify-healing-inconsistent-versions: install-race ## verify resolving inconsist
build-debugging:
@(env bash $(PWD)/docs/debugging/build.sh)
build: checks build-debugging ## builds minio to $(PWD)
@echo "Building minio binary to './minio'"
@CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -tags kqueue -trimpath --ldflags "$(LDFLAGS)" -o $(PWD)/minio 1>/dev/null
build: checks build-debugging ## builds Silo to $(PWD)
@echo "Building Silo binary to './silo'"
@CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -tags kqueue -trimpath --ldflags "$(LDFLAGS)" -o $(PWD)/silo 1>/dev/null
hotfix-vars:
$(eval LDFLAGS := $(shell MINIO_RELEASE="RELEASE" MINIO_HOTFIX="hotfix.$(shell git rev-parse --short HEAD)" go run buildscripts/gen-ldflags.go $(shell git describe --tags --abbrev=0 | \
sed 's#RELEASE\.\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)T\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)Z#\1-\2-\3T\4:\5:\6Z#')))
$(eval VERSION := $(shell git describe --tags --abbrev=0).hotfix.$(shell git rev-parse --short HEAD))
hotfix: hotfix-vars clean install ## builds minio binary with hotfix tags
@wget -q -c https://github.com/minio/pkger/releases/download/v2.3.11/pkger_2.3.11_linux_amd64.deb
@wget -q -c https://raw.githubusercontent.com/minio/minio-service/v1.1.1/linux-systemd/distributed/minio.service
@sudo apt install ./pkger_2.3.11_linux_amd64.deb --yes
@mkdir -p minio-release/$(GOOS)-$(GOARCH)/archive
@cp -af ./minio minio-release/$(GOOS)-$(GOARCH)/minio
@cp -af ./minio minio-release/$(GOOS)-$(GOARCH)/minio.$(VERSION)
@minisign -qQSm minio-release/$(GOOS)-$(GOARCH)/minio.$(VERSION) -s "${CRED_DIR}/minisign.key" < "${CRED_DIR}/minisign-passphrase"
@sha256sum < minio-release/$(GOOS)-$(GOARCH)/minio.$(VERSION) | sed 's, -,minio.$(VERSION),g' > minio-release/$(GOOS)-$(GOARCH)/minio.$(VERSION).sha256sum
@cp -af minio-release/$(GOOS)-$(GOARCH)/minio.$(VERSION)* minio-release/$(GOOS)-$(GOARCH)/archive/
@pkger -r $(VERSION) --ignore
hotfix-push: hotfix
@scp -q -r minio-release/$(GOOS)-$(GOARCH)/* minio@dl-0.minio.io:~/releases/server/minio/hotfixes/linux-$(GOOS)/
@scp -q -r minio-release/$(GOOS)-$(GOARCH)/* minio@dl-0.minio.io:~/releases/server/minio/hotfixes/linux-$(GOOS)/archive
@scp -q -r minio-release/$(GOOS)-$(GOARCH)/* minio@dl-1.minio.io:~/releases/server/minio/hotfixes/linux-$(GOOS)/
@scp -q -r minio-release/$(GOOS)-$(GOARCH)/* minio@dl-1.minio.io:~/releases/server/minio/hotfixes/linux-$(GOOS)/archive
@echo "Published new hotfix binaries at https://dl.min.io/server/minio/hotfixes/linux-$(GOOS)/archive/minio.$(VERSION)"
docker-hotfix-push: docker-hotfix
@docker push -q $(TAG) && echo "Published new container $(TAG)"
docker-hotfix: hotfix-push checks ## builds minio docker container with hotfix tags
@echo "Building minio docker image '$(TAG)'"
@docker build -q --no-cache -t $(TAG) --build-arg RELEASE=$(VERSION) . -f Dockerfile.hotfix
docker: build ## builds minio docker container
@echo "Building minio docker image '$(TAG)'"
@docker build -q --no-cache -t $(TAG) . -f Dockerfile
docker: checks build-debugging ## builds the local Linux Silo container image
@echo "Building Silo container image '$(TAG)'"
@set -e; \
context=$$(mktemp -d); \
trap 'rm -rf "$$context"' EXIT; \
CGO_ENABLED=0 GOOS=linux GOARCH=$(GOARCH) go build -tags kqueue -trimpath \
--ldflags "$(LDFLAGS)" -o "$$context/silo"; \
mkdir -p "$$context/dockerscripts"; \
cp Dockerfile.goreleaser LICENSE CREDITS "$$context/"; \
cp dockerscripts/docker-entrypoint.sh dockerscripts/download-static-curl.sh \
"$$context/dockerscripts/"; \
docker build -q --no-cache --platform linux/$(GOARCH) -t $(TAG) --build-arg TARGETARCH=$(GOARCH) \
-f "$$context/Dockerfile.goreleaser" "$$context"
test-resiliency: build
@echo "Running resiliency tests"
@(DOCKER_COMPOSE_FILE=$(PWD)/docs/resiliency/docker-compose.yaml env bash $(PWD)/docs/resiliency/resiliency-tests.sh)
install-race: checks build-debugging ## builds minio to $(PWD)
@echo "Building minio binary with -race to './minio'"
@GORACE=history_size=7 CGO_ENABLED=1 go build -tags kqueue,dev -race -trimpath --ldflags "$(LDFLAGS)" -o $(PWD)/minio 1>/dev/null
@echo "Installing minio binary with -race to '$(GOPATH)/bin/minio'"
@mkdir -p $(GOPATH)/bin && cp -af $(PWD)/minio $(GOPATH)/bin/minio
install-race: checks build-debugging ## builds Silo to $(PWD)
@echo "Building Silo binary with -race to './silo'"
@GORACE=history_size=7 CGO_ENABLED=1 go build -tags kqueue,dev -race -trimpath --ldflags "$(LDFLAGS)" -o $(PWD)/silo 1>/dev/null
@echo "Installing Silo binary with -race to '$(GOPATH)/bin/silo'"
@mkdir -p $(GOPATH)/bin && cp -af $(PWD)/silo $(GOPATH)/bin/silo
install: build ## builds minio and installs it to $GOPATH/bin.
@echo "Installing minio binary to '$(GOPATH)/bin/minio'"
@mkdir -p $(GOPATH)/bin && cp -af $(PWD)/minio $(GOPATH)/bin/minio
@echo "Installation successful. To learn more, try \"minio --help\"."
install: build ## builds Silo and installs it to $GOPATH/bin.
@echo "Installing Silo binary to '$(GOPATH)/bin/silo'"
@mkdir -p $(GOPATH)/bin && cp -af $(PWD)/silo $(GOPATH)/bin/silo
@echo "Installation successful. To learn more, try \"silo --help\"."
clean: ## cleanup all generated assets
@echo "Cleaning up all the generated files"
@@ -254,10 +238,8 @@ clean: ## cleanup all generated assets
@find . -name '*~' | xargs rm -fv
@find . -name '.#*#' | xargs rm -fv
@find . -name '#*#' | xargs rm -fv
@rm -rvf minio
@rm -rvf silo
@rm -rvf build
@rm -rvf release
@rm -rvf .verify*
@rm -rvf minio-release
@rm -rvf minio.RELEASE*.hotfix.*
@rm -rvf pkger_*.deb
+32 -11
View File
@@ -34,11 +34,29 @@ fi
# against the config file, so the unit path is passed in absolute. Otherwise
# this only works when invoked from the repository root and fails elsewhere on
# a message that names the file rather than the cause.
unit_file="${repo_dir}/minio.service"
unit_file="${repo_dir}/silo.service"
defaults_file="${repo_dir}/silo.env"
sysusers_file="${repo_dir}/silo.sysusers"
postinstall_file="${repo_dir}/buildscripts/package/postinstall.sh"
preremove_file="${repo_dir}/buildscripts/package/preremove.sh"
if [ ! -f "${unit_file}" ]; then
echo "Missing systemd unit: ${unit_file}" >&2
exit 1
fi
if [ ! -f "${defaults_file}" ]; then
echo "Missing defaults file: ${defaults_file}" >&2
exit 1
fi
if [ ! -f "${sysusers_file}" ]; then
echo "Missing sysusers file: ${sysusers_file}" >&2
exit 1
fi
for lifecycle_script in "${postinstall_file}" "${preremove_file}"; do
if [ ! -x "${lifecycle_script}" ]; then
echo "Missing executable package lifecycle script: ${lifecycle_script}" >&2
exit 1
fi
done
packages_dir="${dist_dir}/packages"
mkdir -p "${packages_dir}"
@@ -68,7 +86,7 @@ find_binary() {
# variants (an added goamd64 level, a stale dist entry) would silently ship a
# package whose contents do not match its name.
matches="$(find "${dist_dir}" -maxdepth 2 -type f \
-path "${dist_dir}/minio_linux_${goarch}*/minio" | sort)"
-path "${dist_dir}/silo_linux_${goarch}*/silo" | sort)"
count="$(printf '%s' "${matches}" | grep -c . || true)"
if [ "${count}" -eq 0 ]; then
@@ -98,16 +116,19 @@ build_arch() {
# These names are the public download names and must not drift; RPM carries a
# release number, DEB and APK do not, matching what pkger produced.
rpm_file="${packages_dir}/minio-${PKG_VERSION}-1.${rpm_arch}.rpm"
deb_file="${packages_dir}/minio_${PKG_VERSION}_${deb_arch}.deb"
apk_file="${packages_dir}/minio_${PKG_VERSION}_${apk_arch}.apk"
rpm_file="${packages_dir}/silo-${PKG_VERSION}-1.${rpm_arch}.rpm"
deb_file="${packages_dir}/silo_${PKG_VERSION}_${deb_arch}.deb"
apk_file="${packages_dir}/silo_${PKG_VERSION}_${apk_arch}.apk"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE=1 NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" \
nfpm package --config "${nfpm_config}" --packager rpm --target "${rpm_file}"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE='' NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" \
nfpm package --config "${nfpm_config}" --packager deb --target "${deb_file}"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE='' NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" \
nfpm package --config "${nfpm_config}" --packager apk --target "${apk_file}"
(
cd "${repo_dir}"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE=1 NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" NFPM_DEFAULTS="${defaults_file}" NFPM_SYSUSERS="${sysusers_file}" \
nfpm package --config "${nfpm_config}" --packager rpm --target "${rpm_file}"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE='' NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" NFPM_DEFAULTS="${defaults_file}" NFPM_SYSUSERS="${sysusers_file}" \
nfpm package --config "${nfpm_config}" --packager deb --target "${deb_file}"
PKG_VERSION="${PKG_VERSION}" NFPM_RELEASE='' NFPM_ARCH="${goarch}" NFPM_SOURCE="${source}" NFPM_UNIT="${unit_file}" NFPM_DEFAULTS="${defaults_file}" NFPM_SYSUSERS="${sysusers_file}" \
nfpm package --config "${nfpm_config}" --packager apk --target "${apk_file}"
)
sha256_file "${rpm_file}"
sha256_file "${deb_file}"
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_dir="$(cd "${script_dir}/../.." && pwd)"
postinstall="${script_dir}/postinstall.sh"
preremove="${script_dir}/preremove.sh"
test_dir="$(mktemp -d)"
fakebin="${test_dir}/bin"
log_file="${test_dir}/calls.log"
useradd_shell=/usr/sbin/nologin
[ -x "${useradd_shell}" ] || useradd_shell=/sbin/nologin
busybox_shell=/sbin/nologin
[ -x "${busybox_shell}" ] || busybox_shell=/bin/false
cleanup() {
rm -rf "${test_dir}"
}
trap cleanup EXIT
mkdir -p "${fakebin}"
touch "${log_file}"
# One dispatcher represents every external command used by the lifecycle
# scripts. The tested scripts run with no host utilities in PATH, so a green
# result cannot create a real account or touch the host service manager.
cat > "${fakebin}/fake-command" <<'EOF'
#!/bin/sh
set -eu
command_name=${0##*/}
case "${command_name}" in
id)
[ "${PACKAGE_TEST_USER_EXISTS:-0}" = 1 ]
;;
getent)
[ "${PACKAGE_TEST_GROUP_EXISTS:-0}" = 1 ]
;;
systemd-sysusers|useradd|addgroup|adduser|systemctl)
{
printf '%s' "${command_name}"
for argument in "$@"; do
printf ' %s' "${argument}"
done
printf '\n'
} >> "${PACKAGE_TEST_LOG}"
;;
*)
echo "unexpected fake command: ${command_name}" >&2
exit 1
;;
esac
EOF
chmod +x "${fakebin}/fake-command"
link_command() {
ln -sf fake-command "${fakebin}/$1"
}
unlink_optional_commands() {
rm -f \
"${fakebin}/systemd-sysusers" \
"${fakebin}/useradd" \
"${fakebin}/adduser" \
"${fakebin}/addgroup"
}
reset_log() {
: > "${log_file}"
}
run_postinstall() {
PACKAGE_TEST_LOG="${log_file}" \
PACKAGE_TEST_USER_EXISTS="${1}" \
PACKAGE_TEST_GROUP_EXISTS="${2}" \
PATH="${fakebin}" \
/bin/sh "${postinstall}"
}
run_preremove() {
PACKAGE_TEST_LOG="${log_file}" PATH="${fakebin}" \
/bin/sh "${preremove}" "$@"
}
assert_log_line() {
grep -Fx -- "$1" "${log_file}" >/dev/null
}
reject_log_text() {
if grep -F -- "$1" "${log_file}" >/dev/null; then
echo "unexpected lifecycle call containing '$1':" >&2
cat "${log_file}" >&2
exit 1
fi
}
link_command id
link_command getent
link_command systemctl
# Clean install through systemd-sysusers. Side-by-side safety is represented
# by the fact that the only service-manager operation is daemon-reload: no old
# service is stopped, disabled, enabled, masked, or restarted.
unlink_optional_commands
link_command systemd-sysusers
reset_log
run_postinstall 0 0
assert_log_line "systemd-sysusers /usr/lib/sysusers.d/silo.conf"
assert_log_line "systemctl daemon-reload"
test "$(wc -l < "${log_file}" | tr -d ' ')" -eq 2
# An existing service account is preserved without modification.
reset_log
run_postinstall 1 0
test "$(cat "${log_file}")" = "systemctl daemon-reload"
# useradd creates a private group only when one does not already exist. An
# administrator may pre-create group silo with the legacy GID; that group must
# be reused rather than causing installation to fail.
unlink_optional_commands
link_command useradd
reset_log
run_postinstall 0 0
assert_log_line "useradd --system --user-group --no-create-home --shell ${useradd_shell} --comment Silo object storage service silo"
reject_log_text "--gid silo"
reset_log
run_postinstall 0 1
assert_log_line "useradd --system --gid silo --no-create-home --shell ${useradd_shell} --comment Silo object storage service silo"
reject_log_text "--user-group"
# BusyBox follows the same existing-group contract.
unlink_optional_commands
link_command adduser
link_command addgroup
reset_log
run_postinstall 0 0
assert_log_line "addgroup -S silo"
assert_log_line "adduser -S -D -H -G silo -s ${busybox_shell} silo"
reset_log
run_postinstall 0 1
reject_log_text "addgroup"
assert_log_line "adduser -S -D -H -G silo -s ${busybox_shell} silo"
# Debian remove, RPM erase, and Alpine deinstall stop the Silo unit. Upgrade
# arguments must leave the running service alone.
for removal_argument in remove 0 20260214120000.0.0-r0; do
reset_log
run_preremove "${removal_argument}"
test "$(cat "${log_file}")" = "systemctl disable --now silo.service"
done
for upgrade_argument in upgrade 1; do
reset_log
run_preremove "${upgrade_argument}"
test ! -s "${log_file}"
done
# The package deliberately leaves legacy ownership changes to an explicit
# systemd drop-in. Lifecycle scripts must never rewrite ownership or touch the
# old unit, and the base unit must expose overridable User/Group directives.
grep -Fx 'User=silo' "${repo_dir}/silo.service" >/dev/null
grep -Fx 'Group=silo' "${repo_dir}/silo.service" >/dev/null
if grep -Ein '\b(chown|chgrp|usermod|groupmod)\b|minio\.service' \
"${postinstall}" "${preremove}"; then
echo "package lifecycle scripts must not mutate data ownership or the legacy service" >&2
exit 1
fi
echo "Silo package lifecycle checks passed"
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
set -eu
sysusers_file=/usr/lib/sysusers.d/silo.conf
group_exists() {
if command -v getent >/dev/null 2>&1; then
getent group silo >/dev/null 2>&1
return
fi
[ -r /etc/group ] || return 1
while IFS=: read -r group_name _; do
[ "${group_name}" = silo ] && return 0
done < /etc/group
return 1
}
if ! id -u silo >/dev/null 2>&1; then
if command -v systemd-sysusers >/dev/null 2>&1; then
systemd-sysusers "${sysusers_file}"
elif command -v useradd >/dev/null 2>&1; then
nologin_shell=/usr/sbin/nologin
[ -x "${nologin_shell}" ] || nologin_shell=/sbin/nologin
if group_exists; then
useradd --system --gid silo --no-create-home --shell "${nologin_shell}" --comment "Silo object storage service" silo
else
useradd --system --user-group --no-create-home --shell "${nologin_shell}" --comment "Silo object storage service" silo
fi
elif command -v adduser >/dev/null 2>&1 && command -v addgroup >/dev/null 2>&1; then
nologin_shell=/sbin/nologin
[ -x "${nologin_shell}" ] || nologin_shell=/bin/false
group_exists || addgroup -S silo
adduser -S -D -H -G silo -s "${nologin_shell}" silo
else
echo "Unable to create the silo system account: systemd-sysusers, useradd, or BusyBox adduser is required" >&2
exit 1
fi
fi
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload >/dev/null 2>&1 || true
fi
+14
View File
@@ -0,0 +1,14 @@
#!/bin/sh
set -eu
# Debian passes "remove" for an actual removal, RPM passes 0 to %preun, and
# Alpine runs pre-deinstall only for removal and passes the old dotted version.
# Upgrade paths deliberately leave the running service untouched.
case "${1:-}" in
remove|0|*.*)
if command -v systemctl >/dev/null 2>&1; then
systemctl disable --now silo.service >/dev/null 2>&1 || true
fi
;;
esac
+11 -8
View File
@@ -10,12 +10,15 @@ expected_fingerprint="9592A7BC7A682E7333376E09E7935D8DB9BD8B20"
expected_vendor="PGSTY"
expected_packager="Ruohang Feng (@Vonng) <rh@vonng.com>"
expected_url="https://silo.pgsty.com"
expected_summary="S3-Interface Libre Object Storage, Community-maintained MinIO server fork."
expected_description="S3-Interface Libre Object Storage, Community-maintained MinIO server fork."
expected_summary="S3-Interface Libre Object Storage, a community-maintained S3-compatible server."
expected_description="S3-Interface Libre Object Storage, a community-maintained S3-compatible server."
expected_license="AGPL-3.0-or-later"
expected_group="Applications/File"
expected_payload="/usr/lib/systemd/system/minio.service
/usr/local/bin/minio"
expected_payload="/etc/default/silo
/usr/bin/silo
/usr/lib/systemd/system/silo.service
/usr/lib/sysusers.d/silo.conf"
# Transitional until the irreversible GitHub repository rename.
repository="${GH_REPO:-pgsty/minio}"
container="${DNFUPDATE_CONTAINER:-dnfupdate}"
upload=false
@@ -122,8 +125,8 @@ mkdir -p "${unsigned_dir}" "${signed_dir}"
chmod 700 "${work_dir}" "${unsigned_dir}" "${signed_dir}"
rpm_files=(
"minio-${package_version}-1.x86_64.rpm"
"minio-${package_version}-1.aarch64.rpm"
"silo-${package_version}-1.x86_64.rpm"
"silo-${package_version}-1.aarch64.rpm"
)
download_patterns=()
@@ -159,7 +162,7 @@ for rpm_file in "${rpm_files[@]}"; do
done
safe_tag="$(printf '%s' "${release_tag}" | tr -c 'A-Za-z0-9._-' '_')"
container_dir="/tmp/minio-sign-${safe_tag}-$$"
container_dir="/tmp/silo-sign-${safe_tag}-$$"
docker exec "${container}" mkdir -p "${container_dir}"
cleanup_container() {
@@ -203,7 +206,7 @@ for rpm_file in "${rpm_files[@]}"; do
docker cp "${unsigned_dir}/${rpm_file}" "${container}:${container_dir}/${rpm_file}" >/dev/null
container_rpm="${container_dir}/${rpm_file}"
assert_rpm_tag "${container_rpm}" NAME minio
assert_rpm_tag "${container_rpm}" NAME silo
assert_rpm_tag "${container_rpm}" VERSION "${package_version}"
assert_rpm_tag "${container_rpm}" RELEASE 1
assert_rpm_tag "${container_rpm}" ARCH "${expected_arch}"
+1 -1
View File
@@ -41,7 +41,7 @@ while IFS= read -r binary; do
grep -F 'vcs.' <<< "${info}" >&2 || true
exit 1
fi
done < <(find "${dist_dir}" -maxdepth 2 -type f \( -name 'minio' -o -name 'minio.exe' \) | sort)
done < <(find "${dist_dir}" -maxdepth 2 -type f \( -name 'silo' -o -name 'silo.exe' \) | sort)
if [ "${count}" -ne "${expected_count}" ]; then
echo "Expected ${expected_count} release binaries, found ${count}" >&2
+9
View File
@@ -0,0 +1,9 @@
# Silo keeps the MINIO_* environment variable interface for compatibility.
# This packaged file intentionally contains no active assignments so values in
# the legacy /etc/default/minio continue to work until an administrator chooses
# to override them here.
#
# MINIO_VOLUMES="/data"
# MINIO_OPTS="--console-address :9001"
# MINIO_ROOT_USER="silo-admin"
# MINIO_ROOT_PASSWORD="replace-with-a-long-random-secret"
+9 -7
View File
@@ -1,21 +1,23 @@
[Unit]
Description=MinIO
Description=Silo Object Storage Server
Documentation=https://silo.pgsty.com/docs/
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio
After=network-online.target minio.service
Conflicts=minio.service
AssertFileIsExecutable=/usr/bin/silo
[Service]
Type=notify
WorkingDirectory=/usr/local
User=minio-user
Group=minio-user
User=silo
Group=silo
ProtectProc=invisible
EnvironmentFile=-/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
EnvironmentFile=-/etc/default/silo
ExecStart=/usr/bin/silo server $MINIO_OPTS $MINIO_VOLUMES
# Let systemd restart this service always
Restart=always
@@ -32,7 +34,7 @@ TasksMax=infinity
# Disable timeout logic and wait until process is stopped
TimeoutSec=infinity
# Disable killing of MinIO by the kernel's OOM killer
# Disable killing of Silo by the kernel's OOM killer
OOMScoreAdjust=-1000
SendSIGKILL=no
+1
View File
@@ -0,0 +1 @@
u silo - "Silo object storage service" - -