ServicesAboutNotesContact Get in touch →
EN FR
Note

CLOUDSDK_CONFIG for Per-Project gcloud Isolation

How CLOUDSDK_CONFIG isolates all gcloud state per project — credentials, ADC files, active config — and why it's the missing piece for multi-client GCP work.

Planted
gcpdata engineeringautomation

The gcloud CLI stores everything in a single directory: ~/.config/gcloud/. One set of credentials, one active configuration, one Application Default Credentials file — shared across every terminal window and every process on your machine. When you run gcloud config set project client-a, that change affects every other session reading from the same directory.

This works for single-project setups. For multi-project work, the shared state creates auth errors when contexts change.

The Root of the Problem

gcloud’s global mutable state means that switching context in one terminal affects every other terminal. A few failure modes that happen regularly on consulting machines:

  • You start a dbt build for Client A, switch your gcloud context to Client B in another terminal. Client A’s build starts failing with permission errors halfway through.
  • You run gcloud auth application-default login for a new client. The ADC file gets overwritten system-wide, breaking everything that was using the previous credentials.
  • You start Claude Code in a new terminal and it picks up stale credentials from whatever project you last authenticated against.

AWS handles this differently — profiles are named, and there’s no shared “active” context that leaks across sessions. Google chose global mutable state. CLOUDSDK_CONFIG is the escape hatch.

What CLOUDSDK_CONFIG Does

Setting CLOUDSDK_CONFIG to a directory path tells gcloud to use that directory as its entire state store instead of ~/.config/gcloud/. This includes:

  • credentials.db — OAuth tokens for the gcloud CLI
  • application_default_credentials.json — ADC file used by client libraries
  • properties — active configuration (active project, account, region)
  • access_tokens.db — cached access tokens
  • logs/ — gcloud command logs

Two terminal sessions using different CLOUDSDK_CONFIG paths cannot interfere with each other. They’re using completely separate state. Authenticating in one has no effect on the other.

Terminal window
# Terminal 1: Client A
export CLOUDSDK_CONFIG="$HOME/.config/gcloud-acme"
gcloud auth login # authenticates only in ~/.config/gcloud-acme/
# Terminal 2: Client B — completely independent
export CLOUDSDK_CONFIG="$HOME/.config/gcloud-globex"
gcloud auth login # authenticates only in ~/.config/gcloud-globex/

The Four Variables for Full Isolation

CLOUDSDK_CONFIG alone isn’t enough because gcloud and client libraries are separate systems. You need four variables working together:

VariableWhat it controlsAffects
CLOUDSDK_CONFIGFull gcloud state directorygcloud, bq, gsutil
CLOUDSDK_CORE_PROJECTDefault project for CLI commandsgcloud, bq, gsutil
GOOGLE_CLOUD_PROJECTDefault project for client librariesPython, dbt, Terraform
GOOGLE_APPLICATION_CREDENTIALSPath to credential file for ADCPython, dbt, Terraform

Why two project variables? CLOUDSDK_CORE_PROJECT only affects the gcloud CLI and its companions. GOOGLE_CLOUD_PROJECT only affects client libraries. They’re independent systems. Set only one and you’ll have gcloud targeting the right project while dbt targets the wrong one, or vice versa. See GCP Application Default Credentials for more on why these two auth systems exist separately.

Setting Up a New Client

For each client project, create a dedicated gcloud state directory and activate credentials into it:

Terminal window
# Create isolated config directory
mkdir -p ~/.config/gcloud-newclient
# Activate service account credentials into that directory only
CLOUDSDK_CONFIG=~/.config/gcloud-newclient \
gcloud auth activate-service-account \
--key-file=~/.gcp-keys/newclient-sa.json
# Verify it worked
CLOUDSDK_CONFIG=~/.config/gcloud-newclient \
gcloud config list

The inline CLOUDSDK_CONFIG= prefix activates the variable for that single command without exporting it to your whole shell session. Useful when setting up credentials without loading an .envrc.

One Caveat

The gke-gcloud-auth-plugin does not respect CLOUDSDK_CONFIG. If you do Kubernetes work, GKE authentication breaks the isolation pattern because the plugin always reads from the global ~/.config/gcloud/. For analytics engineering workflows that don’t touch Kubernetes, this isn’t relevant. But if your consulting work spans GKE clusters, be aware that you need a separate strategy for Kubernetes auth.

Relationship to Named Configurations

Google’s documentation covers named configurations (gcloud config configurations create) as the primary multi-project mechanism, but named configurations still share the same credentials store. Switching configurations changes the active project but does not isolate credentials.db or the ADC file.

CLOUDSDK_CONFIG provides deeper isolation that named configurations cannot. It is commonly used in CI/CD contexts and applies equally to consulting and agency workflows.

The direnv Multi-Client GCP Setup note covers automating this with direnv so the variables are set automatically per client directory.