42

With Divshot shutting down recently, I've switched a number of applications over to Firebase hosting. Some of these apps connect to external APIs, so I need a way to store private environment variables (for example, a secret key for S3 access) on Firebase hosting - anyone have any ideas? There's this article - https://www.firebase.com/blog/2015-10-29-managing-development-environments.html - but that's only for non-private environment variables.

Thanks!

nrswolf
  • 431
  • 1
  • 4
  • 3
  • 2
    Firebase Hosting is intended for static assets. Think of it more like a CDN than a private SSH shell. So it's not a good place to try to store secure environment variables. Perhaps you should start with the X part of the [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378)? – Kato Dec 28 '15 at 21:48
  • Aerobatic does https://www.aerobatic.com/docs/configuration#environment-variables – motleydev Sep 25 '16 at 18:05
  • As the other comments here have hinted at, a better solution might be for your front-end hosted in firebase to call to some endpoint (possibly created in AWS API Gateway) that then returns original data you wanted so that you don't have to directly access S3 from your production client. – Jim Dec 30 '16 at 21:22

7 Answers7

33

Firebase Hosting can not store private environment variables. It is for static hosting only. If you want to use a private variable, you will need to do that server side.

If you want a "Firebase way" to handle secrets, you can use Firebase Cloud Functions, and set an environment variable in cloud functions. Here is the link to the documentation on how to do so: https://firebase.google.com/docs/functions/config-env

If you don't have cloud functions added to your Firebase hosting you can do so via the Firebase cli tools:

firebase init functions
npm install --save firebase-functions@latest
npm install -g firebase-tools

More about that here: https://firebase.google.com/docs/hosting/functions

In order to set environment variables in cloud functions, you can do so from the command line as well like so:

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

You can then access the variables from a function like so:

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}
  });
});
benomatis
  • 5,536
  • 7
  • 36
  • 59
Dylan
  • 1,681
  • 11
  • 16
  • 1
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – Zoe Aug 27 '18 at 15:59
  • 7
    Does not answer OQ – Simon H Sep 28 '19 at 14:31
  • 2
    Is it safe to use `firebase-functions` on the frontend? – Francis Rodrigues Oct 22 '19 at 13:24
  • Firebase functions are cloud based functions like AWS Lambda. They can be invoked from the frontend, but run "server-side". I use quotes because it is actually a serverless function. – Dylan Oct 22 '19 at 16:30
9

You could try out Google's Secret Manager API.

The reasons why this is more secure than storing it as environment variables in Firebase Cloud Functions are:

  1. The Secret Manager API enforces the principle of least privilege. This means that you can restrict access to the secrets and hence only allow authorized users to view/edit the secrets.
  2. The secrets are encrypted using AES-256.
  3. There is an audit logging feature that you can use for anomaly detection.

For more examples of the source codes, you can have a look at the Google Cloud's Secret Manager NPM Package Documentation here.

Hope that it helps!

erwinleonardy
  • 486
  • 8
  • 14
  • I hate the fact that Firebase never says that in the actual documentation for Environment Variables, only in the Security Checklist. Even the way that they wrote that manual, they make it seem like it's totally ok to have secret variables set in ENV Vars – Jean Costa Sep 09 '21 at 21:17
  • Before you use Secret Manager, be sure to understand the [pricing scheme](https://cloud.google.com/secret-manager/pricing). As a comparison, you can store 64 encrypted secrets in Cloudflare's free tier. – thdoan Jun 12 '23 at 07:47
9

If you're looking to use GitHub actions to deploy to Firebase, you can consider creating .env variables before build and deployment.

Simply set your environment variables as secrets under your GitHub repository settings and in your .github/workflows/{action}.yml, add this step

...
- name: Create env file
    run: |
      touch .env
      echo API_ENDPOINT=${{ secrets.API_ENDPOINT }} >> .env
      echo API_KEY=${{ secrets.API_KEY }} >> .env
      cat .env
...

And in your codebase, just call process.env.API_KEY to use the variable!

a.fahmiin
  • 330
  • 3
  • 12
  • 3
    Please do not repost others' answers. If you think this question is a duplicate then flag it as such – Vega Oct 30 '21 at 11:17
8

I have a solution that works for me, based on this article: https://victorbruce82.medium.com/how-to-deploy-a-react-app-to-different-firebase-hosting-environments-dev-and-prod-da3f4cae9a1e

It uses env-cmd, and you don't need cloud-functions to get the right env variables on the current firebase-hosting the site is running from (Since NODE_ENV always returns production when deployed on firebase)

Based on using two separate firebase projects, one for production, one for development. So after adding a 2nd firebase project, used for development:

Add the dev project to your current one with: firebase use --add, and use alias dev.

Create two .env files: .env.production and .env.development with each a variable like:

APP_ENV="production"

(Change it to development in the .env.development file)

(You can also add API-keys to these .env files, make sure you .gitignore them, so you don't have secrets in your codebase)

Now in you code you can reference this with process.env.APP_ENV:

const websiteConfig = process.env.APP_ENV=== 'production' ? {
  themeColor: '#fff'
} : {
  themeColor: '#ccc'
}

(You can also choose to have a APP_THEME_COLOR in your .env files instead and access it directly, depending on your preference)

Install env-cmd

npm i -D env-cmd

Now add 2 scripts to your package.json:

"build:dev":"env-cmd -f .env.development npm run build && firebase deploy -P dev",
"build:prod":"env-cmd -f .env.production npm run build && firebase deploy -P prod"

Now you can deploy your code to two different environments/domains/hosts, but also have them use different environment variables.

(Note: using NODE_ENV in your .env files does not work, it will always return production when deployed on firebase hosting)

TrySpace
  • 2,233
  • 8
  • 35
  • 62
  • Good one, thanks! – Vahe Jun 10 '23 at 12:49
  • It's not necessary to use `env-cmd`. Firebase automatically reads from `.env.` so you can name your dotfiles `.env.dev` and `.env.prod` and you're good to go. [More info](https://firebase.google.com/docs/functions/config-env?gen=2nd#env-variables) – thdoan Jul 24 '23 at 09:19
  • @thdoan but the `build` command doesn't know which env file to use when you run them. or does it read from the `build:x` command which you want to run? – TrySpace Jul 25 '23 at 22:07
  • @TrySpace, if you `firebase use dev` then the deployed function will read environment variables from `.env.dev` automatically. It's documented further down in the page I linked to. – thdoan Jul 26 '23 at 03:44
  • ok, but it depends on the build script you are using if it will pick up whatever firebase 'use's. Hence the `env-cmd` to pass the right env to the build command. – TrySpace Jul 26 '23 at 09:20
  • @TrySpace I use rollup and set up different build commands in the npm run script, e.g.: `"build": "rollup -c", "build-dev": "rollup -c rollup-dev.config.js", "deploy": "firebase use prod && npm run build && firebase deploy", "deploy-dev": "firebase use dev && npm run build-dev && firebase deploy"` – thdoan Jul 29 '23 at 18:56
1

To add .env or environment values to the firebase hosting, follow this steps:

  1. Go the Google Cloud Account https://cloud.google.com/
  2. Choose the same project as the project you're hosting in firebease.
  3. Go to the service cloud function
  4. Find your service and click on edit and your can add env variable, build variable.
  5. (optionally) you can see the build files, you can add/edit .env files

enter image description here

Aravin
  • 6,605
  • 5
  • 42
  • 58
1

As of 2023, you should use secrets instead of config for most of the API access keys:

firebase functions:secrets:set YOUR_ENV_VARIABLE_NAME

And copy paste your secret to the console.

Then in your function, you can access it with

exports["myfunc"] = runWith({secrets: ["YOUR_ENV_VARIABLE_NAME"]}).https.onCall(() => {
  process.env.YOUR_ENV_VARIABLE_NAME
})

For more information, check Firebase Official Document

SeanCheey
  • 143
  • 1
  • 4
0

In order for React to access these environment variables through process.env, start your environment variable name with REACT_APP_