Jacob Paris
← Back to all content

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 file
DEVELOPMENT_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_TOKEN
PASSWORD_CREDENTIALS
VAULT_ID
ENV_FILE_ID

Create a file sync-env.sh

sh
#!/bin/bash -u
apology () {
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 1
fi
docker stop op-connect-api 2>/dev/null && docker rm op-connect-api
docker stop op-connect-sync 2>/dev/null && docker rm op-connect-sync
echo $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:latest
docker 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:latest
gp await-port 8080
sleep 5
curl -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 \
> .env
echo "Stopping container…"
docker stop op-connect-api && docker rm op-connect-api
echo "Stopping container…"
docker stop op-connect-sync && docker rm op-connect-sync
rm "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
```
Professional headshot
Moulton
Moulton

Hey there! I'm a developer, designer, and digital nomad building cool things with Remix, and I'm also writing Moulton, the Remix Community Newsletter

About once per month, I send an email with:

  • New guides and tutorials
  • Upcoming talks, meetups, and events
  • Cool new libraries and packages
  • What's new in the latest versions of Remix

Stay up to date with everything in the Remix community by entering your email below.

Unsubscribe at any time.