I added environment variables (NODE_ENV) in my 'dev' GitHub Environment.
How can I use it in my Action for my self-hosted runner on AWS?
Now, I tried in this way:
- name: start pm2 service
env:
NODE_ENV: ${{ secrets.NODE_ENV }}
run: NODE_ENV=$NODE_ENV pm2 start ./bin/www --name 'backend'
But I can't get the env on the AWS, my app shows nothing.
Try and and use the official example
steps:
- shell: bash
env:
NODE_ENV: ${{ secrets.NODE_ENV }}
run: |
echo "NODE=ENV='$NODE_ENV'"
pm2 start ./bin/www --name 'backend'
Since NODE_ENV is exported, you might not need to prefix pm2 with NODE_ENV=$NODE_ENV.
However, since the value is still empty, that would confirm the "External Configuration/Secret Sources" is not fully supported yet for an AWS App Runner, assuming it is used for a Github self-hosted runner execution.
That differs from the fact App Runners support GitHub Actions since Nov. 2021.
I am trying to deploy a Next.js application to Azure and I am noticing that the application is not reading from the Application Settings environment variables when I run the application. For example, I created a simple variable called "NEXT_PUBLIC_AZURE_ENV" in the Azure Application Settings.
It seems like from the documentation on Next.js that the environment variables are set at build time.
Our DevOps team is trying to leverage a build once; deploy anywhere approach and having the application read from the Application Settings is what we are trying to do.
Here is the variables declared locally in the local .env file:
Here is the next.js.config file, which I added to the env section, not sure if that is needed or not.
When I print the variable out, it works:
However, once the application is deployed to Azure; the variable to is not being read.
Is it possible to read from Application Settings in Azure from Next.js? Thank you!
To access front-end env variables from an Azure Static app, you need add the env variables inside of your job configuration. For Azure Pipelines, the relevant part should look like:
...
inputs:
app_location: 'src'
api_location: 'api'
output_location: 'public'
azure_static_web_apps_api_token: $(deployment_token)
env: # Add environment variables here
HUGO_VERSION: 0.58.0
For Github Actions:
...
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: 'upload'
app_location: 'src'
api_location: 'api'
output_location: 'public'
env: # Add environment variables here
HUGO_VERSION: 0.58.0
Examples taken from: https://learn.microsoft.com/en-gb/azure/static-web-apps/build-configuration?tabs=github-actions#environment-variables
I have a multicontainer application that I would like to deploy and run within an Azure App Service. The compose file I have, docker-compose.prod.yml, contains environment variables (as shown in the below code).
When I run build the compose file locally, these variables are resolved during the build process by referencing an environment file (env.) located in the same directory:
docker-compose -f docker-compose.prod.yml build push
I know that it is possible to build a DevOps pipeline (as described here), which will insert environment variables during the build process, similar to how I build it locally.
However, I wanted to know if it is possible to either
1.) configure environment variables via the Azure Portal web interface (as you can do with application settings), which the docker compose file can then reference to resolve these variables on startup
or
2.) somehow upload the env. file I use locally which can then be used to resolve the variables on create or startup.
Contents of docker-compose.prod.yml
--------------------------------------------
version: '3.7'
services:
app1:
build: ./app1
command : python3 manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
image: "${AZ_CONTAINER_REGISTRY}/${APP1_IMAGE}:${APP1_VERSION}"
app2:
build: ./app2
command: python app.py
ports:
- 8081:8080
image: "${AZ_CONTAINER_REGISTRY}/${APP2_IMAGE}:${APP2_VERSION}"
restart: always
Contents of env. file
--------------------------------------------
AZ_CONTAINER_REGISTRY=sample.azurecr.io
APP1_IMAGE=app1test
APP1_VERSION=1.0
APP2_IMAGE=app2test
APP2_VERSION=2.0
Any feedback is appreciated, thanks
1.) configure environment variables via the Azure Portal web interface (as you can do with application settings), which the docker compose
file can then reference to resolve these variables on startup
According to my knowledge, the Azure Web App does not support that uses variables instead of the real image currently. Only some variables that Azure gives can be used in the docker-compose file, such as the variable WEBAPP_STORAGE_HOME for persistent storage.
2.) somehow upload the env. file I use locally which can then be used to resolve the variables on create or startup
And it also does not support the env. file, all the docker commands are executed by Azure in the backend. Otherwise, the Azure Web App also does not support the build option in the docker-compopse file, see the supported options.
I was struggling with the exact same question. After a lot of searching I found this post describing a nice little hack.
Add this to your init/startup script:
# Get environment variables to show up in SSH session
eval $(printenv | awk -F= '{print "export " "\""$1"\"""=""\""$2"\"" }' >> /etc/profile)
I can now run my management commands via SSH.
I am importing some secrets from Azure Key Vault to Variable Group to CI / CD pipeline.
I am able to map the required secrets in VariableGroup from KeyVault using Azure Devops UI.
In my pipeline YAML i am able to read and print those VariableGroup variables which are AzureKeyVault secrets.
trigger:
- dev
# define the VM image
pool:
vmImage: "Ubuntu 16.04"
# define variables to use during the build
variables:
- group: SecretVarGroup # it has keyvault variable 'KV_API_KEY'
- group: PublicVarGroup # it has a variable 'API_CLIENTID'
# define the step to export key to env varaiable
steps:
- script: echo $MYSECRETAPIKEY
env:
MYSECRETAPIKEY: $(KV_API_KEY)
## Run the npm build
- script: |
npm run build
displayName: "npm build"
I am able to see value for 'KV_API_KEY' secret printed as *** value in the build output log which i assume its able to consume. I also see value for API_CLIENTID printed in build log as well as node js process.env object.
I was assuming the variable "MYSECRETAPIKEY" will be available in my node js process.env object. But it's not avaialble.
The way i tested it is in my node js project build config i have a print statement which prints process.env object. It printed all the environment variables of pipeline build agent including my PUBLICVARGROUP variable 'API_CLIENTID'. But i don't see my secret variable 'MYSECRETAPIKEY' in the process.env object.
env:
MYSECRETAPIKEY: $(KV_API_KEY)
I thought above line would export variable to specific language process environment. But it is not. How can i fix this?
# define the step to export key to env varaiable
steps:
## Run the npm build
- script: |
npm run build
displayName: "npm build"
env:
MYSECRETAPIKEY: $(KV_API_KEY)
Looks like secrets are scoped on the agent for individual tasks and scripts to use. The issue was i had env: declaraion in a separate adhoc task.Moving it to the same place of my script declaration in the above code has fixed the issue.
Is there anyway to inject environment variables from Cloud Build into the App Engine Standard environment?
I do not want to push my environment variables to GitHub inside the app.yaml or .env. Thus, when Cloud Build pulls and deploys it is missing the .env file and the server is unable to complete some requests.
I am trying to avoid using Datastore as the async nature of Datastore will make the code a lot more messy. I tried to use encrypted secrets found here, but that doesn't seem to work as I added the secrets to app deploy and they do not make their way into the deployment, so I assume this is not the use case for Cloud Build.
I also tried the tutorial here, to import the .env file into App Engine Standard from storage, but since Standard does not have local storage I assume it goes into the void.
So is there anyway to inject the .env into App Engine Standard environment without using Datastore, or committing app.yaml or .env to change control? Potentially using Cloud Build, KMS, or some type of storage?
Here is what I tried for cloudbuild.yaml:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
secretEnv: ['SECRET1', 'SECRET2', 'SECRET3', 'SECRET4', 'SECRET5']
timeout: "1600s"
secrets:
- kmsKeyName: projects/<Project-Name>/locations/global/keyRings/<Key-Ring-Name>/cryptoKeys/<Key-Name>
secretEnv:
SECRET1: <encrypted-key-base64 here>
SECRET2: <encrypted-key-base64 here>
SECRET3: <encrypted-key-base64 here>
SECRET4: <encrypted-key-base64 here>
SECRET5: <encrypted-key-base64 here>
Here is a tutorial on how to securely store env vars in your cloud build (triggers) settings and import them into your app.
Basically there are three steps:
Add your env vars to the 'variables' section in one of your build trigger settings
Screenshot of where to add variables in build triggers
By convention variables set in the build trigger must begin with an underscore (_)
Configure cloudbuild.yaml (on the second step in the code example) to read in variables from your build trigger, set them as env vars, and write all env vars in a local .env file
Add couldbuild.yaml (below) to your project root directory
steps:
- name: node:10.15.1
entrypoint: npm
args: ["install"]
- name: node:10.15.1
entrypoint: npm
args: ["run", "create-env"]
env:
- 'MY_SECRET_KEY=${_MY_SECRET_KEY}'
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
timeout: "1600s"
Add create-env script to package.json
"scripts": {
"create-env": "printenv > .env"
},
Read env vars from .env to your app (config.js)
Install dotenv package
npm i dotenv -S
Add a config.js to your app
// Import all env vars from .env file
require('dotenv').config()
export const MY_SECRET_KEY = process.env.MY_SECRET_KEY
console.log(MY_SECRET_KEY) // => Hello
Done! Now you may deploy your app by triggering the cloud build and your app will have access to the env vars.
I have another solution, if someone is still interested in this. This should work on all languages, because environment variables are added directly into app.yaml file
Add substitution variable in build trigger (as described in this answer).
Add environment variables to app.yaml in a way they can be easily substituted with build trigger variables. Like this:
env_variables:
SECRET_KEY: %SECRET_KEY%
Add a step in cloudbuild.yaml to substitute all %XXX% variables inside app.yaml with their values from build trigger.
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
sed -i 's/%SECRET_KEY%/'${_SECRET_KEY}'/g' app.yaml
gcloud app deploy app.yaml
The highfivebrian answer is great, but I'm adding my slightly different solution.
1). In the root project folder we need the cloudbuild.yaml file but I'll call it buildsetttings.yaml, because
first one name have a problem
In buildsetttings.yaml I added this code:
steps:
- name: node
entrypoint: npm
args: ['install']
- name: node
entrypoint: npm
env:
- 'DB_URL=${_DB_URL}'
- 'SENDGRID_API_KEY=${_SENDGRID_API_KEY}'
- 'CLIENT_ID=${_CLIENT_ID}'
args: ['run', 'create-app-yaml']
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy']
buildsetttings.yaml will be create app.yaml file in the Cloud Build, using a npm create-app-yaml command.
Tip: app.yaml file we will then use to deploy our app to GCP App Engine.
2). In the root folder(near buildsetttings.yaml) we need to create create-app-yaml.js which will run in Cloud Build after it is called from buildsetttings.yaml.
In buildsetttings.yaml I added this code:
require('dotenv').config();
const fs = require('fs');
const appYamlContent = `runtime: nodejs14
env_variables:
DB_URL: ${process.env.DB_URL}
SENDGRID_API_KEY: ${process.env.SENDGRID_API_KEY}
CLIENT_ID: ${process.env.CLIENT_ID}`;
fs.writeFileSync('./app.yaml', appYamlContent);
This code using a npm package dotenv(add it to package.json) and get variables from Cloud Build Trigger Variables and create with they app.yaml file.
3). app.yaml file was created in the Cloud build and our last step(name: 'gcr.io/cloud-builders/gcloud') in the buildsetttings.yaml, using app.yaml file, deploy the project to the Google Cloud App Engine.
Success!
In short, it works like this: buildsetttings.yaml run "create-app-yaml.js" in the Cloud Build, after which dynamically creates an app.yaml file by adding variables from Cloud Build Trigger Variables, then makes a deployment in the App Engine.
Notes:
Delete the file app.yamlin from you project, because it will be create dynamically in the Cloud Build. Also delete cloudbuild.yaml file, because instead we use buildsetttings.yaml.
package.json:
Cloud Build Trigger Variables:
As of 2020/11/13. It seem like .env will work only at that step and in the next step an invisible .env will no longer there.
If you get stuck do try consume that printed .env it in 1 step like this ...
in cloudbuild.yaml
# [START cloudbuild_yarn_node]
steps:
# Install
- name: node
entrypoint: yarn
args: ["install"]
# Build
- name: node
entrypoint: yarn
env:
- "FOO=${_FOO}"
args: ["env-build"]
and in package.json add this
{
"scripts": {
"env-build": "printenv > .env && yarn build",
}
}
in index.js
require('dotenv').config();
console.log(process.env.FOO);
Took me an hour to figure this out.
First, I created secret using gcp secret manager and uploaded my env file there.
Second, I called the secret in cloudbuild.yaml on run time and created a file with name of '.env' using echo.
Example
steps:
- id: "Injecting ENV"
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
args:
- '-c'
- |
echo $$ENV > .env
secretEnv: ['ENV']
availableSecrets:
- versionName: projects/<Project-Name>/secrets/environment-variables/versions/1
env: 'ENV'
timeout: 900s
Based on your preferences that you have highlighted (Cloud Build, KMS). The Google Secrets link that you had mentioned involves storing sensitive data at build or runtime using Cloud KMS: KeyRing and CryptoKey. However, Google offers other Secret Management Solutions using Cloud KMS as well.
Here are a couple of other options you can use while storing Secrets:
Option 1 : You can store Secrets in code that are encrypted with a key from Cloud KMS.
(This is typically used by encrypting your secret at the application layer.)
Benefit: Provides a layer of security from insider threats because it restricts access to the code with a corresponding key.
[You can find some additional information about these options on the Google Documentation here.]
Option 2: You can Store Secrets inside a Google Storage Bucket where your data is at rest encryption. (Similar to option 1 this has the ability to limit access to secrets to a small group of Developers.)
Benefit: Storing your secrets in a separate location ensures that if a breach of your code repository has occurred, your secrets may still be protected.)
[Note: Google recommends that you use two projects for proper separation of duties. One project will use Cloud KMS to manage the keys and the other project will use Cloud Storage to store the secrets.]
If the options listed above still do not meet your needs, I have found a StackOverflow question that shares a similar objective as your project. (i.e: Storing environment variables in GAE without Datastore)
The solution provided on this link illustrates the use of storing keys in a client_secrets.json file that gets excluded when uploading to git by listing it in .gitignore. You can find some Google examples (Python) of usage here.