lightningnetwork/lnd

[documentation] [feature]: sample-lnd.conf makes misleading or wrong statement about env var expansion

dienummer opened this issue · 2 comments

Background

sample-lnd.conf contains the statement "Environment variables are expanded so they may be used" near the top of the file:

; on Plan9. Environment variables are expanded so they may be used. NOTE:

However, this is only true for path-type variables, which call CleanAndExpandPath when they are parsed:

lnd/config.go

Line 1749 in 7af1957

func CleanAndExpandPath(path string) string {
, and for the special case of the rpc user and rpc password, parsed by supplyEnvValue

lnd/config.go

Line 1951 in 7af1957

func supplyEnvValue(value string) string {

lnd/config.go

Lines 1831 to 1834 in 7af1957

// Resolves environment variable references in RPCUser
// and RPCPass fields.
conf.RPCUser = supplyEnvValue(conf.RPCUser)
conf.RPCPass = supplyEnvValue(conf.RPCPass)

It could be extremely important to allow env var substitution also for backend RPC hostname, ZMQ host and port, etc. when running in a container orchestration system or other professional setup.

In general, storing critical elements of the config in the environment is preferred (https://12factor.net/config)

Your environment

  • version of lnd: v0.17.4-beta
  • which operating system (uname -a on *Nix) Linux ubuntu 6.8.0-22-generic #22-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 4 22:30:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
  • version of btcd, bitcoind, or other backend 26.1
  • any other relevant environment details (N/A)

Steps to reproduce

N/A; see https://github.com/lightningnetwork/lnd/blob/7af195768aa3e06ec447615ce25dd32343d8bd59/config.go and in particular review lines

lnd/config.go

Lines 927 to 945 in 7af1957

cfg.DataDir = CleanAndExpandPath(cfg.DataDir)
cfg.TLSCertPath = CleanAndExpandPath(cfg.TLSCertPath)
cfg.TLSKeyPath = CleanAndExpandPath(cfg.TLSKeyPath)
cfg.LetsEncryptDir = CleanAndExpandPath(cfg.LetsEncryptDir)
cfg.AdminMacPath = CleanAndExpandPath(cfg.AdminMacPath)
cfg.ReadMacPath = CleanAndExpandPath(cfg.ReadMacPath)
cfg.InvoiceMacPath = CleanAndExpandPath(cfg.InvoiceMacPath)
cfg.LogDir = CleanAndExpandPath(cfg.LogDir)
cfg.BtcdMode.Dir = CleanAndExpandPath(cfg.BtcdMode.Dir)
cfg.BitcoindMode.Dir = CleanAndExpandPath(cfg.BitcoindMode.Dir)
cfg.BitcoindMode.ConfigPath = CleanAndExpandPath(
cfg.BitcoindMode.ConfigPath,
)
cfg.BitcoindMode.RPCCookie = CleanAndExpandPath(cfg.BitcoindMode.RPCCookie)
cfg.Tor.PrivateKeyPath = CleanAndExpandPath(cfg.Tor.PrivateKeyPath)
cfg.Tor.WatchtowerKeyPath = CleanAndExpandPath(cfg.Tor.WatchtowerKeyPath)
cfg.Watchtower.TowerDir = CleanAndExpandPath(cfg.Watchtower.TowerDir)
cfg.BackupFilePath = CleanAndExpandPath(cfg.BackupFilePath)
cfg.WalletUnlockPasswordFile = CleanAndExpandPath(
which are distinct from non-path type config settings (with the exception of RPCuser and RPCpass, which are the only other elements parsed from environment)

Expected behaviour

I expect env var expansion / substitution to work for all config settings so that I can more easily deploy LND in a professionally-managed container orchestration setup.

I would also expect that RPCUser and RPCPass config item env var expansion be documented.

Actual behaviour

Documentation suggests any config item could undergo variable expansion.

Only path-type vars, plus RPCUser and RPCPass undergo env var substitution.

Documentation does not mention that RPCUser and RPCPass undergo env var substitution.

Oops. Ran into this issue also. I guess the hack/workaround is to create a script that writes a uniqe lnd.conf for each deployment?

It's correct that the text about the env variable parameter expansion is a bit misleading. But it's actually only meant for the datadir variable, not for the whole file. But any field that takes a directory or file path can use environment variables.
And any password field also allows expansion, although with a slightly extended syntax: #8310

So in short, anything that isn't a path/directory or password value doesn't support environment variable expansion.

Oops. Ran into this issue also. I guess the hack/workaround is to create a script that writes a uniqe lnd.conf for each deployment?

I would suggest using command line flags for the dynamic parts. You can mix a configuration file and command line flags, IIRC command line flags take precedence. So have everything general in the config file and then use node-specific values in flags, such as ports, paths and so on.