Merge pull request #783 from wilmerpaulino/config-node-dir
config+cmd/lncli: add flags to specify the base directory for lnd and supported backend nodes
This commit is contained in:
commit
3a53752d90
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@ -28,9 +29,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
lndHomeDir = btcutil.AppDataDir("lnd", false)
|
||||
defaultTLSCertPath = filepath.Join(lndHomeDir, defaultTLSCertFilename)
|
||||
defaultMacaroonPath = filepath.Join(lndHomeDir, defaultMacaroonFilename)
|
||||
defaultLndDir = btcutil.AppDataDir("lnd", false)
|
||||
defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename)
|
||||
defaultMacaroonPath = filepath.Join(defaultLndDir, defaultMacaroonFilename)
|
||||
)
|
||||
|
||||
func fatal(err error) {
|
||||
@ -59,6 +60,27 @@ func getClient(ctx *cli.Context) (lnrpc.LightningClient, func()) {
|
||||
}
|
||||
|
||||
func getClientConn(ctx *cli.Context, skipMacaroons bool) *grpc.ClientConn {
|
||||
lndDir := cleanAndExpandPath(ctx.GlobalString("lnddir"))
|
||||
if lndDir != defaultLndDir {
|
||||
// If a custom lnd directory was set, we'll also check if custom
|
||||
// paths for the TLS cert and macaroon file were set as well. If
|
||||
// not, we'll override their paths so they can be found within
|
||||
// the custom lnd directory set. This allows us to set a custom
|
||||
// lnd directory, along with custom paths to the TLS cert and
|
||||
// macaroon file.
|
||||
tlsCertPath := cleanAndExpandPath(ctx.GlobalString("tlscertpath"))
|
||||
if tlsCertPath == defaultTLSCertPath {
|
||||
ctx.GlobalSet("tlscertpath",
|
||||
filepath.Join(lndDir, defaultTLSCertFilename))
|
||||
}
|
||||
|
||||
macPath := cleanAndExpandPath(ctx.GlobalString("macaroonpath"))
|
||||
if macPath == defaultMacaroonPath {
|
||||
ctx.GlobalSet("no-macaroons",
|
||||
filepath.Join(lndDir, defaultMacaroonFilename))
|
||||
}
|
||||
}
|
||||
|
||||
// Load the specified TLS certificate and build transport credentials
|
||||
// with it.
|
||||
tlsCertPath := cleanAndExpandPath(ctx.GlobalString("tlscertpath"))
|
||||
@ -136,6 +158,11 @@ func main() {
|
||||
Value: "localhost:10009",
|
||||
Usage: "host:port of ln daemon",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "lnddir",
|
||||
Value: defaultLndDir,
|
||||
Usage: "path to lnd's base directory",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tlscertpath",
|
||||
Value: defaultTLSCertPath,
|
||||
@ -210,7 +237,15 @@ func main() {
|
||||
func cleanAndExpandPath(path string) string {
|
||||
// Expand initial ~ to OS specific home directory.
|
||||
if strings.HasPrefix(path, "~") {
|
||||
homeDir := filepath.Dir(lndHomeDir)
|
||||
var homeDir string
|
||||
|
||||
user, err := user.Current()
|
||||
if err == nil {
|
||||
homeDir = user.HomeDir
|
||||
} else {
|
||||
homeDir = os.Getenv("HOME")
|
||||
}
|
||||
|
||||
path = strings.Replace(path, "~", homeDir, 1)
|
||||
}
|
||||
|
||||
|
149
config.go
149
config.go
@ -9,6 +9,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -66,23 +67,22 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO(roasbeef): base off of datadir instead?
|
||||
lndHomeDir = btcutil.AppDataDir("lnd", false)
|
||||
defaultConfigFile = filepath.Join(lndHomeDir, defaultConfigFilename)
|
||||
defaultDataDir = filepath.Join(lndHomeDir, defaultDataDirname)
|
||||
defaultTLSCertPath = filepath.Join(lndHomeDir, defaultTLSCertFilename)
|
||||
defaultTLSKeyPath = filepath.Join(lndHomeDir, defaultTLSKeyFilename)
|
||||
defaultAdminMacPath = filepath.Join(lndHomeDir, defaultAdminMacFilename)
|
||||
defaultReadMacPath = filepath.Join(lndHomeDir, defaultReadMacFilename)
|
||||
defaultLogDir = filepath.Join(lndHomeDir, defaultLogDirname)
|
||||
defaultLndDir = btcutil.AppDataDir("lnd", false)
|
||||
defaultConfigFile = filepath.Join(defaultLndDir, defaultConfigFilename)
|
||||
defaultDataDir = filepath.Join(defaultLndDir, defaultDataDirname)
|
||||
defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename)
|
||||
defaultTLSKeyPath = filepath.Join(defaultLndDir, defaultTLSKeyFilename)
|
||||
defaultAdminMacPath = filepath.Join(defaultLndDir, defaultAdminMacFilename)
|
||||
defaultReadMacPath = filepath.Join(defaultLndDir, defaultReadMacFilename)
|
||||
defaultLogDir = filepath.Join(defaultLndDir, defaultLogDirname)
|
||||
|
||||
btcdHomeDir = btcutil.AppDataDir("btcd", false)
|
||||
defaultBtcdRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert")
|
||||
defaultBtcdDir = btcutil.AppDataDir("btcd", false)
|
||||
defaultBtcdRPCCertFile = filepath.Join(defaultBtcdDir, "rpc.cert")
|
||||
|
||||
ltcdHomeDir = btcutil.AppDataDir("ltcd", false)
|
||||
defaultLtcdRPCCertFile = filepath.Join(ltcdHomeDir, "rpc.cert")
|
||||
defaultLtcdDir = btcutil.AppDataDir("ltcd", false)
|
||||
defaultLtcdRPCCertFile = filepath.Join(defaultLtcdDir, "rpc.cert")
|
||||
|
||||
bitcoindHomeDir = btcutil.AppDataDir("bitcoin", false)
|
||||
defaultBitcoindDir = btcutil.AppDataDir("bitcoin", false)
|
||||
)
|
||||
|
||||
type chainConfig struct {
|
||||
@ -112,6 +112,7 @@ type neutrinoConfig struct {
|
||||
}
|
||||
|
||||
type btcdConfig struct {
|
||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||
@ -120,6 +121,7 @@ type btcdConfig struct {
|
||||
}
|
||||
|
||||
type bitcoindConfig struct {
|
||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||
@ -146,10 +148,11 @@ type torConfig struct {
|
||||
type config struct {
|
||||
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
|
||||
|
||||
LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
|
||||
ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"`
|
||||
DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"`
|
||||
TLSCertPath string `long:"tlscertpath" description:"Path to TLS certificate for lnd's RPC and REST services"`
|
||||
TLSKeyPath string `long:"tlskeypath" description:"Path to TLS private key for lnd's RPC and REST services"`
|
||||
TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for lnd's RPC and REST services"`
|
||||
TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for lnd's RPC and REST services"`
|
||||
TLSExtraIP string `long:"tlsextraip" description:"Adds an extra ip to the generated certificate"`
|
||||
NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication"`
|
||||
AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"`
|
||||
@ -208,6 +211,7 @@ type config struct {
|
||||
// 4) Parse CLI options and overwrite/add any specified options
|
||||
func loadConfig() (*config, error) {
|
||||
defaultCfg := config{
|
||||
LndDir: defaultLndDir,
|
||||
ConfigFile: defaultConfigFile,
|
||||
DataDir: defaultDataDir,
|
||||
DebugLevel: defaultLogLevel,
|
||||
@ -224,10 +228,12 @@ func loadConfig() (*config, error) {
|
||||
Node: "btcd",
|
||||
},
|
||||
BtcdMode: &btcdConfig{
|
||||
Dir: defaultBtcdDir,
|
||||
RPCHost: defaultRPCHost,
|
||||
RPCCert: defaultBtcdRPCCertFile,
|
||||
},
|
||||
BitcoindMode: &bitcoindConfig{
|
||||
Dir: defaultBitcoindDir,
|
||||
RPCHost: defaultRPCHost,
|
||||
},
|
||||
Litecoin: &chainConfig{
|
||||
@ -238,6 +244,7 @@ func loadConfig() (*config, error) {
|
||||
Node: "btcd",
|
||||
},
|
||||
LtcdMode: &btcdConfig{
|
||||
Dir: defaultLtcdDir,
|
||||
RPCHost: defaultRPCHost,
|
||||
RPCCert: defaultLtcdRPCCertFile,
|
||||
},
|
||||
@ -268,9 +275,22 @@ func loadConfig() (*config, error) {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Create the home directory if it doesn't already exist.
|
||||
// If the provided lnd directory is not the default, we'll modify the
|
||||
// path to all of the files and directories that will live within it.
|
||||
lndDir := cleanAndExpandPath(preCfg.LndDir)
|
||||
if lndDir != defaultLndDir {
|
||||
defaultCfg.ConfigFile = filepath.Join(lndDir, defaultConfigFilename)
|
||||
defaultCfg.DataDir = filepath.Join(lndDir, defaultDataDirname)
|
||||
defaultCfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
|
||||
defaultCfg.TLSKeyPath = filepath.Join(lndDir, defaultTLSKeyFilename)
|
||||
defaultCfg.AdminMacPath = filepath.Join(lndDir, defaultAdminMacFilename)
|
||||
defaultCfg.ReadMacPath = filepath.Join(lndDir, defaultReadMacFilename)
|
||||
defaultCfg.LogDir = filepath.Join(lndDir, defaultLogDirname)
|
||||
}
|
||||
|
||||
// Create the lnd directory if it doesn't already exist.
|
||||
funcName := "loadConfig"
|
||||
if err := os.MkdirAll(lndHomeDir, 0700); err != nil {
|
||||
if err := os.MkdirAll(lndDir, 0700); err != nil {
|
||||
// Show a nicer error message if it's because a symlink is
|
||||
// linked to a directory that does not exist (probably because
|
||||
// it's not mounted).
|
||||
@ -281,7 +301,7 @@ func loadConfig() (*config, error) {
|
||||
}
|
||||
}
|
||||
|
||||
str := "%s: Failed to create home directory: %v"
|
||||
str := "%s: Failed to create lnd directory: %v"
|
||||
err := fmt.Errorf(str, funcName, err)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, err
|
||||
@ -290,7 +310,8 @@ func loadConfig() (*config, error) {
|
||||
// Next, load any additional configuration options from the file.
|
||||
var configFileError error
|
||||
cfg := defaultCfg
|
||||
if err := flags.IniParse(preCfg.ConfigFile, &cfg); err != nil {
|
||||
configFile := cleanAndExpandPath(preCfg.ConfigFile)
|
||||
if err := flags.IniParse(configFile, &cfg); err != nil {
|
||||
configFileError = err
|
||||
}
|
||||
|
||||
@ -300,6 +321,19 @@ func loadConfig() (*config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// As soon as we're done parsing configuration options, ensure all paths
|
||||
// to directories and files are cleaned and expanded before attempting
|
||||
// to use them later on.
|
||||
cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
|
||||
cfg.TLSCertPath = cleanAndExpandPath(cfg.TLSCertPath)
|
||||
cfg.TLSKeyPath = cleanAndExpandPath(cfg.TLSKeyPath)
|
||||
cfg.AdminMacPath = cleanAndExpandPath(cfg.AdminMacPath)
|
||||
cfg.ReadMacPath = cleanAndExpandPath(cfg.ReadMacPath)
|
||||
cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
|
||||
cfg.BtcdMode.Dir = cleanAndExpandPath(cfg.BtcdMode.Dir)
|
||||
cfg.LtcdMode.Dir = cleanAndExpandPath(cfg.LtcdMode.Dir)
|
||||
cfg.BitcoindMode.Dir = cleanAndExpandPath(cfg.BitcoindMode.Dir)
|
||||
|
||||
// Setup dial and DNS resolution functions depending on the specified
|
||||
// options. The default is to use the standard golang "net" package
|
||||
// functions. When Tor's proxy is specified, the dial function is set to
|
||||
@ -489,28 +523,12 @@ func loadConfig() (*config, error) {
|
||||
cfg.ReadMacPath = filepath.Join(cfg.DataDir, defaultReadMacFilename)
|
||||
}
|
||||
|
||||
// Append the network type to the data directory so it is "namespaced"
|
||||
// per network. In addition to the block database, there are other
|
||||
// pieces of data that are saved to disk such as address manager state.
|
||||
// All data is specific to a network, so namespacing the data directory
|
||||
// means each individual piece of serialized data does not have to
|
||||
// worry about changing names per network and such.
|
||||
// TODO(roasbeef): when we go full multi-chain remove the additional
|
||||
// namespacing on the target chain.
|
||||
cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
|
||||
|
||||
// Append the network type to the log directory so it is "namespaced"
|
||||
// per network in the same fashion as the data directory.
|
||||
cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
|
||||
cfg.LogDir = filepath.Join(cfg.LogDir,
|
||||
registeredChains.PrimaryChain().String(),
|
||||
normalizeNetwork(activeNetParams.Name))
|
||||
|
||||
// Ensure that the paths to the TLS key and certificate files are
|
||||
// expanded and cleaned.
|
||||
cfg.TLSCertPath = cleanAndExpandPath(cfg.TLSCertPath)
|
||||
cfg.TLSKeyPath = cleanAndExpandPath(cfg.TLSKeyPath)
|
||||
|
||||
// Initialize logging at the default logging level.
|
||||
initLogRotator(filepath.Join(cfg.LogDir, defaultLogFilename))
|
||||
|
||||
@ -589,7 +607,15 @@ func loadConfig() (*config, error) {
|
||||
func cleanAndExpandPath(path string) string {
|
||||
// Expand initial ~ to OS specific home directory.
|
||||
if strings.HasPrefix(path, "~") {
|
||||
homeDir := filepath.Dir(lndHomeDir)
|
||||
var homeDir string
|
||||
|
||||
user, err := user.Current()
|
||||
if err == nil {
|
||||
homeDir = user.HomeDir
|
||||
} else {
|
||||
homeDir = os.Getenv("HOME")
|
||||
}
|
||||
|
||||
path = strings.Replace(path, "~", homeDir, 1)
|
||||
}
|
||||
|
||||
@ -693,9 +719,11 @@ func noiseDial(idPriv *btcec.PrivateKey) func(net.Addr) (net.Conn, error) {
|
||||
|
||||
func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
funcName string) error {
|
||||
// If the configuration has already set the RPCUser and RPCPass, and
|
||||
// if we're either not using bitcoind mode or the ZMQ path is already
|
||||
// specified, we can return.
|
||||
|
||||
// First, we'll check our node config to make sure the RPC parameters
|
||||
// were set correctly. We'll also determine the path to the conf file
|
||||
// depending on the backend node.
|
||||
var daemonName, confDir, confFile string
|
||||
switch conf := nodeConfig.(type) {
|
||||
case *btcdConfig:
|
||||
// If both RPCUser and RPCPass are set, we assume those
|
||||
@ -709,6 +737,17 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
return fmt.Errorf("please set both or neither of " +
|
||||
"btcd.rpcuser and btcd.rpcpass")
|
||||
}
|
||||
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
daemonName = "btcd"
|
||||
confDir = conf.Dir
|
||||
confFile = "btcd"
|
||||
case litecoinChain:
|
||||
daemonName = "ltcd"
|
||||
confDir = conf.Dir
|
||||
confFile = "ltcd"
|
||||
}
|
||||
case *bitcoindConfig:
|
||||
// If all of RPCUser, RPCPass, and ZMQPath are set, we assume
|
||||
// those parameters are good to use.
|
||||
@ -722,6 +761,10 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
"bitcoind.rpcuser, bitcoind.rpcpass, and " +
|
||||
"bitcoind.zmqpath")
|
||||
}
|
||||
|
||||
daemonName = "bitcoind"
|
||||
confDir = conf.Dir
|
||||
confFile = "bitcoin"
|
||||
}
|
||||
|
||||
// If we're in simnet mode, then the running btcd instance won't read
|
||||
@ -733,33 +776,9 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||
return fmt.Errorf(str, funcName)
|
||||
}
|
||||
|
||||
var daemonName, homeDir, confFile string
|
||||
switch net {
|
||||
case bitcoinChain:
|
||||
switch cConfig.Node {
|
||||
case "btcd":
|
||||
daemonName = "btcd"
|
||||
homeDir = btcdHomeDir
|
||||
confFile = "btcd"
|
||||
case "bitcoind":
|
||||
daemonName = "bitcoind"
|
||||
homeDir = bitcoindHomeDir
|
||||
confFile = "bitcoin"
|
||||
}
|
||||
case litecoinChain:
|
||||
switch cConfig.Node {
|
||||
case "btcd":
|
||||
daemonName = "ltcd"
|
||||
homeDir = ltcdHomeDir
|
||||
confFile = "ltcd"
|
||||
case "bitcoind":
|
||||
return fmt.Errorf("bitcoind mode doesn't work with Litecoin yet")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Attempting automatic RPC configuration to " + daemonName)
|
||||
|
||||
confFile = filepath.Join(homeDir, fmt.Sprintf("%v.conf", confFile))
|
||||
confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
|
||||
switch cConfig.Node {
|
||||
case "btcd":
|
||||
nConf := nodeConfig.(*btcdConfig)
|
||||
|
Loading…
Reference in New Issue
Block a user