Cloudflare Pages
Learn how to sync your Doppler secrets with Cloudflare Pages
This guide will show you how to sync secrets from Doppler to Cloudflare Pages environment variables using the Cloudflare Pages Update Project API.
Prerequites
- Cloudflare Custom API Token, Account Id, and Page Name
- The Doppler CLI is installed
- The jq shell binary installed
Cloudflare Custom API Token
You'll need a Cloudflare Custom API Token to authentication with their API. This token will need the Account.Cloudflare Pages
permission with Edit
access. To create that token, follow this process:
- Browse to the API Tokens page
- Click the Create Token button
- Click the Get Started button near the bottom of the page next to "Create Custom Token"
- Name your token "Doppler" (or whatever else you like)
- For Permissions choose Account, then Cloudflare Pages (note that the list is not alphabetized), and finally Edit
- Choose the Account(s) you would like to include
- Click the Continue to Summary button
- Click the Create Token button
- Copy your token and store this in your Doppler project as
CLOUDFLARE_API_TOKEN
Service Token
To sync your secrets to Clouflare Pages as part of a CI/CD, the Doppler CLI requires a Service Token to provide read-only access to a specific config and is exposed to the CLI via the DOPPLER_TOKEN
environment variable.
You'll need to use multiple service tokens if wanting to sync separate Doppler configs to Cloudflare's Preview and Production environments.
Script
Save the contents of the below Doppler created bash script to cloudflare-pages-secrets-sync.sh
.
#!/usr/bin/env bash
log () {
case $1 in
info)
echo -e "\n\e[92m[info]: $2"
;;
warn)
echo -e "\n\e[93m[warn]: $2"
;;
error)
echo -e "\n\e[91m[error]: $2"
;;
*)
echo -e "\n\e[92m[$1]: $2"
esac
}
#################################################
# Confirm selected Doppler Project and Config #
#################################################
if ! doppler secrets > /dev/null 2>&1; then
log error "Doppler Project and Config not set. Expose a service token using the \$DOPPLER_TOKEN environment variable or run 'doppler setup' prior to executing this script.\n"
exit 1
fi
DOPPLER_PROJECT=$(doppler secrets get DOPPLER_PROJECT --plain)
DOPPLER_CONFIG=$(doppler secrets get DOPPLER_CONFIG --plain)
################################
# Required Cloudflare config #
################################
if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
echo -en '\nCLOUDFLARE_ACCOUNT_ID: ' && read -rs CLOUDFLARE_ACCOUNT_ID
fi
if [ -z "$CLOUDFLARE_API_TOKEN" ]; then
echo -en '\nCLOUDFLARE_API_TOKEN: ' && read -rs CLOUDFLARE_API_TOKEN
fi
if [ -z "$CLOUDFLARE_PAGES_NAME" ]; then
echo -en '\nCLOUDFLARE_PAGES_NAME: ' && read -r CLOUDFLARE_PAGES_NAME
fi
if [ -z "$CLOUDFLARE_PAGES_ENVIRONMENT" ]; then
echo -en '\nCLOUDFLARE_PAGES_ENVIRONMENT (preview|production): ' && read -r CLOUDFLARE_PAGES_ENVIRONMENT
fi
if [[ $CLOUDFLARE_PAGES_ENVIRONMENT != "production" ]] && [[ $CLOUDFLARE_PAGES_ENVIRONMENT != "preview" ]]
then
log error 'The CLOUDFLARE_PAGES_ENVIRONMENT must be either "production" or "preview"\n'
exit 1
fi
CLOUDFLARE_PAGE_URL="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PAGES_NAME"
# Verify supplied credentials
if ! curl --silent --fail --tlsv1.2 --proto "=https" -X GET "$CLOUDFLARE_PAGE_URL" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" > /dev/null; then
log error "Sorry, the supplied Cloudflare credentials appear to be invalid\n"
exit 1
fi
#########################
# Cloudflare functions #
#########################
cloudflare_deploy () {
curl --fail --silent --tlsv1.2 --proto "=https" -X "$1" "$CLOUDFLARE_PAGE_URL/deployments" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json"
}
cloudflare_env_vars () {
if [[ -n "$2" ]]; then
curl --fail --silent -X "$1" "$CLOUDFLARE_PAGE_URL" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data "$2";
else
curl --fail --silent -X "$1" "$CLOUDFLARE_PAGE_URL" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json";
fi
}
env_vars_payload () {
echo "{\"deployment_configs\":{\"$1\":{\"env_vars\":$2}}}"
}
####################################
# Verify Cloudflare Pages config #
####################################
if ! cloudflare_env_vars GET > /dev/null; then
log error "Sorry, a Pages app '$CLOUDFLARE_PAGES_NAME' belonging to Account Id '$CLOUDFLARE_ACCOUNT_ID' could not be found.\n"
exit 1
fi
if [[ -n "$IMPORT_CLOUDFLARE" ]]; then
log info "\$IMPORT_CLOUDFLARE set: Importing secrets from $CLOUDFLARE_PAGES_NAME $CLOUDFLARE_PAGES_ENVIRONMENT to Doppler"
doppler secrets upload <(jq -cr '.result.deployment_configs.production.env_vars | with_entries(.value |= .value)' <(cloudflare_env_vars GET))
fi
if [[ -n "$CLEAN_SYNC" ]]; then
log info "\$CLEAN_SYNC set: Deleting all $CLOUDFLARE_PAGES_NAME $CLOUDFLARE_PAGES_ENVIRONMENT envirionment variables"
NULL_ENV_VARS=$(jq -cr '.result | select(.deployment_configs == "production") | .env_vars | with_entries(.value |= null)' <(cloudflare_env_vars GET))
cloudflare_env_vars PATCH "$(env_vars_payload production "$NULL_ENV_VARS")" > /dev/null
fi
##################
# Sync Secrets #
##################
log info "Syncing secrets from Doppler ($DOPPLER_PROJECT > $DOPPLER_CONFIG) to Cloudflare Pages ($CLOUDFLARE_PAGES_NAME > $CLOUDFLARE_PAGES_ENVIRONMENT)"
DOPPLER_SECRETS=$(jq -cr '. | with_entries(.value = { "value": (.value)})' <(doppler secrets download --no-file --format json))
cloudflare_env_vars PATCH "$(env_vars_payload "$CLOUDFLARE_PAGES_ENVIRONMENT" "$DOPPLER_SECRETS")" > /dev/null
log info 'Done!'
# Optional production deployment trigger to apply secret updates
if [[ -n "$AUTO_DEPLOY" ]]; then
log info "\$AUTO_DEPLOY set: Triggering deploy so environment variable updates are applied"
if ! cloudflare_deploy POST > /dev/null; then
log error "Deployment failed. Please check your Cloudflare Pages deployment logs\n"
else
log info "Deployment triggered successfully\n"
fi
fi
Configuration
The following environment variables must be set or will be prompted for when running the script.
Cloudflare Credentials
export CLOUDFLARE_ACCOUNT_ID
: Account Idexport CLOUDFLARE_API_TOKEN
: The custom API token you created earlier
Cloudflare Pages Config
export CLOUDFLARE_PAGES_NAME
: Name of your Cloudflare Pages applicationexport CLOUDFLARE_PAGES_ENVIRONMENT
(preview | production): Which environment to sync secrets to
You can also optionally set the following environment variables for additional behavior:
export IMPORT_CLOUDFLARE=yes
: Will import the current environment variables from Cloudflare to Doppler before syncing (only use this once)export CLEAN_SYNC=yes
: Doppler is the source of truth and any environment variables not in Doppler will be deletedexport AUTO_DEPLOY
: Trigger a deploy in order to apply the environment variable updates
Usage
Once the required environment variables are set, secrets can be synced in a single command:
CLOUDFLARE_PAGES_NAME=your-pages-app \
CLOUDFLARE_PAGES_ENVIRONMENT=production \
AUTO_DEPLOY=yes \
./cloudflare-pages-secrets-sync.sh
To also trigger a production deployment to immediately apply the secret updates (recommended), add AUTO_DEPLOY=yes
:
CLOUDFLARE_PAGES_NAME=your-pages-app \
CLOUDFLARE_PAGES_ENVIRONMENT=production \
AUTO_DEPLOY=yes \
./cloudflare-pages-secrets-sync.sh
Awesome Work!
Now you know to use Doppler to easily sync secrets to Cloudflare Pages environment variables in CI/CD environments.
Updated 3 months ago