diff --git a/command/flagset/flagset.go b/command/flagset/flagset.go
index 696765e8c6543d4cc91d530903399199ddeba7ca..c272bfbcad4e4174b8b012dbfcfcbb9620e9c757 100644
--- a/command/flagset/flagset.go
+++ b/command/flagset/flagset.go
@@ -3,6 +3,7 @@ package flagset
 import (
 	"flag"
 	"fmt"
+	"math/big"
 	"strings"
 	"time"
 )
@@ -46,10 +47,6 @@ func (f *Flagset) Args() []string {
 	return f.set.Args()
 }
 
-func (f *Flagset) BoolVar() {
-
-}
-
 type BoolFlag struct {
 	Name    string
 	Usage   string
@@ -95,6 +92,56 @@ func (f *Flagset) IntFlag(i *IntFlag) {
 	f.set.IntVar(i.Value, i.Name, i.Default, i.Usage)
 }
 
+type Uint64Flag struct {
+	Name    string
+	Usage   string
+	Default uint64
+	Value   *uint64
+}
+
+func (f *Flagset) Uint64Flag(i *Uint64Flag) {
+	f.addFlag(&FlagVar{
+		Name:  i.Name,
+		Usage: i.Usage,
+	})
+	f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage)
+}
+
+type BigIntFlag struct {
+	Name    string
+	Usage   string
+	Default *big.Int
+	Value   *big.Int
+}
+
+func (b *BigIntFlag) String() string {
+	return b.Value.String()
+}
+
+func (b *BigIntFlag) Set(value string) error {
+	num := new(big.Int)
+
+	var ok bool
+	if strings.HasPrefix(value, "0x") {
+		num, ok = num.SetString(value[2:], 16)
+	} else {
+		num, ok = num.SetString(value, 10)
+	}
+	if !ok {
+		return fmt.Errorf("failed to set big int")
+	}
+	b.Value = num
+	return nil
+}
+
+func (f *Flagset) BigIntFlag(b *BigIntFlag) {
+	f.addFlag(&FlagVar{
+		Name:  b.Name,
+		Usage: b.Usage,
+	})
+	f.set.Var(b, b.Name, b.Usage)
+}
+
 type SliceStringFlag struct {
 	Name  string
 	Usage string
@@ -102,7 +149,7 @@ type SliceStringFlag struct {
 }
 
 func (i *SliceStringFlag) String() string {
-	return ""
+	return strings.Join(i.Value, ",")
 }
 
 func (i *SliceStringFlag) Set(value string) error {
@@ -124,9 +171,75 @@ type DurationFlag struct {
 	Value *time.Duration
 }
 
+func (d *DurationFlag) String() string {
+	return d.Value.String()
+}
+
+func (d *DurationFlag) Set(value string) error {
+	v, err := time.ParseDuration(value)
+	if err != nil {
+		return err
+	}
+	d.Value = &v
+	return nil
+}
+
 func (f *Flagset) DurationFlag(d *DurationFlag) {
 	f.addFlag(&FlagVar{
 		Name:  d.Name,
 		Usage: d.Usage,
 	})
+	f.set.Var(d, d.Name, d.Usage)
+}
+
+type MapStringFlag struct {
+	Name  string
+	Usage string
+	Value *map[string]string
+}
+
+func (m *MapStringFlag) String() string {
+	ls := []string{}
+	for k, v := range *m.Value {
+		ls = append(ls, k+"="+v)
+	}
+	return strings.Join(ls, ",")
+}
+
+func (m *MapStringFlag) Set(value string) error {
+	if m.Value == nil {
+		m.Value = &map[string]string{}
+	}
+	for _, t := range strings.Split(value, ",") {
+		if t != "" {
+			kv := strings.Split(t, "=")
+
+			if len(kv) == 2 {
+				(*m.Value)[kv[0]] = kv[1]
+			}
+		}
+	}
+	return nil
+}
+
+func (f *Flagset) MapStringFlag(m *MapStringFlag) {
+	f.addFlag(&FlagVar{
+		Name:  m.Name,
+		Usage: m.Usage,
+	})
+	f.set.Var(m, m.Name, m.Usage)
+}
+
+type Float64Flag struct {
+	Name  string
+	Usage string
+	Value *float64
+}
+
+func (f *Flagset) Float64Flag(i *Float64Flag) {
+	f.addFlag(&FlagVar{
+		Name:  i.Name,
+		Usage: i.Usage,
+	})
+	f.set.Float64Var(i.Value, i.Name, *i.Value, "")
 }
diff --git a/command/server/command.go b/command/server/command.go
index 59c106fea21bb11546e462b19796b33663cbd090..56b1e1f1053b607f7993fb3eb7336ab0cdb8df0b 100644
--- a/command/server/command.go
+++ b/command/server/command.go
@@ -11,9 +11,12 @@ import (
 
 	"github.com/ethereum/go-ethereum/accounts/keystore"
 	"github.com/ethereum/go-ethereum/eth"
+	"github.com/ethereum/go-ethereum/eth/tracers"
 	"github.com/ethereum/go-ethereum/ethstats"
+	"github.com/ethereum/go-ethereum/graphql"
 	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/metrics"
+	"github.com/ethereum/go-ethereum/metrics/influxdb"
 	"github.com/ethereum/go-ethereum/node"
 	"github.com/mattn/go-colorable"
 	"github.com/mattn/go-isatty"
@@ -57,89 +60,136 @@ func (c *Command) Run(args []string) int {
 	// read config file
 	config := DefaultConfig()
 	if c.configFile != "" {
-		c, err := readConfigFile(c.configFile)
+		cfg, err := readConfigFile(c.configFile)
 		if err != nil {
-			panic(err)
+			c.UI.Error(err.Error())
+			return 1
+		}
+		if err := config.Merge(cfg); err != nil {
+			c.UI.Error(err.Error())
+			return 1
 		}
-		config.Merge(c)
 	}
-	config.Merge(c.cliConfig)
+	if err := config.Merge(c.cliConfig); err != nil {
+		c.UI.Error(err.Error())
+		return 1
+	}
 
 	// start the logger
 	setupLogger(*config.LogLevel)
 
 	// load the chain genesis
 	if err := config.loadChain(); err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 
 	// create the node/stack
 	nodeCfg, err := config.buildNode()
 	if err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 	stack, err := node.New(nodeCfg)
 	if err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 	c.node = stack
 
-	// TODO: MakeChain?
-	// TODO: Metrics
-	// TODO: apis
-	// TODO: Graphql
-
 	// register the ethereum backend
 	ethCfg, err := config.buildEth()
 	if err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 	backend, err := eth.New(stack, ethCfg)
 	if err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 
-	// This is the tracers api, not sure if this should be here, i do not think so.
-	// c.node.RegisterAPIs(tracers.APIs(backend.APIBackend))
+	// debug tracing is enabled by default
+	stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
+
+	// graphql is started from another place
+	if *config.JsonRPC.Graphql.Enabled {
+		if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.Modules); err != nil {
+			c.UI.Error(fmt.Sprintf("Failed to register the GraphQL service: %v", err))
+			return 1
+		}
+	}
 
 	// register ethash service
 	if config.EthStats != nil {
 		if err := ethstats.New(stack, backend.APIBackend, backend.Engine(), *config.EthStats); err != nil {
-			panic(err)
+			c.UI.Error(err.Error())
+			return 1
 		}
 	}
 
 	// setup account manager (only keystore)
 	{
 		keydir := stack.KeyStoreDir()
-		scryptN := keystore.StandardScryptN
-		scryptP := keystore.StandardScryptP
-
-		stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, scryptN, scryptP))
+		n, p := keystore.StandardScryptN, keystore.StandardScryptP
+		if *config.UseLightweightKDF {
+			n, p = keystore.LightScryptN, keystore.LightScryptP
+		}
+		stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
 	}
 
 	// sealing (if enabled)
 	if *config.Sealer.Enabled {
 		if err := backend.StartMining(1); err != nil {
-			panic(err)
+			c.UI.Error(err.Error())
+			return 1
 		}
 	}
 
-	c.setupMetrics()
+	if err := c.setupMetrics(config.Metrics); err != nil {
+		c.UI.Error(err.Error())
+		return 1
+	}
 
 	// start the node
 	if err := c.node.Start(); err != nil {
-		panic(err)
+		c.UI.Error(err.Error())
+		return 1
 	}
 	return c.handleSignals()
 }
 
-func (c *Command) setupMetrics() error {
+func (c *Command) setupMetrics(config *MetricsConfig) error {
+	metrics.Enabled = *config.Enabled
+	metrics.EnabledExpensive = *config.Expensive
+
 	if !metrics.Enabled {
-		// metrics are globally disabled
+		// metrics are disabled, do not set up any sink
 		return nil
 	}
 
+	log.Info("Enabling metrics collection")
+
+	// influxdb
+	if v1Enabled, v2Enabled := (*config.InfluxDB.V1Enabled), (*config.InfluxDB.V2Enabled); v1Enabled || v2Enabled {
+		if v1Enabled && v2Enabled {
+			return fmt.Errorf("both influx v1 and influx v2 cannot be enabled")
+		}
+
+		cfg := config.InfluxDB
+		tags := *cfg.Tags
+		endpoint := *cfg.Endpoint
+
+		if v1Enabled {
+			log.Info("Enabling metrics export to InfluxDB (v1)")
+			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, *cfg.Database, *cfg.Username, *cfg.Password, "geth.", tags)
+		}
+		if v2Enabled {
+			log.Info("Enabling metrics export to InfluxDB (v2)")
+			go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, *cfg.Token, *cfg.Bucket, *cfg.Organization, "geth.", tags)
+		}
+	}
+
 	// Start system runtime metrics collection
 	go metrics.CollectProcessMetrics(3 * time.Second)
 
diff --git a/command/server/config.go b/command/server/config.go
index c8dd5c27c5df0f3e2d6d89d753f6da4ab1604f02..5236d20c7240e66da196694ae990a4a3b63bc04b 100644
--- a/command/server/config.go
+++ b/command/server/config.go
@@ -4,29 +4,44 @@ import (
 	"crypto/ecdsa"
 	"fmt"
 	"io/ioutil"
+	"math"
 	"math/big"
 	"os"
 	"path/filepath"
 	"strconv"
 	"time"
 
+	godebug "runtime/debug"
+
 	"github.com/ethereum/go-ethereum/command/server/chains"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/fdlimit"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth/downloader"
 	"github.com/ethereum/go-ethereum/eth/ethconfig"
+	"github.com/ethereum/go-ethereum/eth/gasprice"
+	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/node"
 	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/p2p/enode"
+	"github.com/ethereum/go-ethereum/p2p/nat"
 	"github.com/ethereum/go-ethereum/params"
 	"github.com/imdario/mergo"
+	gopsutil "github.com/shirou/gopsutil/mem"
 )
 
+func mapStrPtr(m map[string]string) *map[string]string {
+	return &m
+}
+
 func stringPtr(s string) *string {
 	return &s
 }
 
+func float64Ptr(f float64) *float64 {
+	return &f
+}
+
 func uint64Ptr(i uint64) *uint64 {
 	return &i
 }
@@ -42,28 +57,39 @@ func durPtr(d time.Duration) *time.Duration {
 type Config struct {
 	chain *chains.Chain
 
-	Chain    *string
-	Debug    *bool
-	LogLevel *string
-	DataDir  *string
-	P2P      *P2PConfig
-	SyncMode *string
-	EthStats *string
-	TxPool   *TxPoolConfig
-	Sealer   *SealerConfig
-	JsonRPC  *JsonRPCConfig
+	Chain             *string
+	Debug             *bool
+	Whitelist         *map[string]string
+	UseLightweightKDF *bool
+	LogLevel          *string
+	DataDir           *string
+	P2P               *P2PConfig
+	SyncMode          *string
+	GcMode            *string
+	Snapshot          *bool
+	EthStats          *string
+	Heimdall          *HeimdallConfig
+	TxPool            *TxPoolConfig
+	Sealer            *SealerConfig
+	JsonRPC           *JsonRPCConfig
+	Gpo               *GpoConfig
+	Ethstats          *string
+	Metrics           *MetricsConfig
+	Cache             *CacheConfig
 }
 
 type P2PConfig struct {
-	MaxPeers   *uint64
-	Bind       *string
-	Port       *uint64
-	NoDiscover *bool
-	V5Disc     *bool
-	Discovery  *P2PDiscovery
+	MaxPeers     *uint64
+	MaxPendPeers *uint64
+	Bind         *string
+	Port         *uint64
+	NoDiscover   *bool
+	NAT          *string
+	Discovery    *P2PDiscovery
 }
 
 type P2PDiscovery struct {
+	V5Enabled    *bool
 	Bootnodes    []string
 	BootnodesV4  []string
 	BootnodesV5  []string
@@ -72,6 +98,11 @@ type P2PDiscovery struct {
 	DNS          []string
 }
 
+type HeimdallConfig struct {
+	URL     *string
+	Without *bool
+}
+
 type TxPoolConfig struct {
 	Locals       []string
 	NoLocals     *bool
@@ -95,21 +126,84 @@ type SealerConfig struct {
 }
 
 type JsonRPCConfig struct {
+	IPCDisable *bool
+	IPCPath    *string
+
+	Modules []string
+	VHost   []string
+	Cors    []string
+	Bind    *string
+
+	GasCap   *uint64
+	TxFeeCap *float64
+
+	Http    *APIConfig
+	Ws      *APIConfig
+	Graphql *APIConfig
+}
+
+type APIConfig struct {
+	Enabled *bool
+	Port    *uint64
+	Prefix  *string
+}
+
+type GpoConfig struct {
+	Blocks      *uint64
+	Percentile  *uint64
+	MaxPrice    *big.Int
+	IgnorePrice *big.Int
+}
+
+type MetricsConfig struct {
+	Enabled   *bool
+	Expensive *bool
+	InfluxDB  *InfluxDBConfig
+}
+
+type InfluxDBConfig struct {
+	V1Enabled    *bool
+	Endpoint     *string
+	Database     *string
+	Username     *string
+	Password     *string
+	Tags         *map[string]string
+	V2Enabled    *bool
+	Token        *string
+	Bucket       *string
+	Organization *string
+}
+
+type CacheConfig struct {
+	Cache         *uint64
+	PercGc        *uint64
+	PercSnapshot  *uint64
+	PercDatabase  *uint64
+	PercTrie      *uint64
+	Journal       *string
+	Rejournal     *time.Duration
+	NoPrefetch    *bool
+	Preimages     *bool
+	TxLookupLimit *uint64
 }
 
 func DefaultConfig() *Config {
 	return &Config{
-		Chain:    stringPtr("mainnet"),
-		Debug:    boolPtr(false),
-		LogLevel: stringPtr("INFO"),
-		DataDir:  stringPtr(""),
+		Chain:             stringPtr("mainnet"),
+		Debug:             boolPtr(false),
+		UseLightweightKDF: boolPtr(false),
+		Whitelist:         mapStrPtr(map[string]string{}),
+		LogLevel:          stringPtr("INFO"),
+		DataDir:           stringPtr(node.DefaultDataDir()),
 		P2P: &P2PConfig{
-			MaxPeers:   uint64Ptr(30),
-			Bind:       stringPtr("0.0.0.0"),
-			Port:       uint64Ptr(30303),
-			NoDiscover: boolPtr(false),
-			V5Disc:     boolPtr(false),
+			MaxPeers:     uint64Ptr(30),
+			MaxPendPeers: uint64Ptr(50),
+			Bind:         stringPtr("0.0.0.0"),
+			Port:         uint64Ptr(30303),
+			NoDiscover:   boolPtr(false),
+			NAT:          stringPtr("any"),
 			Discovery: &P2PDiscovery{
+				V5Enabled:    boolPtr(false),
 				Bootnodes:    []string{},
 				BootnodesV4:  []string{},
 				BootnodesV5:  []string{},
@@ -118,7 +212,13 @@ func DefaultConfig() *Config {
 				DNS:          []string{},
 			},
 		},
+		Heimdall: &HeimdallConfig{
+			URL:     stringPtr("http://localhost:1317"),
+			Without: boolPtr(false),
+		},
 		SyncMode: stringPtr("fast"),
+		GcMode:   stringPtr("full"),
+		Snapshot: boolPtr(true),
 		EthStats: stringPtr(""),
 		TxPool: &TxPoolConfig{
 			Locals:       []string{},
@@ -134,9 +234,66 @@ func DefaultConfig() *Config {
 			LifeTime:     durPtr(3 * time.Hour),
 		},
 		Sealer: &SealerConfig{
-			Enabled:  boolPtr(false),
-			GasCeil:  uint64Ptr(8000000),
-			GasPrice: big.NewInt(params.GWei),
+			Enabled:   boolPtr(false),
+			GasCeil:   uint64Ptr(8000000),
+			GasPrice:  big.NewInt(params.GWei),
+			ExtraData: stringPtr(""),
+		},
+		Gpo: &GpoConfig{
+			Blocks:      uint64Ptr(20),
+			Percentile:  uint64Ptr(60),
+			MaxPrice:    gasprice.DefaultMaxPrice,
+			IgnorePrice: gasprice.DefaultIgnorePrice,
+		},
+		JsonRPC: &JsonRPCConfig{
+			IPCDisable: boolPtr(false),
+			Modules:    []string{"web3", "net"},
+			Cors:       []string{"*"},
+			VHost:      []string{"*"},
+			GasCap:     uint64Ptr(ethconfig.Defaults.RPCGasCap),
+			TxFeeCap:   float64Ptr(ethconfig.Defaults.RPCTxFeeCap),
+			Http: &APIConfig{
+				Enabled: boolPtr(false),
+				Port:    uint64Ptr(8545),
+				Prefix:  stringPtr(""),
+			},
+			Ws: &APIConfig{
+				Enabled: boolPtr(false),
+				Port:    uint64Ptr(8546),
+				Prefix:  stringPtr(""),
+			},
+			Graphql: &APIConfig{
+				Enabled: boolPtr(false),
+			},
+		},
+		Ethstats: stringPtr(""),
+		Metrics: &MetricsConfig{
+			Enabled:   boolPtr(false),
+			Expensive: boolPtr(false),
+			InfluxDB: &InfluxDBConfig{
+				V1Enabled:    boolPtr(false),
+				Endpoint:     stringPtr(""),
+				Database:     stringPtr(""),
+				Username:     stringPtr(""),
+				Password:     stringPtr(""),
+				Tags:         mapStrPtr(map[string]string{}),
+				V2Enabled:    boolPtr(false),
+				Token:        stringPtr(""),
+				Bucket:       stringPtr(""),
+				Organization: stringPtr(""),
+			},
+		},
+		Cache: &CacheConfig{
+			Cache:         uint64Ptr(1024),
+			PercDatabase:  uint64Ptr(50),
+			PercTrie:      uint64Ptr(15),
+			PercGc:        uint64Ptr(25),
+			PercSnapshot:  uint64Ptr(10),
+			Journal:       stringPtr("triecache"),
+			Rejournal:     durPtr(60 * time.Minute),
+			NoPrefetch:    boolPtr(false),
+			Preimages:     boolPtr(false),
+			TxLookupLimit: uint64Ptr(2350000),
 		},
 	}
 }
@@ -163,13 +320,22 @@ func (c *Config) loadChain() error {
 	}
 	c.chain = chain
 
-	// preload some default values that are on the chain file
+	// preload some default values that depend on the chain file
+
+	// the genesis files defines default bootnodes
 	if c.P2P.Discovery.Bootnodes == nil {
 		c.P2P.Discovery.Bootnodes = c.chain.Bootnodes
 	}
 	if c.P2P.Discovery.DNS == nil {
 		c.P2P.Discovery.DNS = c.chain.DNS
 	}
+
+	// depending on the chain we have different cache values
+	if *c.Chain != "mainnet" {
+		c.Cache.Cache = uint64Ptr(4096)
+	} else {
+		c.Cache.Cache = uint64Ptr(1024)
+	}
 	return nil
 }
 
@@ -184,25 +350,30 @@ func (c *Config) buildEth() (*ethconfig.Config, error) {
 
 	// txpool options
 	{
-		cfg := n.TxPool
-		cfg.NoLocals = *c.TxPool.NoLocals
-		cfg.Journal = *c.TxPool.Journal
-		cfg.Rejournal = *c.TxPool.Rejournal
-		cfg.PriceLimit = *c.TxPool.PriceLimit
-		cfg.PriceBump = *c.TxPool.PriceBump
-		cfg.AccountSlots = *c.TxPool.AccountSlots
-		cfg.GlobalSlots = *c.TxPool.GlobalSlots
-		cfg.AccountQueue = *c.TxPool.AccountQueue
-		cfg.GlobalQueue = *c.TxPool.GlobalQueue
-		cfg.Lifetime = *c.TxPool.LifeTime
+		n.TxPool.NoLocals = *c.TxPool.NoLocals
+		n.TxPool.Journal = *c.TxPool.Journal
+		n.TxPool.Rejournal = *c.TxPool.Rejournal
+		n.TxPool.PriceLimit = *c.TxPool.PriceLimit
+		n.TxPool.PriceBump = *c.TxPool.PriceBump
+		n.TxPool.AccountSlots = *c.TxPool.AccountSlots
+		n.TxPool.GlobalSlots = *c.TxPool.GlobalSlots
+		n.TxPool.AccountQueue = *c.TxPool.AccountQueue
+		n.TxPool.GlobalQueue = *c.TxPool.GlobalQueue
+		n.TxPool.Lifetime = *c.TxPool.LifeTime
 	}
 
 	// miner options
 	{
-		cfg := n.Miner
-		cfg.Etherbase = common.HexToAddress(*c.Sealer.Etherbase)
-		cfg.GasPrice = c.Sealer.GasPrice
-		cfg.GasCeil = *c.Sealer.GasCeil
+		n.Miner.GasPrice = c.Sealer.GasPrice
+		n.Miner.GasCeil = *c.Sealer.GasCeil
+		n.Miner.ExtraData = []byte(*c.Sealer.ExtraData)
+
+		if etherbase := c.Sealer.Etherbase; etherbase != nil {
+			if !common.IsHexAddress(*etherbase) {
+				return nil, fmt.Errorf("etherbase is not an address: %s", *etherbase)
+			}
+			n.Miner.Etherbase = common.HexToAddress(*etherbase)
+		}
 	}
 
 	// discovery (this params should be in node.Config)
@@ -211,16 +382,106 @@ func (c *Config) buildEth() (*ethconfig.Config, error) {
 		n.SnapDiscoveryURLs = c.P2P.Discovery.DNS
 	}
 
-	var syncMode downloader.SyncMode
+	// whitelist
+	{
+		n.Whitelist = map[uint64]common.Hash{}
+		for k, v := range *c.Whitelist {
+			number, err := strconv.ParseUint(k, 0, 64)
+			if err != nil {
+				return nil, fmt.Errorf("invalid whitelist block number %s: %v", k, err)
+			}
+			var hash common.Hash
+			if err = hash.UnmarshalText([]byte(v)); err != nil {
+				return nil, fmt.Errorf("invalid whitelist hash %s: %v", v, err)
+			}
+			n.Whitelist[number] = hash
+		}
+	}
+
+	// cache
+	{
+		cache := *c.Cache.Cache
+		calcPerc := func(val *uint64) int {
+			return int(cache * (*val) / 100)
+		}
+
+		// Cap the cache allowance
+		mem, err := gopsutil.VirtualMemory()
+		if err == nil {
+			if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 {
+				log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024)
+				mem.Total = 2 * 1024 * 1024 * 1024
+			}
+			allowance := uint64(mem.Total / 1024 / 1024 / 3)
+			if cache > allowance {
+				log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
+				cache = allowance
+			}
+		}
+		// Tune the garbage collector
+		gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
+
+		log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
+		godebug.SetGCPercent(int(gogc))
+
+		n.TrieCleanCacheJournal = *c.Cache.Journal
+		n.TrieCleanCacheRejournal = *c.Cache.Rejournal
+		n.DatabaseCache = calcPerc(c.Cache.PercDatabase)
+		n.SnapshotCache = calcPerc(c.Cache.PercSnapshot)
+		n.TrieCleanCache = calcPerc(c.Cache.PercTrie)
+		n.TrieDirtyCache = calcPerc(c.Cache.PercGc)
+		n.NoPrefetch = *c.Cache.NoPrefetch
+		n.Preimages = *c.Cache.Preimages
+		n.TxLookupLimit = *c.Cache.TxLookupLimit
+	}
+
+	n.RPCGasCap = *c.JsonRPC.GasCap
+	if n.RPCGasCap != 0 {
+		log.Info("Set global gas cap", "cap", n.RPCGasCap)
+	} else {
+		log.Info("Global gas cap disabled")
+	}
+	n.RPCTxFeeCap = *c.JsonRPC.TxFeeCap
+
+	// sync mode. It can either be "fast", "full" or "snap". We disable
+	// for now the "light" mode.
 	switch *c.SyncMode {
 	case "fast":
-		syncMode = downloader.FastSync
+		n.SyncMode = downloader.FastSync
+	case "full":
+		n.SyncMode = downloader.FullSync
+	case "snap":
+		n.SyncMode = downloader.SnapSync
 	default:
-		return nil, fmt.Errorf("sync mode '%s' not found", syncMode)
+		return nil, fmt.Errorf("sync mode '%s' not found", *c.SyncMode)
+	}
+
+	// archive mode. It can either be "archive" or "full".
+	switch *c.GcMode {
+	case "full":
+		n.NoPruning = false
+	case "archive":
+		n.NoPruning = true
+		if !n.Preimages {
+			n.Preimages = true
+			log.Info("Enabling recording of key preimages since archive mode is used")
+		}
+	default:
+		return nil, fmt.Errorf("gcmode '%s' not found", *c.GcMode)
 	}
-	n.SyncMode = syncMode
-	n.DatabaseHandles = dbHandles
 
+	// snapshot disable check
+	if *c.Snapshot {
+		if n.SyncMode == downloader.SnapSync {
+			log.Info("Snap sync requested, enabling --snapshot")
+		} else {
+			// disable snapshot
+			n.TrieCleanCache += n.SnapshotCache
+			n.SnapshotCache = 0
+		}
+	}
+
+	n.DatabaseHandles = dbHandles
 	return &n, nil
 }
 
@@ -231,23 +492,54 @@ var (
 )
 
 func (c *Config) buildNode() (*node.Config, error) {
+	ipcPath := ""
+	if !*c.JsonRPC.IPCDisable {
+		ipcPath = clientIdentifier + ".ipc"
+		if c.JsonRPC.IPCPath != nil {
+			ipcPath = *c.JsonRPC.IPCPath
+		}
+	}
+
 	cfg := &node.Config{
-		Name:    clientIdentifier,
-		DataDir: *c.DataDir,
-		Version: params.VersionWithCommit(gitCommit, gitDate),
-		IPCPath: clientIdentifier + ".ipc",
+		Name:              clientIdentifier,
+		DataDir:           *c.DataDir,
+		UseLightweightKDF: *c.UseLightweightKDF,
+		Version:           params.VersionWithCommit(gitCommit, gitDate),
+		IPCPath:           ipcPath,
 		P2P: p2p.Config{
-			MaxPeers:   int(*c.P2P.MaxPeers),
-			ListenAddr: *c.P2P.Bind + ":" + strconv.Itoa(int(*c.P2P.Port)),
+			MaxPeers:        int(*c.P2P.MaxPeers),
+			MaxPendingPeers: int(*c.P2P.MaxPendPeers),
+			ListenAddr:      *c.P2P.Bind + ":" + strconv.Itoa(int(*c.P2P.Port)),
+			DiscoveryV5:     *c.P2P.Discovery.V5Enabled,
 		},
-		/*
-			HTTPHost:         *c.BindAddr,
-			HTTPPort:         int(*c.Ports.HTTP),
-			HTTPVirtualHosts: []string{"*"},
-			WSHost:           *c.BindAddr,
-			WSPort:           int(*c.Ports.Websocket),
-		*/
+		HTTPModules:         c.JsonRPC.Modules,
+		HTTPCors:            c.JsonRPC.Cors,
+		HTTPVirtualHosts:    c.JsonRPC.VHost,
+		HTTPPathPrefix:      *c.JsonRPC.Http.Prefix,
+		WSModules:           c.JsonRPC.Modules,
+		WSOrigins:           c.JsonRPC.Cors,
+		WSPathPrefix:        *c.JsonRPC.Ws.Prefix,
+		GraphQLCors:         c.JsonRPC.Cors,
+		GraphQLVirtualHosts: c.JsonRPC.VHost,
+	}
+
+	// enable jsonrpc endpoints
+	{
+		if *c.JsonRPC.Http.Enabled {
+			cfg.HTTPHost = *c.JsonRPC.Bind
+			cfg.HTTPPort = int(*c.JsonRPC.Http.Port)
+		}
+		if *c.JsonRPC.Ws.Enabled {
+			cfg.WSHost = *c.JsonRPC.Bind
+			cfg.WSPort = int(*c.JsonRPC.Ws.Port)
+		}
+	}
+
+	natif, err := nat.Parse(*c.P2P.NAT)
+	if err != nil {
+		return nil, fmt.Errorf("wrong 'nat' flag: %v", err)
 	}
+	cfg.P2P.NAT = natif
 
 	// setup private key for DevP2P if not found
 	devP2PPrivKey, err := readDevP2PKey(*c.DataDir)
diff --git a/command/server/flags.go b/command/server/flags.go
index 66d426279878fd0c88472a4aee1dc8f6fb4c51aa..b0359d525f74fa2e9438ea85a65ee3a5d8466efc 100644
--- a/command/server/flags.go
+++ b/command/server/flags.go
@@ -1,65 +1,415 @@
 package server
 
-import "github.com/ethereum/go-ethereum/command/flagset"
+import (
+	"github.com/ethereum/go-ethereum/command/flagset"
+)
 
 func (c *Command) Flags() *flagset.Flagset {
 	c.cliConfig = DefaultConfig()
 
-	f := flagset.NewFlagSet("")
+	f := flagset.NewFlagSet("server")
 
 	f.BoolFlag(&flagset.BoolFlag{
 		Name:  "debug",
-		Value: c.cliConfig.Debug,
 		Usage: "Path of the file to apply",
+		Value: c.cliConfig.Debug,
 	})
 	f.StringFlag(&flagset.StringFlag{
 		Name:  "chain",
-		Value: c.cliConfig.Chain,
 		Usage: "Name of the chain to sync",
+		Value: c.cliConfig.Chain,
 	})
 	f.StringFlag(&flagset.StringFlag{
 		Name:  "log-level",
-		Value: c.cliConfig.LogLevel,
 		Usage: "Set log level for the server",
+		Value: c.cliConfig.LogLevel,
 	})
 	f.StringFlag(&flagset.StringFlag{
-		Name:  "data-dir",
-		Value: c.cliConfig.DataDir,
+		Name:  "datadir",
 		Usage: "Path of the data directory to store information",
+		Value: c.cliConfig.DataDir,
 	})
 	f.StringFlag(&flagset.StringFlag{
 		Name:  "config",
-		Value: &c.configFile,
 		Usage: "File for the config file",
+		Value: &c.configFile,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "syncmode",
+		Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`,
+		Value: c.cliConfig.SyncMode,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "gcmode",
+		Usage: `Blockchain garbage collection mode ("full", "archive")`,
+		Value: c.cliConfig.GcMode,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "lightkdf",
+		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
+		Value: c.cliConfig.UseLightweightKDF,
+	})
+	f.MapStringFlag(&flagset.MapStringFlag{
+		Name:  "whitelist",
+		Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)",
+		Value: c.cliConfig.Whitelist,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "snapshot",
+		Usage: `Enables snapshot-database mode (default = enable)`,
+		Value: c.cliConfig.Snapshot,
+	})
+
+	// heimdall
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "bor.heimdall",
+		Usage: "URL of Heimdall service",
+		Value: c.cliConfig.Heimdall.URL,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "bor.withoutheimdall",
+		Usage: "Run without Heimdall service (for testing purpose)",
+		Value: c.cliConfig.Heimdall.Without,
 	})
 
 	// txpool options
 	f.SliceStringFlag(&flagset.SliceStringFlag{
 		Name:  "txpool.locals",
-		Value: c.cliConfig.TxPool.Locals,
 		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
+		Value: c.cliConfig.TxPool.Locals,
 	})
 	f.BoolFlag(&flagset.BoolFlag{
 		Name:  "txpool.nolocals",
-		Value: c.cliConfig.TxPool.NoLocals,
 		Usage: "Disables price exemptions for locally submitted transactions",
+		Value: c.cliConfig.TxPool.NoLocals,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "txpool.journal",
+		Usage: "Disk journal for local transaction to survive node restarts",
+		Value: c.cliConfig.TxPool.Journal,
+	})
+	f.DurationFlag(&flagset.DurationFlag{
+		Name:  "txpool.rejournal",
+		Usage: "Time interval to regenerate the local transaction journal",
+		Value: c.cliConfig.TxPool.Rejournal,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.pricelimit",
+		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
+		Value: c.cliConfig.TxPool.PriceLimit,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.pricebump",
+		Usage: "Price bump percentage to replace an already existing transaction",
+		Value: c.cliConfig.TxPool.PriceBump,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.accountslots",
+		Usage: "Minimum number of executable transaction slots guaranteed per account",
+		Value: c.cliConfig.TxPool.AccountSlots,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.globalslots",
+		Usage: "Maximum number of executable transaction slots for all accounts",
+		Value: c.cliConfig.TxPool.GlobalSlots,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.accountqueue",
+		Usage: "Maximum number of non-executable transaction slots permitted per account",
+		Value: c.cliConfig.TxPool.AccountQueue,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txpool.globalqueue",
+		Usage: "Maximum number of non-executable transaction slots for all accounts",
+		Value: c.cliConfig.TxPool.GlobalQueue,
+	})
+	f.DurationFlag(&flagset.DurationFlag{
+		Name:  "txpool.lifetime",
+		Usage: "Maximum amount of time non-executable transaction are queued",
+		Value: c.cliConfig.TxPool.LifeTime,
 	})
 
 	// sealer options
 	f.BoolFlag(&flagset.BoolFlag{
 		Name:  "mine",
+		Usage: "Enable mining",
 		Value: c.cliConfig.Sealer.Enabled,
-		Usage: "",
 	})
 	f.StringFlag(&flagset.StringFlag{
 		Name:  "miner.etherbase",
+		Usage: "Public address for block mining rewards (default = first account)",
 		Value: c.cliConfig.Sealer.Etherbase,
-		Usage: "",
 	})
 	f.StringFlag(&flagset.StringFlag{
 		Name:  "miner.extradata",
+		Usage: "Block extra data set by the miner (default = client version)",
 		Value: c.cliConfig.Sealer.ExtraData,
-		Usage: "",
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "miner.gaslimit",
+		Usage: "Target gas ceiling for mined blocks",
+		Value: c.cliConfig.Sealer.GasCeil,
+	})
+	f.BigIntFlag(&flagset.BigIntFlag{
+		Name:  "miner.gasprice",
+		Usage: "Minimum gas price for mining a transaction",
+		Value: c.cliConfig.Sealer.GasPrice,
+	})
+
+	// ethstats
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "ethstats",
+		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
+		Value: c.cliConfig.Ethstats,
+	})
+
+	// gas price oracle
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "gpo.blocks",
+		Usage: "Number of recent blocks to check for gas prices",
+		Value: c.cliConfig.Gpo.Blocks,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "gpo.percentile",
+		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
+		Value: c.cliConfig.Gpo.Percentile,
+	})
+	f.BigIntFlag(&flagset.BigIntFlag{
+		Name:  "gpo.maxprice",
+		Usage: "Maximum gas price will be recommended by gpo",
+		Value: c.cliConfig.Gpo.MaxPrice,
+	})
+	f.BigIntFlag(&flagset.BigIntFlag{
+		Name:  "gpo.ignoreprice",
+		Usage: "Gas price below which gpo will ignore transactions",
+		Value: c.cliConfig.Gpo.IgnorePrice,
+	})
+
+	// cache options
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "cache",
+		Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)",
+		Value: c.cliConfig.Cache.Cache,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "cache.database",
+		Usage: "Percentage of cache memory allowance to use for database io",
+		Value: c.cliConfig.Cache.PercDatabase,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "cache.trie",
+		Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
+		Value: c.cliConfig.Cache.PercTrie,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "cache.trie.journal",
+		Usage: "Disk journal directory for trie cache to survive node restarts",
+		Value: c.cliConfig.Cache.Journal,
+	})
+	f.DurationFlag(&flagset.DurationFlag{
+		Name:  "cache.trie.rejournal",
+		Usage: "Time interval to regenerate the trie cache journal",
+		Value: c.cliConfig.Cache.Rejournal,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "cache.gc",
+		Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
+		Value: c.cliConfig.Cache.PercGc,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "cache.snapshot",
+		Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
+		Value: c.cliConfig.Cache.PercSnapshot,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "cache.noprefetch",
+		Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
+		Value: c.cliConfig.Cache.NoPrefetch,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "cache.preimages",
+		Usage: "Enable recording the SHA3/keccak preimages of trie keys",
+		Value: c.cliConfig.Cache.Preimages,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "txlookuplimit",
+		Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
+		Value: c.cliConfig.Cache.TxLookupLimit,
+	})
+
+	// rpc options
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "rpc.gascap",
+		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
+		Value: c.cliConfig.JsonRPC.GasCap,
+	})
+	f.Float64Flag(&flagset.Float64Flag{
+		Name:  "rpc.txfeecap",
+		Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
+		Value: c.cliConfig.JsonRPC.TxFeeCap,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "ipcdisable",
+		Usage: "Disable the IPC-RPC server",
+		Value: c.cliConfig.JsonRPC.IPCDisable,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "ipcpath",
+		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
+		Value: c.cliConfig.JsonRPC.IPCPath,
+	})
+	f.SliceStringFlag(&flagset.SliceStringFlag{
+		Name:  "rpc.corsdomain",
+		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
+		Value: c.cliConfig.JsonRPC.Cors,
+	})
+	f.SliceStringFlag(&flagset.SliceStringFlag{
+		Name:  "rpc.vhosts",
+		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
+		Value: c.cliConfig.JsonRPC.VHost,
+	})
+	// http options
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "http",
+		Usage: "Enable the HTTP-RPC server",
+		Value: c.cliConfig.JsonRPC.Http.Enabled,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "http.port",
+		Usage: "HTTP-RPC server listening port",
+		Value: c.cliConfig.JsonRPC.Http.Port,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "http.rpcprefix",
+		Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
+		Value: c.cliConfig.JsonRPC.Http.Prefix,
+	})
+	// ws options
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "ws",
+		Usage: "Enable the WS-RPC server",
+		Value: c.cliConfig.JsonRPC.Ws.Enabled,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "ws.port",
+		Usage: "WS-RPC server listening port",
+		Value: c.cliConfig.JsonRPC.Ws.Port,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "ws.rpcprefix",
+		Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
+		Value: c.cliConfig.JsonRPC.Ws.Prefix,
+	})
+	// graphql options
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "graphql",
+		Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.",
+		Value: c.cliConfig.JsonRPC.Graphql.Enabled,
+	})
+
+	// p2p options
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "bind",
+		Usage: "Network binding address",
+		Value: c.cliConfig.P2P.Bind,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "port",
+		Usage: "Network listening port",
+		Value: c.cliConfig.P2P.Port,
+	})
+	f.SliceStringFlag(&flagset.SliceStringFlag{
+		Name:  "bootnodes",
+		Usage: "Comma separated enode URLs for P2P discovery bootstrap",
+		Value: c.cliConfig.P2P.Discovery.Bootnodes,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "maxpeers",
+		Usage: "Maximum number of network peers (network disabled if set to 0)",
+		Value: c.cliConfig.P2P.MaxPeers,
+	})
+	f.Uint64Flag(&flagset.Uint64Flag{
+		Name:  "maxpendpeers",
+		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
+		Value: c.cliConfig.P2P.MaxPendPeers,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "nat",
+		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
+		Value: c.cliConfig.P2P.NAT,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "nodiscover",
+		Usage: "Disables the peer discovery mechanism (manual peer addition)",
+		Value: c.cliConfig.P2P.NoDiscover,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "v5disc",
+		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
+		Value: c.cliConfig.P2P.Discovery.V5Enabled,
+	})
+
+	// metrics
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "metrics",
+		Usage: "Enable metrics collection and reporting",
+		Value: c.cliConfig.Metrics.Enabled,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "metrics.expensive",
+		Usage: "Enable expensive metrics collection and reporting",
+		Value: c.cliConfig.Metrics.Expensive,
+	})
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "metrics.influxdb",
+		Usage: "Enable metrics export/push to an external InfluxDB database (v1)",
+		Value: c.cliConfig.Metrics.InfluxDB.V1Enabled,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.endpoint",
+		Usage: "InfluxDB API endpoint to report metrics to",
+		Value: c.cliConfig.Metrics.InfluxDB.Endpoint,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.database",
+		Usage: "InfluxDB database name to push reported metrics to",
+		Value: c.cliConfig.Metrics.InfluxDB.Database,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.username",
+		Usage: "Username to authorize access to the database",
+		Value: c.cliConfig.Metrics.InfluxDB.Username,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.password",
+		Usage: "Password to authorize access to the database",
+		Value: c.cliConfig.Metrics.InfluxDB.Password,
+	})
+	f.MapStringFlag(&flagset.MapStringFlag{
+		Name:  "metrics.influxdb.tags",
+		Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
+		Value: c.cliConfig.Metrics.InfluxDB.Tags,
+	})
+	// influx db v2
+	f.BoolFlag(&flagset.BoolFlag{
+		Name:  "metrics.influxdbv2",
+		Usage: "Enable metrics export/push to an external InfluxDB v2 database",
+		Value: c.cliConfig.Metrics.InfluxDB.V2Enabled,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.token",
+		Usage: "Token to authorize access to the database (v2 only)",
+		Value: c.cliConfig.Metrics.InfluxDB.Token,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.bucket",
+		Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
+		Value: c.cliConfig.Metrics.InfluxDB.Bucket,
+	})
+	f.StringFlag(&flagset.StringFlag{
+		Name:  "metrics.influxdb.organization",
+		Usage: "InfluxDB organization name (v2 only)",
+		Value: c.cliConfig.Metrics.InfluxDB.Organization,
 	})
 
 	return f