The “envsubst” tool is part of the GNU’s “gettext” package that programmers use to create multilingual programs. We use envsubst to substitute environment variables in a file or a data stream. This is particularly useful when creating and adapting configuration file templates in a variety of scenarios. For example, you sometimes have a template configuration file for a docker application that has several placeholders for variables such as database credentials and server IP addresses. Using envsubst, you can replace all those variables with the ones specific to your application and have a customized configuration file ready in seconds.
First, let’s look at the regular syntax of envsubst.
Envsubst Syntax
Here’s the basic syntax for the command:
envsubst [OPTION] [SHELL-FORMAT]
In truth, most of the time you won’t even need to use either the [OPTIONS], or the [SHELL-FORMAT] parameters. The command works normally on its own. It’s hard to explain what the parameters do without seeing some examples first.
The only “options” envsubst has is “–help” and “–version”. As you can see, it’s a simple command that doesn’t require any complex configuration.
Basic envsubst Usage
Let’s say I have the following environment variable set in bash:
export NAME="World"
Now, I can access the “NAME” variable in any script. For example, I can echo the following statement:
echo "Hello, $NAME!"
And it gives the following output:
However, if I were to escape the variable, then it would print the variable instead of the value:
echo "Hello, \$NAME!"
Now, given this output, I can use the envsubst tool to replace the “$NAME” variable with its value in the output of the echo statement as shown here:
echo "Hello, \$NAME!" | envsubst
As you can see, when we piped the output to envsubst, the tool replaced the environment variable “$NAME”, with the value “World”.
Now with the above information, we can understand the parameters. Let’s say we use the following statement:
envsubst '$GREETING'
Then the command would replace only the “$GREETING” variable and leave the others alone. Like I said, most of the time you don’t need to do this, since the power of envsubst comes when you use it to replace everything at once. But you might want to proceed step by step, for whatever reason, and then you’ll find the options useful.
Substituting Variables in Configuration Templates
One of the most useful applications of envsubst is when we use it to replace environment variables in standard configuration templates to customize it for our application. For example, let’s say I have a template called “config.template”, containing the following code:
server_name $SERVER;
Now I can use envsubst to create my own configuration file while replacing $SERVER with the name of my server. For example:
export SERVER="example.com"
envsubst < config.template > config
This will result in a file called “config”, containing the following line:
server_name example.com;
Here’s a screenshot:
In the above example, I’ve placed my server name – “example.com” into the config file by exporting it as a variable. Of course, in this example, you could have simply created the file yourself. But imagine how useful this would be when you have a massive configuration file, filled with paths, server names, backup locations, timeout placeholders, and more. You can customize templates much faster with a tool like this.
Here’s a simple example of an nginx template configuration file that we can use to create our own:
export SERVER_NAME="example.com"
export ROOT_DIR="/var/www/html"
cat <<EOF | envsubst > nginx.conf
server {
listen 80;
server_name \$SERVER_NAME;
root \$ROOT_DIR;
}
EOF
In the above example, we replace two variables – “$SERVER_NAME” and “$ROOT_DIR” with our own values. Let’s take a look at some more applications of the envsubst command.
More Applications of the envsubst Command
Here are some other uses for the envsubst command, demonstrating the wide range of scenarios where you will find it useful. All of the examples below are variations on the same theme – using a template file and then substituting the variables within it with values from the Linux environment. Apart from protecting sensitive information, they all have the same goal – ease of use and scalability.
Used in Kubernetes Deployment Configurations
In the context of Kubernetes and Docker, “YAML” configuration files are often used to set up the application. These YAML files often take a “template” form. For example, here’s what a sample YAML file can look like:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: $REPLICA_COUNT
template:
spec:
containers:
- name: app
image: $APP_IMAGE
The above is a Kubernetes deployment YAML file. As you can see, it has two variables – $APP_IMAGE and $REPLICA_COUNT. You can use envsubst to replace both of these with the actual values of your application as follows:
export APP_IMAGE="my-app:latest"
export REPLICA_COUNT=3
envsubst < deployment-template.yaml > deployment.yaml
All we need to do is export the values to the variable names, use envsubst, and write the output to a new deployment file. When you’re a system administrator handling these container applications on a regular basis, envsubst is a tool that you’ll be using regularly.
Dynamically Injecting Secrets
An application has many “secrets” that it wouldn’t want to expose unnecessarily. For example, database passwords, API keys, account passwords, and various other types of sensitive information. Configuration files often require these to be hard-coded into configuration files. For example, the “wp-config.php” file in WordPress contains the database password for WordPress without which, the application can’t function.
However, for some, the stakes might be too high to simply allow sensitive values like this to be hardcoded into a configuration file. But what’s the alternative? Enter envsubst.
Using envsubst, instead of using a file like wp-config.php directly, you will be able to use a template instead, with something like this:
<?php
define('DB_NAME', '$DB_NAME');
define('DB_USER', '$DB_USER');
define('DB_PASSWORD', '$DB_PASSWORD');
define('DB_HOST', '$DB_HOST');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
And set the environment variables like so:
export DB_NAME="wordpress"
export DB_USER="wp_user"
export DB_PASSWORD="super_secret_password"
export DB_HOST="localhost"
Then when the time comes to access wp-config.php, you can use envsubst to replace the variables:
envsubst < wp-config.template.php > wp-config.php
And so the application will find it. To avoid the changes persisting on disk, you can then delete the wp-config.php file so there’s no trace of the secrets. But the above technique must be used carefully, since saving secrets as environment variables comes with its own risks. You’ll need to carefully limit the scope of these variables and take other precautions.
However, one benefit is that such a system can be used with version control since you’re not changing the source files. You can make changes and commit them to the remote branch without uploading the hardcoded secrets as well.
Use in Email Templates
Depending on the application, you can use envsubst to create e-mails with dynamic content. Something like this:
export RECIPIENT="[email protected]"
export SENDER="[email protected]"
cat <<EOF | envsubst > email.txt
To: \$RECIPIENT
From: \$SENDER
Subject: Welcome!
Hello, \$RECIPIENT!
EOF
There are probably easier ways to accomplish this, but you get the idea!
Conclusion
As you can see, envsubst does one job, and it does it well. Whenever you have variables in your scripts and need to replace them with actual values for your application to work, envsubst will be useful. In sophisticated ways, you can also use it to keep secrets and protect them from being exposed on your hard drive.
I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!
Leave a Reply