Skip to content

Instantly share code, notes, and snippets.

@koistya
Last active October 23, 2023 14:08
Show Gist options
  • Save koistya/5fb986553efd21796e330f67cd660b2e to your computer and use it in GitHub Desktop.
Save koistya/5fb986553efd21796e330f67cd660b2e to your computer and use it in GitHub Desktop.
Load environment variables and secrets from `.env` files and Google Secret Manager.

Environment Variables and Secrets

The following demonstrates how to load environment variables and secret values into a software project for local development.

  • [Step 1]: Create secret records in Google Secret Manager
  • [Step 2]: Save environment variables and secret references to .env file(s)
  • [Step 3]: Add a call to loadEnv(environment, options) where you need those variables

Basic Example

.env — environment variables

# Environment varialbes and secrets
# NOTE: You can reference secrets from a cloud secret manager by
#       following this pattern: secret://[provider]/[resource]

# Google Cloud
# https://console.cloud.google.com/
GOOGLE_CLOUD_PROJECT=example
GOOGLE_CLOUD_REGION=us-central1

# Cloud Identity Platform (a.k.a. Firebase Auth)
# https://console.cloud.google.com/customer-identity
FIREBASE_APP_ID=1:674174690042:web:bb8d27dcc9e48fc0a7690d
FIREBASE_API_KEY=BIzbEyGBAlkrEIvlYgZeub9LBCkYJM6ySIMF2Je
FIREBASE_AUTH_DOMAIN=example.com

# Cloudflare
# https://dash.cloudflare.com/
CLOUDFLARE_ACCOUNT_ID=a8b47b39ab92525b2653229b28a1fc31
CLOUDFLARE_ZONE_ID=f3206a12cd93f45de116318496037c9f
CLOUDFLARE_API_TOKEN=secret://google/projects/example/secrets/cloudflare-api-token/versions/latest

# PostgreSQL Database
# https://www.postgresql.org/docs/current/libpq-envars.htm
PGHOST=34.172.75.101
PGPORT=5432
PGUSER=secret://google/projects/example/secrets/db-user/versions/latest
PGPASSWORD=secret://google/projects/example/secrets/db-password/versions/latest

# SendGrid
# https://app.sendgrid.com/settings/api_keys
EMAIL_FROM=[email protected]
SENDGRID_API_KEY=secrets://google/projects/example/secrets/sendgrid-api-key/versions/latest

NOTE: Only PGUSER, PGPASSWORD, CLOUDFLARE_API_TOKEN, and SENDGRID_API_KEY are actually secrets in the example above. The rest environment variables can be included as plain text into .env files.

NOTE: You can reference secret values using the following pattern secret://[provider]/[resource].

./core/env.ts — environment variables schema (validator)

To ensure that the app fails in case of any of the environment variables required by the app are missing or malformed, it's a good idea to create a validator (schema) similar to this:

import { cleanEnv, num, str } from "envalid";

export default cleanEnv(process.env, {
  GOOGLE_CLOUD_PROJECT: str(),
  GOOGLE_CLOUD_REGION: str(),
  
  FIREBASE_APP_ID: str(),
  FIREBASE_API_KEY: str(),
  FIREBASE_AUTH_DOMAIN: str(),
  
  PGHOST: str(),
  PGPORT: num(),
  PGUSER: str(),
  PGPASSWORD: str(),

  EMAIL_FROM: str(),
  SENDGRID_API_KEY: str(),
});

./vite.config.ts — Vite configuration

If you're launching your Node.js app using Vite / Vite Node, you would load secrets inside of the vite.configt.ts file as follows:

import { defineConfig } from "vite";
import { loadEnv } from "envars";

export default defineConfig(async ({ mode }) => {
  await loadEnv(mode, {
    root: ".",
    schema: "./core/env.ts",
    mergeTo: process.env,
  });

  return {
    build: {
      ssr: "index.ts",
      target: "esnext",
      sourcemap: true,
    },
  };
});

NOTE: Normally, you want to use loadEnv(...) helper function just for local development and deployment. For example, if you deploy your app to Google Cloud Functions it supports secrets from Google Secret Manager natively.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment