diff --git a/cmd/syncthing/cmdutil/options_common.go b/cmd/syncthing/cmdutil/options_common.go index 34485e6a5..0751892d8 100644 --- a/cmd/syncthing/cmdutil/options_common.go +++ b/cmd/syncthing/cmdutil/options_common.go @@ -12,4 +12,5 @@ type CommonOptions struct { ConfDir string `name:"config" placeholder:"PATH" help:"Set configuration directory (config and keys)"` HomeDir string `name:"home" placeholder:"PATH" help:"Set configuration and data directory"` NoDefaultFolder bool `env:"STNODEFAULTFOLDER" help:"Don't create the \"default\" folder on first startup"` + SkipPortProbing bool `help:"Don't try to find free ports for GUI and listen addresses on first startup"` } diff --git a/cmd/syncthing/generate/generate.go b/cmd/syncthing/generate/generate.go index 4f5c2fa14..4df7c3d46 100644 --- a/cmd/syncthing/generate/generate.go +++ b/cmd/syncthing/generate/generate.go @@ -58,13 +58,13 @@ func (c *CLI) Run() error { c.GUIPassword = string(password) } - if err := Generate(c.ConfDir, c.GUIUser, c.GUIPassword, c.NoDefaultFolder); err != nil { + if err := Generate(c.ConfDir, c.GUIUser, c.GUIPassword, c.NoDefaultFolder, c.SkipPortProbing); err != nil { return fmt.Errorf("Failed to generate config and keys: %w", err) } return nil } -func Generate(confDir, guiUser, guiPassword string, noDefaultFolder bool) error { +func Generate(confDir, guiUser, guiPassword string, noDefaultFolder, skipPortProbing bool) error { dir, err := fs.ExpandTilde(confDir) if err != nil { return err @@ -92,7 +92,7 @@ func Generate(confDir, guiUser, guiPassword string, noDefaultFolder bool) error cfgFile := locations.Get(locations.ConfigFile) cfg, _, err := config.Load(cfgFile, myID, events.NoopLogger) if fs.IsNotExist(err) { - if cfg, err = syncthing.DefaultConfig(cfgFile, myID, events.NoopLogger, noDefaultFolder); err != nil { + if cfg, err = syncthing.DefaultConfig(cfgFile, myID, events.NoopLogger, noDefaultFolder, skipPortProbing); err != nil { return fmt.Errorf("create config: %w", err) } } else if err != nil { diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 07deb9be8..98175f80f 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -337,7 +337,7 @@ func (options serveOptions) Run() error { } if options.GenerateDir != "" { - if err := generate.Generate(options.GenerateDir, "", "", options.NoDefaultFolder); err != nil { + if err := generate.Generate(options.GenerateDir, "", "", options.NoDefaultFolder, options.SkipPortProbing); err != nil { l.Warnln("Failed to generate config and keys:", err) os.Exit(svcutil.ExitError.AsInt()) } @@ -551,7 +551,7 @@ func syncthingMain(options serveOptions) { evLogger := events.NewLogger() earlyService.Add(evLogger) - cfgWrapper, err := syncthing.LoadConfigAtStartup(locations.Get(locations.ConfigFile), cert, evLogger, options.AllowNewerConfig, options.NoDefaultFolder) + cfgWrapper, err := syncthing.LoadConfigAtStartup(locations.Get(locations.ConfigFile), cert, evLogger, options.AllowNewerConfig, options.NoDefaultFolder, options.SkipPortProbing) if err != nil { l.Warnln("Failed to initialize config:", err) os.Exit(svcutil.ExitError.AsInt()) diff --git a/lib/config/config.go b/lib/config/config.go index 67ea8a024..302cc760c 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -113,18 +113,16 @@ func New(myID protocol.DeviceID) Configuration { return cfg } -func NewWithFreePorts(myID protocol.DeviceID) (Configuration, error) { - cfg := New(myID) - +func (cfg *Configuration) ProbeFreePorts() error { port, err := getFreePort("127.0.0.1", DefaultGUIPort) if err != nil { - return Configuration{}, errors.Wrap(err, "get free port (GUI)") + return errors.Wrap(err, "get free port (GUI)") } cfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port) port, err = getFreePort("0.0.0.0", DefaultTCPPort) if err != nil { - return Configuration{}, errors.Wrap(err, "get free port (BEP)") + return errors.Wrap(err, "get free port (BEP)") } if port == DefaultTCPPort { cfg.Options.RawListenAddresses = []string{"default"} @@ -136,7 +134,7 @@ func NewWithFreePorts(myID protocol.DeviceID) (Configuration, error) { } } - return cfg, nil + return nil } type xmlConfiguration struct { diff --git a/lib/syncthing/utils.go b/lib/syncthing/utils.go index 5f59af2b6..bf4752494 100644 --- a/lib/syncthing/utils.go +++ b/lib/syncthing/utils.go @@ -59,9 +59,12 @@ func GenerateCertificate(certFile, keyFile string) (tls.Certificate, error) { return tlsutil.NewCertificate(certFile, keyFile, tlsDefaultCommonName, deviceCertLifetimeDays) } -func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger, noDefaultFolder bool) (config.Wrapper, error) { - newCfg, err := config.NewWithFreePorts(myID) - if err != nil { +func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger, noDefaultFolder, skipPortProbing bool) (config.Wrapper, error) { + newCfg := config.New(myID) + + if skipPortProbing { + l.Infoln("Using default network port numbers instead of probing for free ports") + } else if err := newCfg.ProbeFreePorts(); err != nil { return nil, err } @@ -84,11 +87,11 @@ func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger, // creates a default one, without the default folder if noDefaultFolder is ture. // Otherwise it checks the version, and archives and upgrades the config if // necessary or returns an error, if the version isn't compatible. -func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, noDefaultFolder bool) (config.Wrapper, error) { +func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, noDefaultFolder, skipPortProbing bool) (config.Wrapper, error) { myID := protocol.NewDeviceID(cert.Certificate[0]) cfg, originalVersion, err := config.Load(path, myID, evLogger) if fs.IsNotExist(err) { - cfg, err = DefaultConfig(path, myID, evLogger, noDefaultFolder) + cfg, err = DefaultConfig(path, myID, evLogger, noDefaultFolder, skipPortProbing) if err != nil { return nil, errors.Wrap(err, "failed to generate default config") }