init.go 4.75 KB
Newer Older
1 2 3
package main

import (
4
	"bytes"
5 6
	"encoding/base64"
	"errors"
7
	"fmt"
8
	"os"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
9
	"path/filepath"
10

11 12
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
13
	config "github.com/jbenet/go-ipfs/config"
14
	core "github.com/jbenet/go-ipfs/core"
15
	ci "github.com/jbenet/go-ipfs/crypto"
16 17
	imp "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
18
	peer "github.com/jbenet/go-ipfs/peer"
19
	updates "github.com/jbenet/go-ipfs/updates"
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
	u "github.com/jbenet/go-ipfs/util"
)

var cmdIpfsInit = &commander.Command{
	UsageLine: "init",
	Short:     "Initialize ipfs local configuration",
	Long: `ipfs init

	Initializes ipfs configuration files and generates a
	new keypair.
`,
	Run:  initCmd,
	Flag: *flag.NewFlagSet("ipfs-init", flag.ExitOnError),
}

func init() {
	cmdIpfsInit.Flag.Int("b", 4096, "number of bits for keypair")
	cmdIpfsInit.Flag.String("p", "", "passphrase for encrypting keys")
	cmdIpfsInit.Flag.Bool("f", false, "force overwrite of existing config")
39
	cmdIpfsInit.Flag.String("d", "", "Change default datastore location")
40 41
}

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
var defaultPeers = []*config.BootstrapPeer{
	&config.BootstrapPeer{
		// mars.i.ipfs.io
		PeerID:  "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
		Address: "/ip4/104.131.131.82/tcp/4001",
	},
}

func datastoreConfig(dspath string) (config.Datastore, error) {
	ds := config.Datastore{}
	if len(dspath) == 0 {
		var err error
		dspath, err = config.DataStorePath("")
		if err != nil {
			return ds, err
		}
	}
	ds.Path = dspath
	ds.Type = "leveldb"

	// Construct the data store if missing
	if err := os.MkdirAll(dspath, os.ModePerm); err != nil {
		return ds, err
	}

	// Check the directory is writeable
	if f, err := os.Create(filepath.Join(dspath, "._check_writeable")); err == nil {
		os.Remove(f.Name())
	} else {
		return ds, errors.New("Datastore '" + dspath + "' is not writeable")
	}

	return ds, nil
}

func identityConfig(nbits int) (config.Identity, error) {
	ident := config.Identity{}
	fmt.Println("generating key pair...")
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
	if err != nil {
		return ident, err
	}

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
		return ident, err
	}
	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPubKey(pk)
	if err != nil {
		return ident, err
	}
	ident.PeerID = id.Pretty()

	return ident, nil
}

102
func initCmd(c *commander.Command, inp []string) error {
103 104 105 106 107
	configpath, err := getConfigDir(c.Parent)
	if err != nil {
		return err
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
108
	u.POut("initializing ipfs node at %s\n", configpath)
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
109
	filename, err := config.Filename(configpath)
110 111 112
	if err != nil {
		return errors.New("Couldn't get home directory path")
	}
113

114 115 116 117 118
	dspath, ok := c.Flag.Lookup("d").Value.Get().(string)
	if !ok {
		return errors.New("failed to parse datastore flag")
	}

119
	fi, err := os.Lstat(filename)
120 121 122 123
	force, ok := c.Flag.Lookup("f").Value.Get().(bool)
	if !ok {
		return errors.New("failed to parse force flag")
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
124 125 126 127
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		if !force {
			return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
		}
128 129 130
	}
	cfg := new(config.Config)

131 132 133
	// setup the datastore
	cfg.Datastore, err = datastoreConfig(dspath)
	if err != nil {
134 135 136
		return err
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
137 138 139 140 141
	// setup the node addresses.
	cfg.Addresses = config.Addresses{
		Swarm: "/ip4/0.0.0.0/tcp/4001",
		API:   "/ip4/127.0.0.1/tcp/5001",
	}
142

143 144 145 146 147 148
	// setup the node mount points.
	cfg.Mounts = config.Mounts{
		IPFS: "/ipfs",
		IPNS: "/ipns",
	}

149 150 151 152
	nbits, ok := c.Flag.Lookup("b").Value.Get().(int)
	if !ok {
		return errors.New("failed to get bits flag")
	}
153 154 155
	if nbits < 1024 {
		return errors.New("Bitsize less than 1024 is considered unsafe.")
	}
156

157
	cfg.Identity, err = identityConfig(nbits)
158 159 160 161
	if err != nil {
		return err
	}

162 163 164 165 166 167 168 169
	// Use these hardcoded bootstrap peers for now.
	cfg.Bootstrap = defaultPeers

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

172
	err = config.WriteConfigFile(filename, cfg)
173 174 175 176
	if err != nil {
		return err
	}

177 178 179
	nd, err := core.NewIpfsNode(cfg, false)
	if err != nil {
		return err
180
	}
181
	defer nd.Close()
182

183 184 185 186 187 188 189
	// Set up default file
	msg := `Hello and Welcome to IPFS!
If you're seeing this, that means that you have successfully
installed ipfs and are now interfacing with the wonderful
world of DAGs and hashes!
`
	reader := bytes.NewBufferString(msg)
190

191
	defnd, err := imp.BuildDagFromReader(reader, nd.DAG, nd.Pinning.GetManual(), chunk.DefaultSplitter)
192 193 194
	if err != nil {
		return err
	}
195 196 197 198

	k, _ := defnd.Key()
	fmt.Printf("Default file key: %s\n", k)

199 200
	return nil
}