diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 4d43c422fbb..a1bf0d23d25 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -7,6 +7,7 @@ import ( "io" "os" "path" + "strings" context "context" assets "github.com/ipfs/go-ipfs/assets" @@ -27,6 +28,13 @@ var initCmd = &cmds.Command{ ShortDescription: ` Initializes ipfs configuration files and generates a new keypair. +If you are going to run IPFS in server environment, you may want to +initialize it using 'server' profile. + +Available profiles: + 'server' - Disables local host discovery, recommended when + running IPFS on machines with public IPv4 addresses. + ipfs uses a repository in the local file system. By default, the repo is located at ~/.ipfs. To change the repo location, set the $IPFS_PATH environment variable: @@ -40,6 +48,7 @@ environment variable: Options: []cmds.Option{ cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key.").Default(nBitsForKeypairDefault), cmds.BoolOption("empty-repo", "e", "Don't add and pin help files to the local storage.").Default(false), + cmds.StringOption("profile", "p", "Apply profile settings to config. Multiple profiles can be separated by ','"), // TODO need to decide whether to expose the override as a file or a // directory. That is: should we allow the user to also specify the @@ -96,7 +105,18 @@ environment variable: } } - if err := doInit(os.Stdout, req.InvocContext().ConfigRoot, empty, nBitsForKeypair, conf); err != nil { + profile, _, err := req.Option("profile").String() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + var profiles []string + if profile != "" { + profiles = strings.Split(profile, ",") + } + + if err := doInit(os.Stdout, req.InvocContext().ConfigRoot, empty, nBitsForKeypair, profiles, conf); err != nil { res.SetError(err, cmds.ErrNormal) return } @@ -108,10 +128,10 @@ Reinitializing would overwrite your keys. `) func initWithDefaults(out io.Writer, repoRoot string) error { - return doInit(out, repoRoot, false, nBitsForKeypairDefault, nil) + return doInit(out, repoRoot, false, nBitsForKeypairDefault, nil, nil) } -func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, conf *config.Config) error { +func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, confProfiles []string, conf *config.Config) error { if _, err := fmt.Fprintf(out, "initializing IPFS node at %s\n", repoRoot); err != nil { return err } @@ -132,6 +152,17 @@ func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, con } } + for _, profile := range confProfiles { + transformer, ok := config.ConfigProfiles[profile] + if !ok { + return fmt.Errorf("invalid configuration profile: %s", profile) + } + + if err := transformer(conf); err != nil { + return err + } + } + if err := fsrepo.Init(repoRoot, conf); err != nil { return err } diff --git a/repo/config/profile.go b/repo/config/profile.go new file mode 100644 index 00000000000..2f754617c37 --- /dev/null +++ b/repo/config/profile.go @@ -0,0 +1,31 @@ +package config + +// ConfigProfiles is a map holding configuration transformers +var ConfigProfiles = map[string]func(*Config) error{ + "server": func(c *Config) error { + + // defaultServerFilters has a list of non-routable IPv4 prefixes + // according to http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + defaultServerFilters := []string{ + "/ip4/10.0.0.0/ipcidr/8", + "/ip4/100.64.0.0/ipcidr/10", + "/ip4/169.254.0.0/ipcidr/16", + "/ip4/172.16.0.0/ipcidr/12", + "/ip4/192.0.0.0/ipcidr/24", + "/ip4/192.0.0.0/ipcidr/29", + "/ip4/192.0.0.8/ipcidr/32", + "/ip4/192.0.0.170/ipcidr/32", + "/ip4/192.0.0.171/ipcidr/32", + "/ip4/192.0.2.0/ipcidr/24", + "/ip4/192.168.0.0/ipcidr/16", + "/ip4/198.18.0.0/ipcidr/15", + "/ip4/198.51.100.0/ipcidr/24", + "/ip4/203.0.113.0/ipcidr/24", + "/ip4/240.0.0.0/ipcidr/4", + } + + c.Swarm.AddrFilters = append(c.Swarm.AddrFilters, defaultServerFilters...) + c.Discovery.MDNS.Enabled = false + return nil + }, +} diff --git a/test/sharness/t0020-init.sh b/test/sharness/t0020-init.sh index 6d2bfa26fda..e0ee8607987 100755 --- a/test/sharness/t0020-init.sh +++ b/test/sharness/t0020-init.sh @@ -126,6 +126,28 @@ test_expect_success "clean up ipfs dir" ' rm -rf "$IPFS_PATH" ' +# test init profiles +test_expect_success "'ipfs init --profile' with invalid profile fails" ' + BITS="1024" && + test_must_fail ipfs init --bits="$BITS" --profile=nonexistent_profile 2> invalid_profile_out + EXPECT="Error: invalid configuration profile: nonexistent_profile" && + grep "$EXPECT" invalid_profile_out +' + +test_expect_success "'ipfs init --profile' succeeds" ' + BITS="1024" && + ipfs init --bits="$BITS" --profile=server +' + +test_expect_success "'ipfs config Swarm.AddrFilters' looks good" ' + ipfs config Swarm.AddrFilters > actual_config && + test $(cat actual_config | wc -l) = 17 +' + +test_expect_success "clean up ipfs dir" ' + rm -rf "$IPFS_PATH" +' + test_init_ipfs test_launch_ipfs_daemon