Files
minio/cmd/globals.go
T
Feng Ruohang 77bdc4c0cd feat(server): present Silo identity and close the inherited upstream services
Two coupled changes that must land together, because the same files carry both:
the server now identifies itself as Silo, and every path that would have called
home to a MinIO-operated service is closed.

Product identity
- build-constants.go: store name, UA name and startup banner become Silo. The
  Go identifiers (MinioStoreName, MinioBannerName, ...) keep their names on
  purpose - renaming exported symbols would churn the compatibility surface for
  a cosmetic gain, and the rebrand guard freezes that surface.
- main.go, server-startup-msg.go, ftp-server.go and the user-visible log, help
  and error strings across cmd/ and internal/ switch to Silo. Original MinIO
  copyright, LICENSE, NOTICE and CREDITS are untouched; --version now prints
  the upstream copyright, the pgsty modification notice, and the trademark
  policy's approved "based on MinIO technology" attribution.
- api-headers.go: the HTTP Server header becomes "Silo". This is the one
  externally observable identity change, so TestCommonHeadersUseSiloProductName
  pins it - probes that sniff for "MinIO" must move to capability detection.
- Prometheus metric HELP strings keep their MinIO wording. They are part of the
  metrics contract the guard protects, not product copy.

Configuration directory
- config-dir.go: new installs use ~/.silo. If only ~/.minio exists it is still
  read, with a one-time notice and no files moved. If both exist ~/.silo wins
  and an ambiguity warning is emitted; an explicit --config-dir always wins.
  Covered by TestSelectDefaultConfigDir. The internal .minio.sys layout is
  never renamed - this rule applies to the user config directory only.

Upstream service lockdown
- globalInplaceUpdateDisabled is now true at initialization rather than being
  set from MINIO_UPDATE. common-main.go still parses MINIO_UPDATE so upgrading
  nodes do not fail on an unknown key, but warns that the value is ignored;
  there is no way to re-enable the updater. TestInplaceUpdateCannotBeEnabled
  guards that. Without this, an admin with mc could have overwritten
  /usr/bin/silo with an upstream MinIO binary.
- verifyBinary and commitBinary refuse early; the ServerUpdate v1/v2 admin
  routes and the peer-rest update endpoints stay registered and keep returning
  the existing programmatic error, so clients see a stable failure rather than
  a 404.
- MinioReleaseBaseURL and defaultMinisignPubkey are emptied: no dl.min.io
  download root, and upstream's minisign key is no longer a trust root for
  anything this fork ships.
- cmd/callhome.go is deleted and internal/config/subnet/ is reduced to parsing
  its old keys and reporting that the integration is disabled. config-current.go
  warns instead of failing when callhome or SUBNET settings are present, so an
  upgraded node with those keys still starts.
- internal/config/errors.go replaces the MinIO Slack and support entry points
  with Silo documentation and issue links. Error codes and programmatic fields
  are unchanged.

Verified: the compatibility baseline is unchanged except for the deliberate
removal of the /api/health/upload SUBNET route; go build, go vet and the full
cmd/ and internal/ unit suites pass; a locally built binary starts, serves
S3/Admin/metrics on the unchanged /minio/* routes, answers with Server: Silo,
and falls back to a pre-existing ~/.minio with the expected notice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 08:46:58 +08:00

488 lines
15 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd
import (
"crypto/x509"
"errors"
"net/http"
"os"
"sync"
"time"
consoleapi "github.com/minio/console/api"
"github.com/minio/dnscache"
"github.com/minio/madmin-go/v3"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/internal/bpool"
"github.com/minio/minio/internal/bucket/bandwidth"
"github.com/minio/minio/internal/config"
"github.com/minio/minio/internal/config/browser"
"github.com/minio/minio/internal/grid"
"github.com/minio/minio/internal/handlers"
"github.com/minio/minio/internal/kms"
"go.uber.org/atomic"
"github.com/dustin/go-humanize"
"github.com/minio/minio/internal/auth"
"github.com/minio/minio/internal/config/callhome"
"github.com/minio/minio/internal/config/compress"
"github.com/minio/minio/internal/config/dns"
"github.com/minio/minio/internal/config/drive"
idplugin "github.com/minio/minio/internal/config/identity/plugin"
polplugin "github.com/minio/minio/internal/config/policy/plugin"
"github.com/minio/minio/internal/config/storageclass"
"github.com/minio/minio/internal/config/subnet"
xhttp "github.com/minio/minio/internal/http"
etcd "go.etcd.io/etcd/client/v3"
levent "github.com/minio/minio/internal/config/lambda/event"
"github.com/minio/minio/internal/event"
"github.com/minio/minio/internal/pubsub"
"github.com/minio/pkg/v3/certs"
"github.com/minio/pkg/v3/env"
xnet "github.com/minio/pkg/v3/net"
)
// minio configuration related constants.
const (
GlobalMinioDefaultPort = "9000"
globalMinioDefaultRegion = ""
// This is a sha256 output of ``arn:aws:iam::minio:user/admin``,
// this is kept in present form to be compatible with S3 owner ID
// requirements -
//
// ```
// The canonical user ID is the Amazon S3only concept.
// It is 64-character obfuscated version of the account ID.
// ```
// http://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example4.html
globalMinioDefaultOwnerID = "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4"
globalMinioDefaultStorageClass = "STANDARD"
globalWindowsOSName = "windows"
globalMacOSName = "darwin"
globalMinioModeFS = "mode-server-fs"
globalMinioModeErasureSD = "mode-server-xl-single"
globalMinioModeErasure = "mode-server-xl"
globalMinioModeDistErasure = "mode-server-distributed-xl"
globalDirSuffix = "__XLDIR__"
globalDirSuffixWithSlash = globalDirSuffix + slashSeparator
// Add new global values here.
)
const (
// Limit fields size (except file) to 1Mib since Policy document
// can reach that size according to https://aws.amazon.com/articles/1434
maxFormFieldSize = int64(1 * humanize.MiByte)
// The maximum allowed time difference between the incoming request
// date and server date during signature verification.
globalMaxSkewTime = 15 * time.Minute // 15 minutes skew allowed.
// GlobalStaleUploadsExpiry - Expiry duration after which the uploads in multipart,
// tmp directory are deemed stale.
GlobalStaleUploadsExpiry = time.Hour * 24 // 24 hrs.
// GlobalStaleUploadsCleanupInterval - Cleanup interval when the stale uploads cleanup is initiated.
GlobalStaleUploadsCleanupInterval = time.Hour * 6 // 6 hrs.
// Refresh interval to update in-memory iam config cache.
globalRefreshIAMInterval = 10 * time.Minute
// Limit of location constraint XML for unauthenticated PUT bucket operations.
maxLocationConstraintSize = 3 * humanize.MiByte
// Maximum size of default bucket encryption configuration allowed
maxBucketSSEConfigSize = 1 * humanize.MiByte
// diskFillFraction is the fraction of a disk we allow to be filled.
diskFillFraction = 0.99
// diskReserveFraction is the fraction of a disk where we will fill other server pools first.
// If all pools reach this, we will use all pools with regular placement.
diskReserveFraction = 0.15
// diskAssumeUnknownSize is the size to assume when an unknown size upload is requested.
diskAssumeUnknownSize = 1 << 30
// diskMinInodes is the minimum number of inodes we want free on a disk to perform writes.
diskMinInodes = 1000
// tlsClientSessionCacheSize is the cache size for client sessions.
tlsClientSessionCacheSize = 100
)
func init() {
// Injected to prevent circular dependency.
pubsub.GetByteBuffer = grid.GetByteBuffer
}
type poolDisksLayout struct {
cmdline string
layout [][]string
}
type disksLayout struct {
legacy bool
pools []poolDisksLayout
}
type serverCtxt struct {
JSON, Quiet bool
Anonymous bool
StrictS3Compat bool
Addr, ConsoleAddr string
ConfigDir, CertsDir string
configDirSet, certsDirSet bool
Interface string
RootUser, RootPwd string
FTP []string
SFTP []string
MemLimit uint64
UserTimeout time.Duration
IdleTimeout time.Duration
ReadHeaderTimeout time.Duration
MaxIdleConnsPerHost int
SendBufSize, RecvBufSize int
CrossDomainXML string
// The layout of disks as interpreted
Layout disksLayout
}
var (
// Global user opts context
globalServerCtxt serverCtxt
// Indicates whether the running Silo server is a distributed setup.
globalIsDistErasure = false
// Indicates whether the running Silo server is an erasure-code backend.
globalIsErasure = false
// Indicates whether the running Silo server is in single-drive XL mode.
globalIsErasureSD = false
// Indicates if server code should go through testing path.
globalIsTesting = false
// This flag is set to 'true' by default
globalBrowserEnabled = true
// Custom browser redirect URL, not set by default
// and it is automatically deduced.
globalBrowserRedirectURL *xnet.URL
// Disable redirect, default is enabled.
globalBrowserRedirect bool
// globalBrowserConfig Browser user configurable settings
globalBrowserConfig browser.Config
// Silo permanently disables inherited in-place updates.
globalInplaceUpdateDisabled = true
// Captures site name and region
globalSite config.Site
// MinIO local server address (in `host:port` format)
globalMinioAddr = ""
// MinIO default port, can be changed through command line.
globalMinioPort = GlobalMinioDefaultPort
globalMinioConsolePort = "13333"
// Holds the host that was passed using --address
globalMinioHost = ""
// Holds the host that was passed using --console-address
globalMinioConsoleHost = ""
// Holds the possible host endpoint.
globalMinioEndpoint = ""
globalMinioEndpointURL *xnet.URL
// globalConfigSys server config system.
globalConfigSys *ConfigSys
globalNotificationSys *NotificationSys
globalEventNotifier *EventNotifier
globalNotifyTargetList *event.TargetList
globalLambdaTargetList *levent.TargetList
globalBucketMetadataSys *BucketMetadataSys
globalBucketMonitor *bandwidth.Monitor
globalPolicySys *PolicySys
globalIAMSys *IAMSys
globalBytePoolCap atomic.Pointer[bpool.BytePoolCap]
globalLifecycleSys *LifecycleSys
globalBucketSSEConfigSys *BucketSSEConfigSys
globalBucketTargetSys *BucketTargetSys
// globalAPIConfig controls S3 API requests throttling,
// healthCheck readiness deadlines and cors settings.
globalAPIConfig = apiConfig{listQuorum: "strict", rootAccess: true}
globalStorageClass storageclass.Config
globalAuthNPlugin *idplugin.AuthNPlugin
// CA root certificates, a nil value means system certs pool will be used
globalRootCAs *x509.CertPool
// IsSSL indicates if the server is configured with SSL.
globalIsTLS bool
globalTLSCerts *certs.Manager
globalHTTPServer *xhttp.Server
globalTCPOptions xhttp.TCPOptions
globalHTTPServerErrorCh = make(chan error)
globalOSSignalCh = make(chan os.Signal, 1)
// global Trace system to send HTTP request/response
// and Storage/OS calls info to registered listeners.
globalTrace = pubsub.New[madmin.TraceInfo, madmin.TraceType](8)
// global Listen system to send S3 API events to registered listeners
globalHTTPListen = pubsub.New[event.Event, pubsub.Mask](0)
// global console system to send console logs to
// registered listeners
globalConsoleSys *HTTPConsoleLoggerSys
// All unique drives for this deployment
globalEndpoints EndpointServerPools
// All unique nodes for this deployment
globalNodes []Node
// The name of this local node, fetched from arguments
globalLocalNodeName string
globalLocalNodeNameHex string
globalNodeNamesHex = make(map[string]struct{})
// The global subnet config
globalSubnetConfig subnet.Config
// The global callhome config
globalCallhomeConfig callhome.Config
// The global drive config
globalDriveConfig drive.Config
// Global server's network statistics
globalConnStats = newConnStats()
// Global HTTP request statistics
globalHTTPStats = newHTTPStats()
// Global bucket network and API statistics
globalBucketConnStats = newBucketConnStats()
globalBucketHTTPStats = newBucketHTTPStats()
// Time when the server is started
globalBootTime = UTCNow()
globalActiveCred auth.Credentials
globalNodeAuthToken string
globalSiteReplicatorCred siteReplicatorCred
// Captures if root credentials are set via ENV.
globalCredViaEnv bool
globalPublicCerts []*x509.Certificate
globalDomainNames []string // Root domains for virtual host style requests
globalDomainIPs set.StringSet // Root domain IP address(s) for a distributed MinIO deployment
globalOperationTimeout = newDynamicTimeout(10*time.Minute, 5*time.Minute) // default timeout for general ops
globalDeleteOperationTimeout = newDynamicTimeout(5*time.Minute, 1*time.Minute) // default time for delete ops
globalBucketObjectLockSys *BucketObjectLockSys
globalBucketQuotaSys *BucketQuotaSys
globalBucketVersioningSys *BucketVersioningSys
// Allocated etcd endpoint for config and bucket DNS.
globalEtcdClient *etcd.Client
// Cluster replication manager.
globalSiteReplicationSys SiteReplicationSys
// Cluster replication resync metrics
globalSiteResyncMetrics *siteResyncMetrics
// Is set to true when Bucket federation is requested
// and is 'true' when etcdConfig.PathPrefix is empty
globalBucketFederation bool
// Allocated DNS config wrapper over etcd client.
globalDNSConfig dns.Store
// GlobalKMS initialized KMS configuration
GlobalKMS *kms.KMS
// Common lock for various subsystems performing the leader tasks
globalLeaderLock *sharedLock
// Auto-Encryption, if enabled, turns any non-SSE-C request
// into an SSE-S3 request. If enabled a valid, non-empty KMS
// configuration must be present.
globalAutoEncryption bool
// Is compression enabled?
globalCompressConfigMu sync.Mutex
globalCompressConfig compress.Config
// Some standard object extensions which we strictly dis-allow for compression.
standardExcludeCompressExtensions = []string{".gz", ".bz2", ".rar", ".zip", ".7z", ".xz", ".mp4", ".mkv", ".mov", ".jpg", ".png", ".gif"}
// Some standard content-types which we strictly dis-allow for compression.
standardExcludeCompressContentTypes = []string{"video/*", "audio/*", "application/zip", "application/x-gzip", "application/x-zip-compressed", " application/x-compress", "application/x-spoon"}
// AuthZ Plugin system.
globalAuthZPlugin *polplugin.AuthZPlugin
// Deployment ID - unique per deployment
globalDeploymentIDPtr atomic.Pointer[string]
globalDeploymentID = func() string {
ptr := globalDeploymentIDPtr.Load()
if ptr == nil {
return ""
}
return *ptr
}
globalAllHealState = newHealState(GlobalContext, true)
// The always present healing routine ready to heal objects
globalBackgroundHealRoutine = newHealRoutine()
globalBackgroundHealState = newHealState(GlobalContext, false)
globalMRFState = newMRFState()
// If writes to FS backend should be O_SYNC.
globalFSOSync bool
globalProxyEndpoints []ProxyEndpoint
globalInternodeTransport http.RoundTripper
globalRemoteTargetTransport http.RoundTripper
globalDNSCache = &dnscache.Resolver{
Timeout: 5 * time.Second,
}
globalForwarder *handlers.Forwarder
globalTierConfigMgr *TierConfigMgr
globalConsoleSrv *consoleapi.Server
// handles service freeze or un-freeze S3 API calls.
globalServiceFreeze atomic.Value
// Only needed for tracking
globalServiceFreezeCnt int32
globalServiceFreezeMu sync.Mutex // Updates.
// Map of local drives to this node, this is set during server startup,
// disk reconnect and mutated by HealFormat. Hold globalLocalDrivesMu to access.
globalLocalDrivesMap map[string]StorageAPI
globalLocalDrivesMu sync.RWMutex
globalDriveMonitoring = env.Get("_MINIO_DRIVE_ACTIVE_MONITORING", config.EnableOn) == config.EnableOn
// Is MINIO_CI_CD set?
globalIsCICD bool
globalRootDiskThreshold uint64
// Used for collecting stats for netperf
globalNetPerfMinDuration = time.Second * 10
globalNetPerfRX netPerfRX
globalSiteNetPerfRX netPerfRX
globalObjectPerfBucket = "minio-perf-test-tmp-bucket"
globalObjectPerfUserMetadata = "X-Amz-Meta-Minio-Object-Perf" // Clients can set this to bypass S3 API service freeze. Used by object pref tests.
// MinIO version unix timestamp
globalVersionUnix uint64
// MinIO client
globalMinioClient *minio.Client
// dynamic sleeper to avoid thundering herd for trash folder expunge routine
deleteCleanupSleeper = newDynamicSleeper(5, 25*time.Millisecond, false)
// dynamic sleeper for multipart expiration routine
deleteMultipartCleanupSleeper = newDynamicSleeper(5, 25*time.Millisecond, false)
// Is MINIO_SYNC_BOOT set?
globalEnableSyncBoot bool
// Contains NIC interface name used for internode communication
globalInternodeInterface string
globalInternodeInterfaceOnce sync.Once
// Set last client perf extra time (get lock, and validate)
globalLastClientPerfExtraTime int64
// Captures all batch jobs metrics globally
globalBatchJobsMetrics batchJobMetrics
// Indicates if server was started as `--address ":0"`
globalDynamicAPIPort bool
// Add new variable global values here.
)
var globalAuthPluginMutex sync.Mutex
func newGlobalAuthNPluginFn() *idplugin.AuthNPlugin {
globalAuthPluginMutex.Lock()
defer globalAuthPluginMutex.Unlock()
return globalAuthNPlugin
}
func newGlobalAuthZPluginFn() *polplugin.AuthZPlugin {
globalAuthPluginMutex.Lock()
defer globalAuthPluginMutex.Unlock()
return globalAuthZPlugin
}
func setGlobalAuthNPlugin(authn *idplugin.AuthNPlugin) {
globalAuthPluginMutex.Lock()
globalAuthNPlugin = authn
globalAuthPluginMutex.Unlock()
}
func setGlobalAuthZPlugin(authz *polplugin.AuthZPlugin) {
globalAuthPluginMutex.Lock()
globalAuthZPlugin = authz
globalAuthPluginMutex.Unlock()
}
var errSelfTestFailure = errors.New("self test failed. unsafe to start server")