github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/cmd/ipfs2/init.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/base64"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	cmds "github.com/jbenet/go-ipfs/commands"
    11  	config "github.com/jbenet/go-ipfs/config"
    12  	ci "github.com/jbenet/go-ipfs/crypto"
    13  	peer "github.com/jbenet/go-ipfs/peer"
    14  	u "github.com/jbenet/go-ipfs/util"
    15  )
    16  
    17  var initCmd = &cmds.Command{
    18  	Description: "Initializes IPFS config file",
    19  	Help: `Initializes IPFS configuration files and generates a new keypair.
    20  `,
    21  
    22  	Options: []cmds.Option{
    23  		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
    24  		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
    25  		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),
    26  		cmds.StringOption("datastore", "d", "Location for the IPFS data store"),
    27  	},
    28  	Run: func(req cmds.Request) (interface{}, error) {
    29  
    30  		dspath, err := req.Option("d").String()
    31  		if err != nil {
    32  			return nil, err
    33  		}
    34  
    35  		force, err := req.Option("f").Bool()
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  
    40  		nBitsForKeypair, err := req.Option("b").Int()
    41  		if err != nil {
    42  			return nil, err
    43  		}
    44  		if !req.Option("b").Found() {
    45  			nBitsForKeypair = 4096
    46  		}
    47  
    48  		return nil, doInit(req.Context().ConfigRoot, dspath, force, nBitsForKeypair)
    49  	},
    50  }
    51  
    52  // TODO add default welcome hash: eaa68bedae247ed1e5bd0eb4385a3c0959b976e4
    53  func doInit(configRoot string, dspath string, force bool, nBitsForKeypair int) error {
    54  
    55  	u.POut("initializing ipfs node at %s\n", configRoot)
    56  
    57  	configFilename, err := config.Filename(configRoot)
    58  	if err != nil {
    59  		return errors.New("Couldn't get home directory path")
    60  	}
    61  
    62  	fi, err := os.Lstat(configFilename)
    63  	if fi != nil || (err != nil && !os.IsNotExist(err)) {
    64  		if !force {
    65  			// TODO multi-line string
    66  			return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
    67  		}
    68  	}
    69  
    70  	ds, err := datastoreConfig(dspath)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	identity, err := identityConfig(nBitsForKeypair)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	conf := config.Config{
    81  
    82  		// setup the node addresses.
    83  		Addresses: config.Addresses{
    84  			Swarm: "/ip4/0.0.0.0/tcp/4001",
    85  			API:   "/ip4/127.0.0.1/tcp/5001",
    86  		},
    87  
    88  		Bootstrap: []*config.BootstrapPeer{
    89  			&config.BootstrapPeer{ // Use these hardcoded bootstrap peers for now.
    90  				// mars.i.ipfs.io
    91  				PeerID:  "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
    92  				Address: "/ip4/104.131.131.82/tcp/4001",
    93  			},
    94  		},
    95  
    96  		Datastore: ds,
    97  
    98  		Identity: identity,
    99  
   100  		// setup the node mount points.
   101  		Mounts: config.Mounts{
   102  			IPFS: "/ipfs",
   103  			IPNS: "/ipns",
   104  		},
   105  
   106  		// tracking ipfs version used to generate the init folder and adding
   107  		// update checker default setting.
   108  		Version: config.VersionDefaultValue(),
   109  	}
   110  
   111  	err = config.WriteConfigFile(configFilename, conf)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	return nil
   116  }
   117  
   118  func datastoreConfig(dspath string) (config.Datastore, error) {
   119  	ds := config.Datastore{}
   120  	if len(dspath) == 0 {
   121  		var err error
   122  		dspath, err = config.DataStorePath("")
   123  		if err != nil {
   124  			return ds, err
   125  		}
   126  	}
   127  	ds.Path = dspath
   128  	ds.Type = "leveldb"
   129  
   130  	// Construct the data store if missing
   131  	if err := os.MkdirAll(dspath, os.ModePerm); err != nil {
   132  		return ds, err
   133  	}
   134  
   135  	// Check the directory is writeable
   136  	if f, err := os.Create(filepath.Join(dspath, "._check_writeable")); err == nil {
   137  		os.Remove(f.Name())
   138  	} else {
   139  		return ds, errors.New("Datastore '" + dspath + "' is not writeable")
   140  	}
   141  
   142  	return ds, nil
   143  }
   144  
   145  func identityConfig(nbits int) (config.Identity, error) {
   146  	// TODO guard higher up
   147  	ident := config.Identity{}
   148  	if nbits < 1024 {
   149  		return ident, errors.New("Bitsize less than 1024 is considered unsafe.")
   150  	}
   151  
   152  	fmt.Println("generating key pair...")
   153  	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
   154  	if err != nil {
   155  		return ident, err
   156  	}
   157  
   158  	// currently storing key unencrypted. in the future we need to encrypt it.
   159  	// TODO(security)
   160  	skbytes, err := sk.Bytes()
   161  	if err != nil {
   162  		return ident, err
   163  	}
   164  	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
   165  
   166  	id, err := peer.IDFromPubKey(pk)
   167  	if err != nil {
   168  		return ident, err
   169  	}
   170  	ident.PeerID = id.Pretty()
   171  
   172  	return ident, nil
   173  }