Automatically update your secrets and environment variables from a 1Password vault
Set up .env file
Create a .env
file with a variable DEVELOPMENT_ENVS_UPDATED
and set it to the current date.
sh
# Update this whenever you make changes to the fileDEVELOPMENT_ENVS_UPDATED=2022-JAN-11
Set up 1Password vault
Follow the instructions on this guide to importing secrets from 1Password to set up a 1Password vault.
When you are done, you will have 4 pieces of information to assign to environment variables.
sh
PASSWORD_TOKENPASSWORD_CREDENTIALSVAULT_IDENV_FILE_ID
Create a file sync-env.sh
sh
#!/bin/bash -uapology () { echo "💬 Could not update .env file due to missing $1. Check 1Password for the latest .env file"}: ${VAULT_ID:?"$(apology VAULT_ID)"}: ${ENV_FILE_ID:?"$(apology ENV_FILE_ID)"}: ${PASSWORD_TOKEN:?"$(apology PASSWORD_TOKEN)"}: ${PASSWORD_CREDENTIALS:?"$(apology PASSWORD_CREDENTIALS)"}if [ ! "$(command -v docker)" ]; then echo "💬 Could not update .env file automatically. Check 1Password for the latest variables" echo "🐳 Docker daemon not installed. Install docker to fetch .env file automatically" exit 1fidocker stop op-connect-api 2>/dev/null && docker rm op-connect-apidocker stop op-connect-sync 2>/dev/null && docker rm op-connect-syncecho $PASSWORD_CREDENTIALS > "1password-credentials.json"docker run -d \ --name op-connect-api \ -p 8080:8080 \ -v "$(pwd)/1password-credentials.json:/home/opuser/.op/1password-credentials.json" \ -v "data:/home/opuser/.op/data" \ 1password/connect-api:latestdocker run -d \ --name op-connect-sync \ -p 8081:8080 \ -v "$(pwd)/1password-credentials.json:/home/opuser/.op/1password-credentials.json" \ -v "data:/home/opuser/.op/data" \ 1password/connect-sync:latestgp await-port 8080sleep 5curl -L "http://0.0.0.0:8080/v1/vaults/$VAULT_ID/items/$ENV_FILE_ID" \ -H "Authorization: Bearer $PASSWORD_TOKEN" \ | jq -r .fields[0].value \ > .envecho "Stopping container…"docker stop op-connect-api && docker rm op-connect-apiecho "Stopping container…"docker stop op-connect-sync && docker rm op-connect-syncrm "1password-credentials.json"echo "Updated .env file"
Create a file sync-env.js
js
const fs = require("fs")const path = require("path")/** * Load environment variables from .env * * If they are out of date, or do not exist, download and update them * If they are newer than this file, update this file */module.exports = function syncEnvFile() { require("dotenv").config() /** This variable will update itself when the .env does */ const LATEST_ENVS_DATE = "2022-JAN-11" if ( process.env.DEVELOPMENT_ENVS_UPDATED !== LATEST_ENVS_DATE ) { if (!process.env.DEVELOPMENT_ENVS_UPDATED) { console.error("The .env file is missing") } else { const claimedDate = new Date( process.env.DEVELOPMENT_ENVS_UPDATED, ) const latestDate = new Date(LATEST_ENVS_DATE) if (claimedDate > latestDate) { const thisFilename = path.basename(__filename) console.info( `Updating ${thisFilename} to`, process.env.DEVELOPMENT_ENVS_UPDATED, ) console.log("Please commit this change") const thisFile = fs.readFileSync( thisFilename, "utf8", ) const occurrences = thisFile.split(LATEST_ENVS_DATE).length - 1 if (occurrences !== 1) throw new Error("Cannot automatically update") fs.writeFileSync( thisFilename, thisFile.replace( LATEST_ENVS_DATE, process.env.DEVELOPMENT_ENVS_UPDATED, ), "utf-8", ) return } else { console.error( "The .env file changed on", LATEST_ENVS_DATE, ) } } const { execSync } = require("child_process") console.log( "Downloading latest .env file from 1Password…", ) try { execSync("sh sync-env.sh", { encoding: "utf-8", }) console.log("The .env file is now up to date") } catch (error) { console.error(error.stdout.toString()) } process.exit(1) } else { console.log("The .env file is up to date") }}
Usage
As early as possible in your application, add this line of code. In a node server, this is probably the top of your index.js
, main.js
, or server.js
js
if (process.env.NODE_ENV !== "production") { // Update and load .env file require("./sync-env")()}
Error cases
Missing 1Password environment variables
The .env file is missing
Downloading latest .env file from 1Password…
sync-env.sh: line 7: VAULT_ID: 💬 Could not update .env file due to missing VAULT_ID. Check 1Password for the latest .env file
```