package command

import (
	"context"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"slices"
	"strings"
	"sync"
	"time"

	containerddefaults "github.com/containerd/containerd/v2/defaults"
	"github.com/containerd/containerd/v2/pkg/tracing"
	"github.com/containerd/log"
	"github.com/docker/go-connections/tlsconfig"
	"github.com/moby/buildkit/session"
	"github.com/moby/buildkit/util/tracing/detect"
	"github.com/moby/moby/v2/daemon"
	buildbackend "github.com/moby/moby/v2/daemon/builder/backend"
	"github.com/moby/moby/v2/daemon/builder/dockerfile"
	"github.com/moby/moby/v2/daemon/cluster"
	"github.com/moby/moby/v2/daemon/command/debug"
	"github.com/moby/moby/v2/daemon/command/trap"
	"github.com/moby/moby/v2/daemon/config"
	buildkit "github.com/moby/moby/v2/daemon/internal/builder-next"
	"github.com/moby/moby/v2/daemon/internal/builder-next/exporter"
	"github.com/moby/moby/v2/daemon/internal/libcontainerd/supervisor"
	"github.com/moby/moby/v2/daemon/internal/otelutil"
	"github.com/moby/moby/v2/daemon/internal/rootless"
	"github.com/moby/moby/v2/daemon/listeners"
	dopts "github.com/moby/moby/v2/daemon/pkg/opts"
	"github.com/moby/moby/v2/daemon/pkg/plugin"
	apiserver "github.com/moby/moby/v2/daemon/server"
	"github.com/moby/moby/v2/daemon/server/middleware"
	"github.com/moby/moby/v2/daemon/server/router"
	"github.com/moby/moby/v2/daemon/server/router/build"
	checkpointrouter "github.com/moby/moby/v2/daemon/server/router/checkpoint"
	"github.com/moby/moby/v2/daemon/server/router/container"
	debugrouter "github.com/moby/moby/v2/daemon/server/router/debug"
	distributionrouter "github.com/moby/moby/v2/daemon/server/router/distribution"
	grpcrouter "github.com/moby/moby/v2/daemon/server/router/grpc" //nolint:staticcheck // Deprecated endpoint kept for backward compatibility
	"github.com/moby/moby/v2/daemon/server/router/image"
	"github.com/moby/moby/v2/daemon/server/router/network"
	pluginrouter "github.com/moby/moby/v2/daemon/server/router/plugin"
	sessionrouter "github.com/moby/moby/v2/daemon/server/router/session"
	swarmrouter "github.com/moby/moby/v2/daemon/server/router/swarm"
	systemrouter "github.com/moby/moby/v2/daemon/server/router/system"
	"github.com/moby/moby/v2/daemon/server/router/volume"
	"github.com/moby/moby/v2/dockerversion"
	"github.com/moby/moby/v2/pkg/authorization"
	"github.com/moby/moby/v2/pkg/homedir"
	"github.com/moby/moby/v2/pkg/pidfile"
	"github.com/moby/moby/v2/pkg/plugingetter"
	"github.com/moby/sys/userns"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/bridge/opencensus"
	"go.opentelemetry.io/otel/propagation"
	"tags.cncf.io/container-device-interface/pkg/cdi"
)

// daemonCLI represents the daemon CLI.
type daemonCLI struct {
	*config.Config
	configFile *string
	flags      *pflag.FlagSet

	d               *daemon.Daemon
	authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins

	stopOnce     sync.Once
	apiShutdown  chan struct{}
	apiTLSConfig *tls.Config
}

// newDaemonCLI returns a daemon CLI with the given options.
func newDaemonCLI(opts *daemonOptions) (*daemonCLI, error) {
	cfg, err := loadDaemonCliConfig(opts)
	if err != nil {
		return nil, err
	}

	tlsConfig, err := newAPIServerTLSConfig(cfg)
	if err != nil {
		return nil, err
	}

	if opts.Validate {
		// Verify platform-specific requirements. This is checked early so
		// that `dockerd --validate` also validates system requirements.
		// We only validate when explicitly asked, to allow (un)registering
		// the service (`dockerd --register-service`, `dockerd --unregister-service`)
		// on Windows to succeed. See https://github.com/moby/moby/issues/51997
		//
		// The same check is also performed on start.
		if err := daemon.CheckSystem(); err != nil {
			return nil, fmt.Errorf("system requirements not met: %w", err)
		}
	}

	return &daemonCLI{
		Config:       cfg,
		configFile:   &opts.configFile,
		flags:        opts.flags,
		apiShutdown:  make(chan struct{}),
		apiTLSConfig: tlsConfig,
	}, nil
}

func (cli *daemonCLI) start(ctx context.Context) (retErr error) {
	if err := daemon.CheckSystem(); err != nil {
		return fmt.Errorf("system requirements not met: %w", err)
	}
	configureProxyEnv(ctx, cli.Config.Proxies)
	if err := configureDaemonLogs(ctx, cli.Config.DaemonLogConfig); err != nil {
		return fmt.Errorf("failed to configure daemon logging: %w", err)
	}

	log.G(ctx).Info("Starting up")
	defer func() {
		l := log.G(ctx)
		if retErr != nil && !errors.Is(retErr, context.Canceled) {
			l = l.WithError(retErr)
		}
		l.Info("Daemon shutdown complete")
	}()

	if cli.Config.Debug {
		debug.Enable()
	}

	if rootless.RunningWithRootlessKit() && !cli.Config.IsRootless() {
		return errors.New("rootless mode needs to be enabled for running with RootlessKit")
	}

	// return human-friendly error before creating files
	if runtime.GOOS == "linux" && os.Geteuid() != 0 {
		return errors.New("dockerd needs to be started with root privileges. To run dockerd in rootless mode as an unprivileged user, see https://docs.docker.com/go/rootless/")
	}

	if err := setDefaultUmask(); err != nil {
		return err
	}

	// Create the daemon root before we create ANY other files (PID, or migrate keys)
	// to ensure the appropriate ACL is set (particularly relevant on Windows)
	if err := daemon.CreateDaemonRoot(cli.Config); err != nil {
		return err
	}

	if err := os.MkdirAll(cli.Config.ExecRoot, 0o700); err != nil {
		return err
	}

	potentiallyUnderRuntimeDir := []string{cli.Config.ExecRoot}

	if cli.Pidfile != "" {
		if err := os.MkdirAll(filepath.Dir(cli.Pidfile), 0o755); err != nil {
			return errors.Wrap(err, "failed to create pidfile directory")
		}
		if err := pidfile.Write(cli.Pidfile, os.Getpid()); err != nil {
			return errors.Wrapf(err, "failed to start daemon, ensure docker is not running or delete %s", cli.Pidfile)
		}
		potentiallyUnderRuntimeDir = append(potentiallyUnderRuntimeDir, cli.Pidfile)
		defer func() {
			if err := os.Remove(cli.Pidfile); err != nil {
				log.G(ctx).Error(err)
			}
		}()
	}

	if cli.Config.IsRootless() {
		log.G(ctx).Warn("Running in rootless mode. This mode has feature limitations.")
		if rootless.RunningWithRootlessKit() {
			log.G(ctx).Info("Running with RootlessKit integration")
		}

		// Set sticky bit if XDG_RUNTIME_DIR is set && the file is actually under XDG_RUNTIME_DIR
		if _, err := homedir.StickRuntimeDirContents(potentiallyUnderRuntimeDir); err != nil {
			// StickRuntimeDirContents returns nil error if XDG_RUNTIME_DIR is just unset
			log.G(ctx).WithError(err).Warn("cannot set sticky bit on files under XDG_RUNTIME_DIR")
		}
	}
	if cli.Config.Experimental {
		log.G(ctx).Warn("Running with experimental features enabled")
	}

	lss, hosts, err := loadListeners(cli.Config, cli.apiTLSConfig)
	if err != nil {
		return errors.Wrap(err, "failed to load listeners")
	}

	ctx, cancel := context.WithCancel(ctx)
	waitForContainerDShutdown, err := cli.initContainerd(ctx)
	if waitForContainerDShutdown != nil {
		defer waitForContainerDShutdown(10 * time.Second)
	}
	if err != nil {
		cancel()
		return err
	}
	defer cancel()

	httpServer := &http.Server{
		ReadHeaderTimeout: 5 * time.Minute, // "G112: Potential Slowloris Attack (gosec)"; not a real concern for our use, so setting a long timeout.
	}
	apiShutdownCtx, apiShutdownCancel := context.WithCancel(context.WithoutCancel(ctx))
	apiShutdownDone := make(chan struct{})
	trap.Trap(cli.stop)
	go func() {
		// Block until cli.stop() has been called.
		// It may have already been called, and that's okay.
		// Any httpServer.Serve() calls made after
		// httpServer.Shutdown() will return immediately,
		// which is what we want.
		<-cli.apiShutdown
		if err := httpServer.Shutdown(apiShutdownCtx); err != nil {
			log.G(ctx).WithError(err).Error("Error shutting down http server")
		}
		close(apiShutdownDone)
	}()
	defer func() {
		select {
		case <-cli.apiShutdown:
			// cli.stop() has been called and the daemon has completed
			// shutting down. Give the HTTP server a little more time to
			// finish handling any outstanding requests if needed.
			tmr := time.AfterFunc(5*time.Second, apiShutdownCancel)
			defer tmr.Stop()
			<-apiShutdownDone
		default:
			// cli.start() has returned without cli.stop() being called,
			// e.g. because the daemon failed to start.
			// Stop the HTTP server with no grace period.
			if err := httpServer.Close(); err != nil {
				log.G(ctx).WithError(err).Error("Error closing http server")
			}
		}
	}()

	// Notify that the API is active, but before daemon is set up.
	if err := preNotifyReady(); err != nil {
		return err
	}

	const otelServiceNameEnv = "OTEL_SERVICE_NAME"
	if _, ok := os.LookupEnv(otelServiceNameEnv); !ok {
		_ = os.Setenv(otelServiceNameEnv, filepath.Base(os.Args[0]))
	}

	setOTLPProtoDefault()
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))

	// Initialize the trace recorder for buildkit.
	detect.Recorder = detect.NewTraceRecorder()

	tp, otelShutdown := otelutil.NewTracerProvider(ctx, true)
	otel.SetTracerProvider(tp)
	log.G(ctx).Logger.AddHook(tracing.NewLogrusHook())
	// The github.com/microsoft/hcsshim module is instrumented with
	// OpenCensus, but we use OpenTelemetry for tracing in the daemon.
	// Bridge OpenCensus to OpenTelemetry so OC trace spans are exported to
	// the daemon's configured OTEL collector.
	opencensus.InstallTraceBridge()

	pluginStore := plugin.NewStore()

	// Register the CDI driver before the daemon starts, as it might try to restore containers that depend on the CDI driver.
	// Note that CDI is not inherently linux-specific, there are some linux-specific assumptions / implementations in the code that
	// queries the properties of device on the host as well as performs the injection of device nodes and their access permissions into the OCI spec.
	//
	// In order to lift this restriction the following would have to be addressed:
	// - Support needs to be added to the cdi package for injecting Windows devices: https://tags.cncf.io/container-device-interface/issues/28
	// - The DeviceRequests API must be extended to non-linux platforms.
	var cdiCache *cdi.Cache
	if cdiEnabled(cli.Config) {
		cdiCache = daemon.RegisterCDIDriver(cli.Config.CDISpecDirs...)
	}

	daemon.RegisterGPUDeviceDrivers(cdiCache)

	var apiServer apiserver.Server
	authz, err := initMiddlewares(ctx, &apiServer, cli.Config, pluginStore)
	if err != nil {
		return errors.Wrap(err, "failed to start API server")
	}
	cli.authzMiddleware = authz

	d, err := daemon.NewDaemon(ctx, cli.Config, pluginStore, cli.authzMiddleware)
	if err != nil {
		return errors.Wrap(err, "failed to start daemon")
	}

	d.StoreHosts(hosts)

	// validate after NewDaemon has restored enabled plugins. Don't change order.
	if err := validateAuthzPlugins(cli.Config.AuthorizationPlugins, pluginStore); err != nil {
		return errors.Wrap(err, "failed to validate authorization plugin")
	}

	cli.d = d

	if err := startMetricsServer(cli.Config.MetricsAddress); err != nil {
		return errors.Wrap(err, "failed to start metrics server")
	}

	c, err := createAndStartCluster(d, cli.Config)
	if err != nil {
		return fmt.Errorf("failed to start cluster component: %w", err)
	}

	// Restart all autostart containers which has a swarm endpoint
	// and is not yet running now that we have successfully
	// initialized the cluster.
	d.RestartSwarmContainers()

	b, shutdownBuildKit, err := initBuildkit(ctx, d, cdiCache)
	if err != nil {
		return fmt.Errorf("error initializing buildkit: %w", err)
	}

	if runtime.GOOS == "windows" {
		if enabled, ok := d.Features()["buildkit"]; ok && enabled {
			log.G(ctx).Warn("Buildkit feature is enabled in the daemon.json configuration file. Support for BuildKit on Windows is experimental, and enabling this feature may not work. Use at your own risk!")
		}
	}

	// Enable HTTP/1, HTTP/2 and h2c on the HTTP server. h2c won't be used for *tls.Conn listeners, and HTTP/2 won't be
	// used for non-TLS connections.
	var p http.Protocols
	p.SetHTTP1(true)
	p.SetHTTP2(true)
	p.SetUnencryptedHTTP2(true)

	routers := buildRouters(routerOptions{
		features: d.Features,
		daemon:   d,
		cluster:  c,
		builder:  b,
	})
	gs := newGRPCServer(ctx)
	b.backend.RegisterGRPC(gs)
	httpServer.Protocols = &p
	httpServer.Handler = newHTTPHandler(ctx, gs, apiServer.CreateMux(ctx, routers...))

	go d.ProcessClusterNotifications(ctx, c.GetWatchStream())

	cli.setupConfigReloadTrap()

	log.G(ctx).Info("Daemon has completed initialization")

	// Daemon is fully initialized. Start handling API traffic
	// and wait for serve API to complete.
	var (
		apiWG      sync.WaitGroup
		errAPI     = make(chan error, 1)
		apiStartWG sync.WaitGroup
	)

	apiStartWG.Add(len(lss))
	for _, ls := range lss {
		apiWG.Go(func() {
			log.G(ctx).Infof("API listen on %s", ls.Addr())
			apiStartWG.Done()
			if err := httpServer.Serve(ls); err != nil && !errors.Is(err, http.ErrServerClosed) {
				log.G(ctx).WithFields(log.Fields{
					"error":    err,
					"listener": ls.Addr(),
				}).Error("ServeAPI error")

				select {
				case errAPI <- err:
				default:
				}
			}
		})
	}

	// Wait for all API listeners to start handling requests.
	apiStartWG.Wait()

	select {
	case <-errAPI:
		// An API listener failed to start; skip notifying systemd that we're ready.
	default:
		// All API listeners started handling requests; notify systemd that we're ready.
		notifyReady()
	}

	apiWG.Wait()
	close(errAPI)

	c.Cleanup()

	// notify systemd that we're shutting down
	notifyStopping()
	shutdownDaemon(ctx, d)

	// shutdown / close BuildKit backend
	shutdownBuildKit()

	// Stop notification processing and any background processes
	cancel()

	if err, ok := <-errAPI; ok {
		return errors.Wrap(err, "shutting down due to ServeAPI error")
	}

	if err := otelShutdown(context.WithoutCancel(ctx)); err != nil {
		log.G(ctx).WithError(err).Error("Failed to shutdown OTEL tracing")
	}

	return nil
}

// The buildkit "detect" package uses grpc as the default proto, which is in conformance with the old spec.
// For a little while now http/protobuf is the default spec, so this function sets the protocol to http/protobuf when the env var is unset
// so that the detect package will use http/protobuf as a default.
// TODO: This can be removed after buildkit is updated to use http/protobuf as the default.
func setOTLPProtoDefault() {
	const (
		tracesEnv  = "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL"
		metricsEnv = "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL"
		protoEnv   = "OTEL_EXPORTER_OTLP_PROTOCOL"

		defaultProto = "http/protobuf"
	)

	if os.Getenv(protoEnv) == "" {
		if os.Getenv(tracesEnv) == "" {
			_ = os.Setenv(tracesEnv, defaultProto)
		}
		if os.Getenv(metricsEnv) == "" {
			_ = os.Setenv(metricsEnv, defaultProto)
		}
	}
}

func initBuildkit(ctx context.Context, d *daemon.Daemon, cdiCache *cdi.Cache) (_ builderOptions, closeFn func(), _ error) {
	log.G(ctx).Info("Initializing buildkit")
	closeFn = func() {}

	sm, err := session.NewManager()
	if err != nil {
		return builderOptions{}, closeFn, errors.Wrap(err, "failed to create sessionmanager")
	}

	manager, err := dockerfile.NewBuildManager(d.BuilderBackend(), d.IdentityMapping())
	if err != nil {
		return builderOptions{}, closeFn, err
	}

	cfg := d.Config()

	bk, err := buildkit.New(ctx, buildkit.Opt{
		SessionManager:      sm,
		Root:                filepath.Join(cfg.Root, "buildkit"),
		EngineID:            d.ID(),
		Dist:                d.DistributionServices(),
		ImageTagger:         d.ImageService(),
		NetworkController:   d.NetworkController(),
		DefaultCgroupParent: newCgroupParent(&cfg),
		RegistryHosts:       d.RegistryHosts,
		BuilderConfig:       cfg.Builder,
		Rootless:            daemon.Rootless(&cfg),
		IdentityMapping:     d.IdentityMapping(),
		DNSConfig:           cfg.DNSConfig,
		ApparmorProfile:     daemon.DefaultApparmorProfile(),
		UseSnapshotter:      d.UsesSnapshotter(),
		Snapshotter:         d.ImageService().StorageDriver(),
		ContainerdAddress:   cfg.ContainerdAddr,
		ContainerdNamespace: cfg.ContainerdNamespace,
		HyperVIsolation:     d.DefaultIsolation().IsHyperV(),
		Callbacks: exporter.BuildkitCallbacks{
			Exported: d.ImageExportedByBuildkit,
			Named:    d.ImageNamedByBuildkit,
		},
		CDICache: cdiCache,
	})
	if err != nil {
		return builderOptions{}, closeFn, errors.Wrap(err, "error creating buildkit instance")
	}

	bb, err := buildbackend.NewBackend(d.ImageService(), manager, bk, d.EventsService)
	if err != nil {
		return builderOptions{}, closeFn, errors.Wrap(err, "failed to create builder backend")
	}

	log.G(ctx).Info("Completed buildkit initialization")

	closeFn = func() {
		if err := bk.Close(); err != nil {
			log.G(ctx).WithError(err).Error("Failed to close buildkit")
		}
	}

	return builderOptions{
		backend:        bb,
		buildkit:       bk,
		sessionManager: sm,
	}, closeFn, nil
}

type routerOptions struct {
	features func() map[string]bool
	daemon   *daemon.Daemon
	cluster  *cluster.Cluster
	builder  builderOptions
}

type builderOptions struct {
	backend        *buildbackend.Backend
	buildkit       *buildkit.Builder
	sessionManager *session.Manager
}

func (cli *daemonCLI) reloadConfig() {
	ctx := context.TODO()
	log.G(ctx).WithField("config-file", *cli.configFile).Info("Got signal to reload configuration")
	reload := func(cfg *config.Config) {
		if err := validateAuthzPlugins(cfg.AuthorizationPlugins, cli.d.PluginStore); err != nil {
			log.G(ctx).WithError(err).Fatal("Error validating authorization plugin")
			return
		}

		if err := cli.d.Reload(cfg); err != nil {
			log.G(ctx).WithError(err).Error("Error reconfiguring the daemon")
			return
		}

		// Apply our own configuration only after the daemon reload has succeeded. We
		// don't want to partially apply the config if the daemon is unhappy with it.

		cli.authzMiddleware.SetPlugins(cfg.AuthorizationPlugins)

		if cfg.IsValueSet("debug") {
			debugEnabled := debug.IsEnabled()
			switch {
			case debugEnabled && !cfg.Debug: // disable debug
				debug.Disable()
			case cfg.Debug && !debugEnabled: // enable debug
				debug.Enable()
			}
		}
	}

	// On Linux, we use sd_notify to indicate we're reloading config. We send
	// this signal as early as possible to let systemd know we're reloading,
	// but must signal "ready" after this completes (even on failure), which
	// is done by the reload function defined above.
	done := notifyReloading()
	defer done()

	if err := config.Reload(*cli.configFile, cli.flags, reload); err != nil {
		log.G(ctx).WithError(err).Error("Error reloading configuration")
		return
	}

	sanitizedConfig := config.Sanitize(cli.d.Config())
	jsonData, err := json.Marshal(sanitizedConfig)
	if err != nil {
		log.G(context.TODO()).WithError(err).Warn("Error when marshaling configuration for printing")
		log.G(context.TODO()).Info("Reloaded configuration")
	} else {
		log.G(context.TODO()).WithField("config", string(jsonData)).Info("Reloaded configuration")
	}
}

func (cli *daemonCLI) stop() {
	// Signal that the API server should shut down as soon as possible.
	// This construct is used rather than directly shutting down the HTTP
	// server to avoid any issues if this method is called before the server
	// has been instantiated in cli.start(). If this method is called first,
	// the HTTP server will be shut down immediately upon instantiation.
	cli.stopOnce.Do(func() {
		close(cli.apiShutdown)
	})
}

// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
// d.Shutdown() is waiting too long to kill container or worst it's
// blocked there
func shutdownDaemon(ctx context.Context, d *daemon.Daemon) {
	var cancel context.CancelFunc
	if timeout := d.ShutdownTimeout(); timeout >= 0 {
		ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
	} else {
		ctx, cancel = context.WithCancel(ctx)
	}

	go func() {
		defer cancel()
		d.Shutdown(ctx)
	}()

	<-ctx.Done()
	if errors.Is(ctx.Err(), context.DeadlineExceeded) {
		log.G(ctx).Error("Force shutdown daemon")
	} else {
		log.G(ctx).Debug("Clean shutdown succeeded")
	}
}

func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
	if !opts.flags.Parsed() {
		return nil, errors.New(`cannot load CLI config before flags are parsed`)
	}
	opts.setDefaultOptions()

	conf := opts.daemonConfig
	flags := opts.flags
	conf.Debug = opts.Debug
	conf.Hosts = opts.Hosts

	// The DOCKER_MIN_API_VERSION env-var allows overriding the minimum API
	// version provided by the daemon within constraints of the minimum and
	// maximum (current) supported API versions.
	//
	// API versions older than [config.defaultMinAPIVersion] are deprecated and
	// to be removed in a future release. The "DOCKER_MIN_API_VERSION" env-var
	// should only be used for exceptional cases.
	if ver := os.Getenv("DOCKER_MIN_API_VERSION"); ver != "" {
		if err := config.ValidateMinAPIVersion(ver); err != nil {
			return nil, errors.Wrap(err, "invalid DOCKER_MIN_API_VERSION")
		}
		conf.MinAPIVersion = ver
	}

	if flags.Changed(FlagTLS) {
		conf.TLS = &opts.TLS
	}
	if flags.Changed(FlagTLSVerify) {
		conf.TLSVerify = &opts.TLSVerify
		v := true
		conf.TLS = &v
	}

	if opts.TLSOptions != nil {
		conf.TLSOptions = config.TLSOptions{
			CAFile:   opts.TLSOptions.CAFile,
			CertFile: opts.TLSOptions.CertFile,
			KeyFile:  opts.TLSOptions.KeyFile,
		}
	} else {
		conf.TLSOptions = config.TLSOptions{}
	}

	if runtime.GOOS == "windows" && opts.configFile == "" {
		// On Windows, the location of the config-file is relative to the
		// daemon's data-root, which is configurable, so we cannot use a
		// fixed default location. Instead, we set the location here.
		//
		// FIXME(thaJeztah): find a better default on Windows that does not depend on "daemon.json" or the --data-root option.
		opts.configFile = filepath.Join(conf.Root, "config", "daemon.json")
	}

	if opts.configFile != "" {
		c, err := config.MergeDaemonConfigurations(conf, flags, opts.configFile)
		if err != nil {
			if flags.Changed("config-file") || !os.IsNotExist(err) {
				return nil, errors.Wrapf(err, "unable to configure the Docker daemon with file %s", opts.configFile)
			}
		}

		// the merged configuration can be nil if the config file didn't exist.
		// leave the current configuration as it is if when that happens.
		if c != nil {
			conf = c
		}
	}

	// TODO(thaJeztah): consider making empty strings an error. Existing behavior allowed for empty strings to be used as default, even if explicitly set (`dockerd -H ""`).
	conf.Hosts = slices.DeleteFunc(conf.Hosts, func(h string) bool {
		return strings.TrimSpace(h) == ""
	})
	if len(conf.Hosts) == 0 {
		// Set the default host if no hosts are configured.
		// TODO(thaJeztah) can set defaults in config.New() instead?
		if conf.TLS != nil && *conf.TLS {
			// If no host is configured, but the "--tls" flag is set, we
			// default to using a TCP connection instead of a unix-socket
			// or named pipe.
			//
			// See https://github.com/moby/moby/commit/0906195fbbd6f379c163b80f23e4c5a60bcfc5f0
			conf.Hosts = append(conf.Hosts, dopts.DefaultTLSHost)
		} else {
			// Otherwise use the default unix-socket (Linux) or named pipe (Windows).
			h, err := defaultAPISocketPath(honorXDG)
			if err != nil {
				return nil, err
			}
			conf.Hosts = append(conf.Hosts, h)
		}
	}

	if err := normalizeHosts(conf); err != nil {
		return nil, err
	}

	if err := config.Validate(conf); err != nil {
		return nil, err
	}

	// Check if duplicate label-keys with different values are found
	newLabels, err := config.GetConflictFreeLabels(conf.Labels)
	if err != nil {
		return nil, err
	}
	conf.Labels = newLabels

	// Regardless of whether the user sets it to true or false, if they
	// specify TLSVerify at all then we need to turn on TLS
	if conf.IsValueSet(FlagTLSVerify) {
		v := true
		conf.TLS = &v
	}

	if conf.TLSVerify == nil && conf.TLS != nil {
		conf.TLSVerify = conf.TLS
	}

	err = validateCPURealtimeOptions(conf)
	if err != nil {
		return nil, err
	}

	if conf.CDISpecDirs == nil {
		// If the CDISpecDirs is not set at this stage, we set it to the default.
		conf.CDISpecDirs = append([]string(nil), cdi.DefaultSpecDirs...)
		if rootless.RunningWithRootlessKit() {
			// In rootless mode, we add the user-specific CDI spec directory.
			xch, err := homedir.GetConfigHome()
			if err != nil {
				return nil, err
			}
			xrd, err := homedir.GetRuntimeDir()
			if err != nil {
				return nil, err
			}
			conf.CDISpecDirs = append(conf.CDISpecDirs, filepath.Join(xch, "cdi"), filepath.Join(xrd, "cdi"))
		}
	}
	// Filter out CDI spec directories that are not readable, and log appropriately
	var cdiSpecDirs []string
	for _, dir := range conf.CDISpecDirs {
		// Non-existing directories are not filtered out here, as CDI spec directories are allowed to not exist.
		if _, err := os.ReadDir(dir); err == nil || errors.Is(err, os.ErrNotExist) {
			cdiSpecDirs = append(cdiSpecDirs, dir)
		} else {
			logLevel := log.ErrorLevel
			if userns.RunningInUserNS() && errors.Is(err, os.ErrPermission) {
				logLevel = log.DebugLevel
			}
			log.L.WithField("dir", dir).WithError(err).Log(logLevel, "CDI spec directory cannot be accessed, skipping")
		}
	}
	conf.CDISpecDirs = cdiSpecDirs
	if len(conf.CDISpecDirs) == 1 && conf.CDISpecDirs[0] == "" {
		// If CDISpecDirs is set to an empty string, we clear it to ensure that CDI is disabled.
		conf.CDISpecDirs = nil
	}
	// Only clear CDISpecDirs if CDI is explicitly disabled
	if val, exists := conf.Features["cdi"]; exists && !val {
		// If the CDI feature is explicitly disabled, we clear the CDISpecDirs to ensure that CDI is disabled.
		conf.CDISpecDirs = nil
	}

	if err := setPlatformOptions(conf); err != nil {
		return nil, err
	}

	return conf, nil
}

// defaultAPISocketPath returns the default path for the Unix socket (Linux)
// or named pipe (Windows).
//
// When running with rootlessKit, XDG dirs should be preferred, and the
// default is to listen on an unprivileged socket in [XDG_RUNTIME_DIR].
//
// [XDG_RUNTIME_DIR]: https://specifications.freedesktop.org/basedir/0.8/#variables
func defaultAPISocketPath(honorXDG bool) (string, error) {
	if honorXDG {
		runtimeDir, err := homedir.GetRuntimeDir()
		if err != nil {
			return "", err
		}
		return "unix://" + filepath.Join(runtimeDir, "docker.sock"), nil
	}

	// default unix-socket (Linux) or named pipe (Windows).
	return dopts.DefaultHost, nil
}

// normalizeHosts normalizes the configured config.Hosts and removes duplicates.
// It returns an error if it fails to parse a host.
func normalizeHosts(cfg *config.Config) error {
	if len(cfg.Hosts) == 0 {
		return errors.New("no hosts specified")
	}

	hosts := slices.Clone(cfg.Hosts)
	for i, h := range hosts {
		var err error
		hosts[i], err = dopts.ParseDaemonHost(h)
		if err != nil {
			return err
		}
	}

	slices.Sort(hosts)
	cfg.Hosts = slices.Compact(hosts)
	return nil
}

func buildRouters(opts routerOptions) []router.Router {
	routers := []router.Router{
		// we need to add the checkpoint router before the container router or the DELETE gets masked
		checkpointrouter.NewRouter(opts.daemon),
		container.NewRouter(opts.daemon),
		image.NewRouter(
			opts.daemon.ImageService(),
			opts.daemon.RegistryService(),
		),
		systemrouter.NewRouter(opts.daemon, opts.cluster, opts.builder.buildkit, opts.daemon.Features),
		volume.NewRouter(opts.daemon.VolumesService(), opts.cluster),
		build.NewRouter(opts.builder.backend, opts.daemon),
		sessionrouter.NewRouter(opts.builder.sessionManager), //nolint:staticcheck // Deprecated endpoint kept for backward compatibility
		swarmrouter.NewRouter(opts.cluster),
		pluginrouter.NewRouter(opts.daemon.PluginManager()),
		distributionrouter.NewRouter(opts.daemon.ImageBackend()),
		network.NewRouter(opts.daemon, opts.cluster),
		debugrouter.NewRouter(),
	}

	if opts.builder.backend != nil {
		routers = append(routers, grpcrouter.NewRouter(opts.builder.backend)) //nolint:staticcheck // Deprecated endpoint kept for backward compatibility
	}

	if opts.daemon.HasExperimental() {
		for _, r := range routers {
			for _, route := range r.Routes() {
				if experimental, ok := route.(router.ExperimentalRoute); ok {
					experimental.Enable()
				}
			}
		}
	}

	return routers
}

func initMiddlewares(_ context.Context, s *apiserver.Server, cfg *config.Config, pluginStore plugingetter.PluginGetter) (*authorization.Middleware, error) {
	exp := middleware.NewExperimentalMiddleware(cfg.Experimental)
	s.UseMiddleware(exp)

	vm, err := middleware.NewVersionMiddleware(dockerversion.Version, config.MaxAPIVersion, cfg.MinAPIVersion)
	if err != nil {
		return nil, err
	}
	s.UseMiddleware(*vm)

	authzMiddleware := authorization.NewMiddleware(cfg.AuthorizationPlugins, pluginStore)
	s.UseMiddleware(authzMiddleware)
	return authzMiddleware, nil
}

func getContainerdDaemonOpts(cfg *config.Config) ([]supervisor.DaemonOpt, error) {
	var opts []supervisor.DaemonOpt
	if cfg.Debug {
		opts = append(opts, supervisor.WithLogLevel("debug"))
	} else {
		opts = append(opts, supervisor.WithLogLevel(cfg.DaemonLogConfig.LogLevel))
	}

	if logFormat := cfg.DaemonLogConfig.LogFormat; logFormat != "" {
		opts = append(opts, supervisor.WithLogFormat(logFormat))
	}

	if !cfg.CriContainerd {
		// CRI support in the managed daemon is currently opt-in.
		//
		// It's disabled by default, originally because it was listening on
		// a TCP connection at 0.0.0.0:10010, which was considered a security
		// risk, and could conflict with user's container ports.
		//
		// Current versions of containerd started now listen on localhost on
		// an ephemeral port instead, but could still conflict with container
		// ports, and running kubernetes using the static binaries is not a
		// common scenario, so we (for now) continue disabling it by default.
		//
		// Also see https://github.com/containerd/containerd/issues/2483#issuecomment-407530608
		opts = append(opts, supervisor.WithCRIDisabled())
	}

	if runtime.GOOS == "windows" {
		opts = append(opts, supervisor.WithDetectLocalBinary())
	}

	return opts, nil
}

func newAPIServerTLSConfig(cfg *config.Config) (*tls.Config, error) {
	var tlsConfig *tls.Config
	if cfg.TLS != nil && *cfg.TLS {
		var (
			clientAuth tls.ClientAuthType
			err        error
		)
		if cfg.TLSVerify == nil || *cfg.TLSVerify {
			// server requires and verifies client's certificate
			clientAuth = tls.RequireAndVerifyClientCert
		}
		tlsConfig, err = tlsconfig.Server(tlsconfig.Options{
			CAFile:             cfg.TLSOptions.CAFile,
			CertFile:           cfg.TLSOptions.CertFile,
			KeyFile:            cfg.TLSOptions.KeyFile,
			ExclusiveRootPools: true,
			ClientAuth:         clientAuth,
		})
		if err != nil {
			return nil, errors.Wrap(err, "invalid TLS configuration")
		}
		tlsConfig.NextProtos = []string{"h2", "http/1.1"}
	}

	return tlsConfig, nil
}

// checkTLSAuthOK checks basically for an explicitly disabled TLS/TLSVerify
// Going forward we do not want to support a scenario where dockerd listens
// on TCP without either TLS client auth (or an explicit opt-in to disable it)
func checkTLSAuthOK(cfg *config.Config) bool {
	if cfg.TLS == nil {
		// Either TLS is enabled by default, in which case TLS verification should be enabled by default, or explicitly disabled
		// Or TLS is disabled by default... in any of these cases, we can just take the default value as to how to proceed
		return DefaultTLSValue
	}

	if !*cfg.TLS {
		// TLS is explicitly disabled, which is supported
		return true
	}

	if cfg.TLSVerify == nil {
		// this actually shouldn't happen since we set TLSVerify on the config object anyway
		// But in case it does get here, be cautious and assume this is not supported.
		return false
	}

	// Either TLSVerify is explicitly enabled or disabled, both cases are supported
	return true
}

func loadListeners(cfg *config.Config, tlsConfig *tls.Config) ([]net.Listener, []string, error) {
	ctx := context.TODO()

	if len(cfg.Hosts) == 0 {
		return nil, nil, errors.New("no hosts configured")
	}
	var (
		hosts []string
		lss   []net.Listener
	)

	for i := 0; i < len(cfg.Hosts); i++ {
		protoAddr := cfg.Hosts[i]
		proto, addr, ok := strings.Cut(protoAddr, "://")
		if !ok {
			return nil, nil, fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
		}

		// It's a bad idea to bind to TCP without tlsverify.
		authEnabled := tlsConfig != nil && tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert
		if proto == "tcp" && !authEnabled {
			log.G(ctx).WithField("host", protoAddr).Warn("Binding to IP address without --tlsverify is insecure and gives root access on this machine to everyone who has access to your network.")
			log.G(ctx).WithField("host", protoAddr).Warn("Binding to an IP address, even on localhost, can also give access to scripts run in a browser. Be safe out there!")
			log.G(ctx).WithField("host", protoAddr).Warn("[DEPRECATION NOTICE] In future versions this will be a hard failure preventing the daemon from starting! Learn more at: https://docs.docker.com/go/api-security/")
			time.Sleep(time.Second)

			// If TLSVerify is explicitly set to false we'll take that as "Please let me shoot myself in the foot"
			// We do not want to continue to support a default mode where tls verification is disabled, so we do some extra warnings here and eventually remove support
			if !checkTLSAuthOK(cfg) {
				ipAddr, _, err := net.SplitHostPort(addr)
				if err != nil {
					return nil, nil, errors.Wrap(err, "error parsing tcp address")
				}

				// shortcut all this extra stuff for literal "localhost"
				// -H supports specifying hostnames, since we want to bypass this on loopback interfaces we'll look it up here.
				if ipAddr != "localhost" {
					ip := net.ParseIP(ipAddr)
					if ip == nil {
						ipA, err := net.ResolveIPAddr("ip", ipAddr)
						if err != nil {
							log.G(ctx).WithError(err).WithField("host", ipAddr).Error("Error looking up specified host address")
						}
						if ipA != nil {
							ip = ipA.IP
						}
					}
					if ip == nil || !ip.IsLoopback() {
						log.G(ctx).WithField("host", protoAddr).Warn("Binding to an IP address without --tlsverify is deprecated. Startup is intentionally being slowed down to show this message")
						log.G(ctx).WithField("host", protoAddr).Warn("Please consider generating tls certificates with client validation to prevent exposing unauthenticated root access to your network")
						log.G(ctx).WithField("host", protoAddr).Warnf("You can override this by explicitly specifying '--%s=false' or '--%s=false'", FlagTLS, FlagTLSVerify)
						log.G(ctx).WithField("host", protoAddr).Warnf("Support for listening on TCP without authentication or explicit intent to run without authentication will be removed in the next release")

						time.Sleep(15 * time.Second)
					}
				}
			}
		}
		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
		if proto == "tcp" {
			if err := allocateDaemonPort(addr); err != nil {
				return nil, nil, err
			}
		}
		ls, err := listeners.Init(proto, addr, cfg.SocketGroup, tlsConfig)
		if err != nil {
			return nil, nil, err
		}
		log.G(ctx).Debugf("Listener created for HTTP on %s (%s)", proto, addr)
		hosts = append(hosts, addr)
		lss = append(lss, ls...)
	}

	return lss, hosts, nil
}

func createAndStartCluster(d *daemon.Daemon, cfg *config.Config) (*cluster.Cluster, error) {
	name, _ := os.Hostname()
	c, err := cluster.New(cluster.Config{
		Root:                   cfg.Root,
		Name:                   name,
		Backend:                d,
		VolumeBackend:          d.VolumesService(),
		ImageBackend:           d.ImageBackend(),
		PluginBackend:          d.PluginManager(),
		NetworkSubnetsProvider: d,
		DefaultAdvertiseAddr:   cfg.SwarmDefaultAdvertiseAddr,
		RaftHeartbeatTick:      cfg.SwarmRaftHeartbeatTick,
		RaftElectionTick:       cfg.SwarmRaftElectionTick,
		RuntimeRoot:            getSwarmRunRoot(cfg),
	})
	if err != nil {
		return nil, err
	}
	d.SetCluster(c)
	err = c.Start()

	return c, err
}

// validates that the plugins requested with the --authorization-plugin flag are valid AuthzDriver
// plugins present on the host and available to the daemon
func validateAuthzPlugins(requestedPlugins []string, pg plugingetter.PluginGetter) error {
	for _, reqPlugin := range requestedPlugins {
		if _, err := pg.Get(reqPlugin, authorization.AuthZApiImplements, plugingetter.Lookup); err != nil {
			return err
		}
	}
	return nil
}

func systemContainerdRunning(honorXDG bool) (string, bool, error) {
	addr := containerddefaults.DefaultAddress
	if honorXDG {
		runtimeDir, err := homedir.GetRuntimeDir()
		if err != nil {
			return "", false, err
		}
		addr = filepath.Join(runtimeDir, "containerd", "containerd.sock")
	}
	_, err := os.Lstat(addr)
	return addr, err == nil, nil
}

// configureDaemonLogs sets the logging level and formatting. It expects
// the passed configuration to already be validated, and ignores invalid options.
func configureDaemonLogs(ctx context.Context, conf config.DaemonLogConfig) error {
	switch conf.LogFormat {
	case log.JSONFormat:
		if err := log.SetFormat(log.JSONFormat); err != nil {
			return err
		}
	case log.TextFormat, "":
		if err := log.SetFormat(log.TextFormat); err != nil {
			return err
		}
		if conf.RawLogs {
			// FIXME(thaJeztah): this needs a better solution: containerd doesn't allow disabling colors, and this code is depending on internal knowledge of "log.SetFormat"
			if l, ok := log.L.Logger.Formatter.(*logrus.TextFormatter); ok {
				l.DisableColors = true
			}
		}
	default:
		return fmt.Errorf("unknown log format: %s", conf.LogFormat)
	}

	logLevel := conf.LogLevel
	if logLevel == "" {
		logLevel = "info"
	}
	if err := log.SetLevel(logLevel); err != nil {
		log.G(ctx).WithError(err).Warn("configure log level")
	}
	return nil
}

func configureProxyEnv(ctx context.Context, cfg config.Proxies) {
	if p := cfg.HTTPProxy; p != "" {
		overrideProxyEnv(ctx, "HTTP_PROXY", p)
		overrideProxyEnv(ctx, "http_proxy", p)
	}
	if p := cfg.HTTPSProxy; p != "" {
		overrideProxyEnv(ctx, "HTTPS_PROXY", p)
		overrideProxyEnv(ctx, "https_proxy", p)
	}
	if p := cfg.NoProxy; p != "" {
		overrideProxyEnv(ctx, "NO_PROXY", p)
		overrideProxyEnv(ctx, "no_proxy", p)
	}
}

func overrideProxyEnv(ctx context.Context, name, val string) {
	if oldVal := os.Getenv(name); oldVal != "" && oldVal != val {
		log.G(ctx).WithFields(log.Fields{
			"name":      name,
			"old-value": config.MaskCredentials(oldVal),
			"new-value": config.MaskCredentials(val),
		}).Warn("overriding existing proxy variable with value from configuration")
	}
	_ = os.Setenv(name, val)
}

func (cli *daemonCLI) initializeContainerd(ctx context.Context) (func(time.Duration) error, error) {
	systemContainerdAddr, ok, err := systemContainerdRunning(honorXDG)
	if err != nil {
		return nil, errors.Wrap(err, "could not determine whether the system containerd is running")
	}
	if ok {
		// detected a system containerd at the given address.
		cli.Config.ContainerdAddr = systemContainerdAddr
		return nil, nil
	}

	log.G(ctx).Info("containerd not running, starting managed containerd")
	opts, err := getContainerdDaemonOpts(cli.Config)
	if err != nil {
		return nil, errors.Wrap(err, "failed to generate containerd options")
	}

	r, err := supervisor.Start(ctx, filepath.Join(cli.Config.Root, "containerd"), filepath.Join(cli.Config.ExecRoot, "containerd"), opts...)
	if err != nil {
		return nil, errors.Wrap(err, "failed to start containerd")
	}
	cli.Config.ContainerdAddr = r.Address()

	// Try to wait for containerd to shutdown
	return r.WaitTimeout, nil
}

// cdiEnabled returns true if CDI feature wasn't explicitly disabled via
// features.
func cdiEnabled(conf *config.Config) bool {
	if runtime.GOOS != "linux" {
		return false
	}
	val, ok := conf.Features["cdi"]
	if !ok {
		return true
	}
	return val
}
