Engineering Originally on dev.to

Stop Putting Secrets in .env Files: A Practical Guide to GCP Secret Manager

How we switched from .env files to GCP Secret Manager in 15 minutes and why it's worth it for every project.

P
Pablo Inigo · Founder & Engineer
2 min read
Secure vault with key contrasted with crossed-out env file

Your .env file has your database password, API keys, and AWS credentials. It’s committed to git (or worse, deployed via scp). Here’s how we switched to GCP Secret Manager in a Node.js app — and why it’s worth the 15 minutes of setup.

The Problem With .env

  • PM2 caches env vars in memory. Changing .env does nothing until you restart.
  • Secrets in git history. Even if you .gitignore it, one accidental commit and it’s in history forever.
  • No audit trail. Who changed the API key? When? No way to know.
  • No versioning. Rotated a key? Hope you remembered the old one.

The Setup (15 Minutes)

1. Create secrets in GCP

echo -n "your-database-url" | gcloud secrets create DATABASE_URL --data-file=-
echo -n "your-api-key" | gcloud secrets create API_KEY --data-file=-

2. Load at startup

// SecretsService.ts
const MANAGED_SECRETS = [
  'DATABASE_URL',
  'REDIS_URL',
  'AWS_ACCESS_KEY_ID',
  'AWS_SECRET_ACCESS_KEY',
  'STRIPE_SECRET_KEY',
  // ... 16 secrets total
];

export class SecretsService {
  static async preloadSecrets(): Promise<void> {
    const client = new SecretManagerServiceClient();

    for (const name of MANAGED_SECRETS) {
      const [version] = await client.accessSecretVersion({
        name: `projects/my-project/secrets/${name}/versions/latest`
      });
      process.env[name] = version.payload.data.toString();
    }
  }
}

3. Call before anything else

// bootstrap.ts
await SecretsService.preloadSecrets();
// Now process.env has all secrets
// Start Express, connect to DB, etc.

What You Get

  • Versioning. Every secret change creates a new version. Roll back anytime.
  • Audit trail. GCP logs every access.
  • No .env in production. Secrets live in GCP, not on disk.
  • Rotation without restart. Update the secret, restart PM2, done.

Cost

GCP Secret Manager: $0.06 per 10,000 access operations. With 16 secrets loaded once at startup, it’s essentially free.

This runs at MisuJob, managing 16 production secrets for database, AWS SES, Stripe, and more.


How do you manage secrets in production? Vault? AWS SSM? .env? Let me know.

Security DevOps Google Cloud Platform Node.js
Share
P
Pablo Inigo

Founder & Engineer

Building MisuJob — an AI-powered job matching platform processing 1M+ tech job listings daily.

Engineering updates

Technical deep dives delivered to your inbox.

Find your next role with AI

Upload your CV. Get matched to 50,000+ jobs. Auto-apply to the best fits.

Get Started Free

User

Dashboard Profile Subscription