Neat trick for over-writing default environment variable values for daemons

I thought this was a neat trick I found using command-chain and environment for snaps to have default, but over-written environment variables. If you define an environment variable such as VAULT_ADDR in my case to something, then that value is set by snapd before launching the command or any of the command-chains. This means you could modify the value of that environment variable before the final command is launched by creating a command-chain script which changes that value. For example take the following snapcraft.yaml snippet for vault:

apps:
  vault:
    adapter: full
    command: bin/vault server --config $VAULT_CONFIG
    daemon: simple
    environment:
      VAULT_ADDR: "https://localhost:8200"
      VAULT_CONFIG: "$SNAP_DATA/config/security-secret-store/vault-config.hcl"

This works to set the environment variable, but what if we want a different port number or host-name for vault to listen on? Well we can write a simple command-chain script like this which checks for a config setting with snapctl and then if set, uses that instead. See:

#!/bin/bash -e

VAULT_ADDR_SNAP_CONFIG="$(snapctl get vault-addr)"
if [ -n "$VAULT_ADDR_SNAP_CONFIG" ]; then 
    VAULT_ADDR="$VAULT_ADDR_SNAP_CONFIG"
fi

export VAULT_ADDR

exec "$@"

Then we specify the command-chain for this little script in the snapcraft.yaml (of course after having a part somewhere that stages the script into the snap at bin/vault-addr-config.sh):

apps:
  vault:
    adapter: full
    command: bin/vault server --config $VAULT_CONFIG
    command-chain:
      - bin/vault-addr-config.sh
    daemon: simple
    environment:
      VAULT_ADDR: "https://localhost:8200"
      VAULT_CONFIG: "$SNAP_DATA/config/security-secret-store/vault-config.hcl"

and now you can configure the vault address with snapctl:

$ snap set $SNAP_NAME vault-addr="https://localhost:8300"

This same trick would work for user run apps as well, and in that case you could even expand the script slightly to inspect the user’s environment for VAULT_ADDR and instead define DEFAULT_VAULT_ADDR in the environment in snapcraft.yaml and have the command-chain script set VAULT_ADDR to DEFAULT_VAULT_ADDR if VAULT_ADDR isn’t already defined, allowing a user to set that themselves if they want to set it manually like:

$ VAULT_ADDR="https://localhost:8700" vault server --config ...
1 Like

any reason to use a 1MB shell binary to run these 6 lines instead of /bin/sh (which is 150k) ? :slight_smile:

because bash is easier to write in than sh and I like using up people’s memory

1 Like

"and now you can configure the vault address with snapctl: $ snap set $SNAP_NAME vault-addr=“https://localhost:8300”

Thinking that second line should be running “snapctl”, not “snap”, and not need $SNAP_NAME.