init.go 3.85 KB
Newer Older
1
package main
Matt Bell's avatar
Matt Bell committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

import (
	"encoding/base64"
	"errors"
	"os"
	"path/filepath"

	cmds "github.com/jbenet/go-ipfs/commands"
	config "github.com/jbenet/go-ipfs/config"
	ci "github.com/jbenet/go-ipfs/crypto"
	peer "github.com/jbenet/go-ipfs/peer"
	updates "github.com/jbenet/go-ipfs/updates"
	u "github.com/jbenet/go-ipfs/util"
)

var initCmd = &cmds.Command{
	Options: []cmds.Option{
		cmds.Option{[]string{"bits", "b"}, cmds.Int},
		cmds.Option{[]string{"passphrase", "p"}, cmds.String},
		cmds.Option{[]string{"force", "f"}, cmds.Bool},
		cmds.Option{[]string{"datastore", "d"}, cmds.String},
	},
	Help: `ipfs init

26 27 28
	Initializes ipfs configuration files and generates a
	new keypair.
	`,
Matt Bell's avatar
Matt Bell committed
29
	Run: func(res cmds.Response, req cmds.Request) {
30 31

		arg, found := req.Option("d")
32
		dspath, ok := arg.(string)
33 34 35 36 37
		if found && !ok {
			res.SetError(errors.New("failed to parse datastore flag"), cmds.ErrNormal)
			return
		}

38 39 40 41 42 43 44
		arg, found = req.Option("f")
		force, ok := arg.(bool) // TODO param
		if found && !ok {
			res.SetError(errors.New("failed to parse force flag"), cmds.ErrNormal)
			return
		}

45 46 47 48 49 50 51 52 53
		arg, found = req.Option("b")
		nBitsForKeypair, ok := arg.(int) // TODO param
		if found && !ok {
			res.SetError(errors.New("failed to get bits flag"), cmds.ErrNormal)
			return
		} else if !found {
			nBitsForKeypair = 4096
		}

54
		err := foo(req.Context().ConfigRoot, dspath, force, nBitsForKeypair)
55 56 57 58
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
59 60
	},
}
Matt Bell's avatar
Matt Bell committed
61

62
func foo(configRoot string, dspath string, force bool, nBitsForKeypair int) error {
63

64 65
	u.POut("initializing ipfs node at %s\n", configRoot)
	filename, err := config.Filename(configRoot)
66
	if err != nil {
67
		return errors.New("Couldn't get home directory path")
68 69
	}

70
	fi, err := os.Lstat(filename)
71 72
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		if !force {
73 74
			// TODO multi-line string
			return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
Matt Bell's avatar
Matt Bell committed
75
		}
76 77
	}
	cfg := new(config.Config)
Matt Bell's avatar
Matt Bell committed
78

79 80 81
	cfg.Datastore = config.Datastore{}
	if len(dspath) == 0 {
		dspath, err = config.DataStorePath("")
Matt Bell's avatar
Matt Bell committed
82
		if err != nil {
83
			return err
Matt Bell's avatar
Matt Bell committed
84
		}
85 86 87 88 89 90
	}
	cfg.Datastore.Path = dspath
	cfg.Datastore.Type = "leveldb"

	// Construct the data store if missing
	if err := os.MkdirAll(dspath, os.ModePerm); err != nil {
91
		return err
92 93 94 95 96 97
	}

	// Check the directory is writeable
	if f, err := os.Create(filepath.Join(dspath, "._check_writeable")); err == nil {
		os.Remove(f.Name())
	} else {
98
		return errors.New("Datastore '" + dspath + "' is not writeable")
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	}

	cfg.Identity = config.Identity{}

	// setup the node addresses.
	cfg.Addresses = config.Addresses{
		Swarm: "/ip4/0.0.0.0/tcp/4001",
		API:   "/ip4/127.0.0.1/tcp/5001",
	}

	// setup the node mount points.
	cfg.Mounts = config.Mounts{
		IPFS: "/ipfs",
		IPNS: "/ipns",
	}

115 116
	// TODO guard
	if nBitsForKeypair < 1024 {
117
		return errors.New("Bitsize less than 1024 is considered unsafe.")
118 119 120
	}

	u.POut("generating key pair\n")
121
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nBitsForKeypair)
122
	if err != nil {
123
		return err
124 125 126 127 128 129
	}

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
130
		return err
131 132 133 134 135
	}
	cfg.Identity.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPubKey(pk)
	if err != nil {
136
		return err
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
	}
	cfg.Identity.PeerID = id.Pretty()

	// Use these hardcoded bootstrap peers for now.
	cfg.Bootstrap = []*config.BootstrapPeer{
		&config.BootstrapPeer{
			// mars.i.ipfs.io
			PeerID:  "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
			Address: "/ip4/104.131.131.82/tcp/4001",
		},
	}

	// tracking ipfs version used to generate the init folder and adding update checker default setting.
	cfg.Version = config.Version{
		Check:   "error",
		Current: updates.Version,
	}

	err = config.WriteConfigFile(filename, cfg)
	if err != nil {
157
		return err
158
	}
159
	return nil
Matt Bell's avatar
Matt Bell committed
160
}