Configure your environment

Often you'll need additional configuration for your functions, such as third-party API keys or tuneable settings. The Firebase SDK for Cloud Functions offers built-in environment configuration to make it easy to store and retrieve this type of data for your project.

You can choose between file-based configuration of environment variables (recommended) or runtime environment configuration with the Firebase CLI and functions.config. Both approaches are described in this guide.

Environment variables

Cloud Functions for Firebase supports the dotenv file format for loading environment variables specified in a .env file to your application runtime. Once deployed, the environment variables can be read via the process.env interface.

To configure your environment this way, create a .env file in your project, add the desired variables, and deploy:

  1. Create a .env file in your functions/ directory:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Open the .env file for edit, and add the desired keys. For example:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Deploy functions and verify that environment variables were loaded:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

Once your your custom environment variables are deployed, your function code can access them with process.env syntax:

// Responds with "Hello Earth and Humans"
exports.hello = functions.https.onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

Deploying multiple sets of environment variables

If you need an alternative set of environment variables for your Firebase projects (such as staging vs production), create a .env.<project or alias> file and write your project-specific environment variables there. The environment variables from .env and project-specific .env files (if they exist) will be included in all deployed functions.

For example, a project could include these three files containing slightly different values for development and production:

.env .env.dev .env.prod
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

Given the values in those separate files, the set of environment variables deployed with your functions will vary depending on your target project:

$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Dev Humans

$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Prod Humans

Reserved environment variables

Some environment variable keys are reserved for internal use. Do not use any of these keys in your .env files:

  • All keys starting with X_GOOGLE_
  • All keys starting EXT_
  • All keys starting with FIREBASE_
  • Any key from the following list:
  • CLOUD_RUNTIME_CONFIG
  • ENTRY_POINT
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • FUNCTION_NAME
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCTION_IDENTITY
  • FUNCTION_REGION
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICE
  • K_REVISION
  • PORT
  • K_CONFIGURATION

Store and access sensitive configuration information

Environment variables stored in .env files can be used for function configuration, but you should not consider them a secure way to store sensitive information such as database credentials or API keys. This is especially important if you check your .env files into source control.

To help you store sensitive configuration information, Cloud Functions for Firebase integrates with Google Cloud Secret Manager. This encrypted service stores configuration values securely, while still allowing easy access from your functions when needed.

Create and use a secret

To create a secret, use the Firebase CLI.

To create and use a secret:

  1. From the root of your local project directory, run the following command:

    firebase functions:secrets:set SECRET_NAME

  2. Enter a value for SECRET_NAME.

    The CLI echoes a success message and warns that you must deploy functions for the change to take effect.

  3. Before deploying, make sure your functions code allows the function to access the secret using the runWith parameter:

    exports.processPayment = functions
      // Make the secret available to this function
      .runWith({ secrets: ["SECRET_NAME"] })
      .onCall((data, context) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      });
  4. Deploy Cloud Functions:

    firebase deploy --only functions

Now you'll be able to access it like any other environment variable. Conversely, if another function that does not specify the secret in runWith tries to access the secret, it receives an undefined value:

exports.anotherEndpoint = functions.https.onRequest((request, response) => {
  response.send(`The secret API key is ${process.env.SECRET_NAME}`);
  // responds with "The secret API key is undefined" because the `runWith` parameter is missing
});

Once your function is deployed, it will have access to the secret value. Only functions that specifically include a secret in their runWith parameter will have access to that secret as an environment variable. This helps you make sure that secret values are only available where they're needed, reducing the risk of accidentally leaking a secret.

Managing secrets

Use the Firebase CLI to manage your secrets. While managing secrets this way, keep in mind that some CLI changes require you to modify and/or redeploy associated functions. Specifically:

  • Whenever you set a new value for a secret, you must redeploy all functions that reference that secret for them to pick up the latest value.
  • If you delete a secret, make sure that none of your deployed functions references that secret. Functions that use a secret value that has been deleted will fail silently.

Here's a summary of the Firebase CLI commands for secret management:

# Change the value of an existing secret
firebase functions:secrets:set SECRET_NAME

# View the value of a secret
functions:secrets:access SECRET_NAME

# Destroy a secret
functions:secrets:destroy SECRET_NAME

# View all secret versions and their state
functions:secrets:get SECRET_NAME

# Automatically clean up all secrets that aren't referenced by any of your functions
functions:secrets:prune

For the access and destroy commands, you can provide the optional version parameter to manage a particular version. For example:

functions:secrets:access SECRET_NAME[@VERSION]

For more information about these operations, pass -h with the command to view CLI help.

How secrets are billed

Secret Manager allows 6 active secret versions at no cost. This means that you can have 6 secrets per month in a Firebase project at no cost.

By default, the Firebase CLI attempts to automatically destroy unused secret versions where appropriate, such as when you deploy functions with a new version of the secret. Also, you can actively clean up unused secrets using functions:secrets:destroy and functions:secrets:prune.

Secret Manager allows 10,000 unbilled monthly access operations on a secret. Function instances read only the secrets specified in their runWith parameter every time they cold start. If you have a lot of function instances reading a lot of secrets, your project may exceed this allowance, at which point you'll be charged $0.03 per 10,000 access operations.

For more information, see Secret Manager Pricing.

Emulator support

Environment configuration with dotenv is designed to interoperate with a local Cloud Functions emulator.

When using a local Cloud Functions emulator, you can override environment variables for your project by setting up a .env.local file. Contents of .env.local take precedence over .env and the project-specific .env file.

For example, a project could include these three files containing slightly different values for development and local testing:

.env .env.dev .env.local
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Local Humans

When started in the local context, the emulator loads the environment variables as shown:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

Secrets and credentials in the Cloud Functions emulator

The Cloud Functions emulator supports the use of secrets to store and access sensitive configuration information. By default, the emulator will try to access your production secrets using application default credentials. In certain situations like CI environments, the emulator may fail to access secret values due to permission restrictions.

Similar to Cloud Functions emulator support for environment variables, you can override secrets values by setting up a .secret.local file. This makes it easy for you to test your functions locally, especially if you don't have access to the secret value.

Migrating from environment configuration

If you have been using environment configuration with functions.config, you can migrate your existing configuration as environment variables (in dotenv format). The Firebase CLI provides an export command that outputs the configuration of each alias or project listed in your directory's .firebaserc file (in the example below, local, dev, and prod) as .env files.

To migrate, export your existing environment configurations using the firebase functions:config:export command:

firebase functions:config:export
i  Importing configs from projects: [project-0, project-1]
⚠  The following configs keys could not be exported as environment variables:

⚠  project-0 (dev):
    1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.)

Enter a PREFIX to rename invalid environment variable keys: CONFIG\_
✔  Wrote functions/.env.prod
✔  Wrote functions/.env.dev
✔  Wrote functions/.env.local
✔  Wrote functions/.env

Note that, in some cases, you will be prompted to enter a prefix to rename exported environment variable keys. This is because not all configurations can be automatically transformed since they may be invalid or may be a reserved environment variable key.

We recommend that you carefully review the contents of the generated .env files before you deploy your functions or check the .env files into source control. If any values are sensitive and should not be leaked, remove them from your .env files and store them securely in Secret Manager instead.

You'll also need to update your functions code. Any functions that use functions.config will now need to use process.env instead, as shown in Environment variables.

Environment configuration

Before environment variable support was released in firebase-functions v3.18.0, using functions.config() was the recommended approach for environment configuration. This approach is still supported, but we recommend all new projects use environment variables instead, as they are simpler to use and improve the portability of your code.

Set environment configuration with the CLI

To store environment data, you can use the firebase functions:config:set command in the Firebase CLI. Each key can be namespaced using periods to group related configuration together. Keep in mind that only lowercase characters are accepted in keys; uppercase characters are not allowed.

For instance, to store the Client ID and API key for "Some Service", you might run:

firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"

Retrieve current environment configuration

To inspect what's currently stored in environment config for your project, you can use firebase functions:config:get. It will output JSON something like this:

{
  "someservice": {
    "key":"THE API KEY",
    "id":"THE CLIENT ID"
  }
}

This functionality is based on the Google Cloud Runtime Configuration API.

Use functions.config to access environment configuration in a function

Some configuration is automatically provided under the reserved firebase namespace. Environment configuration is made available inside your running function via functions.config(). To use the configuration above, your code might look like this:

const functions = require('firebase-functions');
const request = require('request-promise');

exports.userCreated = functions.database.ref('/users/{id}').onWrite(event => {
  let email = event.data.child('email').val();

  return request({
    url: 'https://someservice.com/api/some/call',
    headers: {
      'X-Client-ID': functions.config().someservice.id,
      'Authorization': `Bearer ${functions.config().someservice.key}`
    },
    body: {email: email}
  });
});

Use environment configuration to initialize a module

Some Node modules are ready without any configuration. Other modules need extra configuration to initialize correctly. We recommend you store this configuration in environment configuration variables rather than hard-coding it. This helps you keep your code much more portable, which lets you open source your application or easily switch between production and staging versions.

For example, to use the Slack Node SDK module, you might write this:

const functions = require('firebase-functions');
const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(functions.config().slack.url);

Prior to deploying, set the slack.url environment config variable:

firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX

Additional Environment Commands

  • firebase functions:config:unset key1 key2 removes the specified keys from the config
  • firebase functions:config:clone --from <fromProject> clones another project's environment into the currently active project.

Automatically populated environment variables

There are environment variables that are automatically populated in the functions runtime and in locally emulated functions. These include those populated by Google Cloud, as well as a Firebase-specific environment variable:

process.env.FIREBASE_CONFIG: Provides the following Firebase project config info:

{
  databaseURL: 'https://databaseName.firebaseio.com',
  storageBucket: 'projectId.appspot.com',
  projectId: 'projectId'
}

This configuration is applied automatically when you initialize the Firebase Admin SDK with no arguments. If you are writing functions in JavaScript, initialize like this:

const admin = require('firebase-admin');
admin.initializeApp();

If you are writing functions in TypeScript, initialize like this:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import 'firebase-functions';
admin.initializeApp();

If you need to initialize the Admin SDK with the default project configuration using service account credentials, you can load the credentials from a file and add them to FIREBASE_CONFIG like this:

serviceAccount = require('./serviceAccount.json');

const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);