Skip to content

Migration Guide

Complete guide for migrating secrets and configuration between providers using the AnySecret CLI with zero downtime.

🎯 The AnySecret Migration Advantage

Your applications never change. Whether migrating from AWS to GCP, adding multi-cloud support, or moving from .env files to production - the same CLI commands work everywhere.

The migration changes where your secrets are stored, not how your applications use them:

# Same commands work everywhere:
anysecret get DATABASE_PASSWORD    # Works with any provider
anysecret bulk export --output .env # Works with any provider
anysecret list --format json        # Works with any provider

AnySecret handles provider differences through: - Profile management - Switch providers with one command
- Auto-classification - Optimal storage routing - Universal export - Same .env output regardless of provider - Backup/restore - Easy rollback if needed

📋 Migration Scenarios

Common Migration Paths

From → To Use Case Complexity Downtime
Local Files → Cloud Dev to production Low None
AWS → GCP Cloud provider switch Medium None
Single → Multi-Cloud Redundancy/DR High None
Legacy → AnySecret Tool modernization Medium Minimal

🚀 Quick Migration: .env to Cloud

Scenario: Local Development to GCP Production

Most common migration - moving from .env files to cloud providers.

Current State (.env file)

# .env
DATABASE_PASSWORD=dev_password_123
STRIPE_SECRET_KEY=sk_test_abc123  
JWT_SECRET=jwt_dev_secret
DATABASE_HOST=localhost
API_TIMEOUT=30
LOG_LEVEL=debug

Step 1: Create AnySecret Profile

# Import current .env to local profile
anysecret config profile-create local-dev
anysecret bulk import .env

# Verify import
anysecret list
# DATABASE_PASSWORD (secret) ***
# STRIPE_SECRET_KEY (secret) ***
# JWT_SECRET (secret) ***
# DATABASE_HOST (parameter) localhost
# API_TIMEOUT (parameter) 30
# LOG_LEVEL (parameter) debug

Step 2: Create Cloud Profile

# Create production profile
anysecret config profile-create production --provider gcp

# Switch to production profile
anysecret config profile-use production

# Import configuration (auto-routes to optimal storage)
anysecret bulk import .env
# Secrets → GCP Secret Manager (~$0.40/month each)
# Parameters → GCS Storage (~$0.01/month each)

Step 3: Verify Migration

# Test the migration
anysecret list --format json | jq '.summary'
# {"total": 6, "secrets": 3, "parameters": 3}

anysecret get DATABASE_HOST
# localhost (same value, different storage)

# Export to verify same output format
anysecret bulk export --output .env.new
diff .env .env.new
# Should be identical

Step 4: Deploy with New Profile

# Export profile for CI/CD
anysecret config profile-export production --base64 > prod-profile.txt

# In CI/CD pipeline:
export ANYSECRET_PROFILE_DATA="$(cat prod-profile.txt)"
anysecret bulk export --output .env.production
docker run --env-file .env.production myapp

Result: Same application code, 40x cost savings, secure cloud storage.


🔄 Cloud-to-Cloud Migration

Scenario: AWS to GCP Migration

Enterprise scenario - moving from AWS to GCP while maintaining redundancy.

Step 1: Export from AWS

# Current AWS profile
anysecret config profile-use aws-prod

# Export everything as backup
anysecret bulk export --format json --output aws-backup.json
anysecret bulk export --output aws-backup.env

# Verify export
wc -l aws-backup.json
# 150 lines (75 config items)

Step 2: Create GCP Profile

# Create new GCP profile
anysecret config profile-create gcp-prod --provider gcp
anysecret config profile-use gcp-prod

# Import from AWS backup (dry run first)
anysecret bulk import aws-backup.json --format json --dry-run
# Shows: 25 → secrets, 50 → parameters

# Execute import
anysecret bulk import aws-backup.json --format json

Step 3: Verify Data Integrity

# Compare configurations
anysecret config profile-use aws-prod
anysecret list --format json > aws-config.json

anysecret config profile-use gcp-prod  
anysecret list --format json > gcp-config.json

# Compare counts and keys
jq '.summary' aws-config.json gcp-config.json
jq -r '.items[].key' aws-config.json | sort > aws-keys.txt
jq -r '.items[].key' gcp-config.json | sort > gcp-keys.txt
diff aws-keys.txt gcp-keys.txt
# Should show no differences

Step 4: Gradual Cutover

# Phase 1: Test with staging environment
anysecret config profile-export gcp-prod --base64 > gcp-staging-profile.txt

# Phase 2: Blue-green deployment
# Old: AWS profile in production
# New: GCP profile in staging → validate → promote

# Phase 3: Full cutover
anysecret config profile-export gcp-prod --base64 > gcp-prod-profile.txt
# Update all CI/CD systems with new profile

Step 5: Cleanup (After Validation)

# Keep AWS as backup for rollback period
# After 30 days of stable operation:
anysecret config profile-use aws-prod
anysecret bulk export --format json --output final-aws-backup.json
# Store backup, then clean up AWS resources

🏗️ Multi-Cloud Setup

Scenario: Primary + Fallback Architecture

Enterprise resilience - primary provider with automatic fallback.

Design Pattern

# Primary: GCP (main operations)
# Fallback: AWS (disaster recovery)
# Local: Emergency backup

Implementation

# Create primary profile
anysecret config profile-create primary --provider gcp
anysecret config profile-use primary

# Import production configuration
anysecret bulk import production.env

# Create fallback profile  
anysecret config profile-create fallback --provider aws
anysecret config profile-use fallback

# Sync from primary to fallback
anysecret config profile-use primary
anysecret bulk export --format json --output sync.json

anysecret config profile-use fallback
anysecret bulk import sync.json --format json

Operational Scripts

# sync-profiles.sh - Run daily
#!/bin/bash
echo "Syncing primary → fallback"
anysecret config profile-use primary
anysecret bulk export --format json --output /tmp/sync.json

anysecret config profile-use fallback  
anysecret bulk import /tmp/sync.json --format json

echo "Sync complete: $(date)"
rm /tmp/sync.json

Disaster Recovery

# If primary fails, switch to fallback
export ANYSECRET_PROFILE_DATA="$FALLBACK_PROFILE_DATA"

# Same commands, different provider
anysecret bulk export --output .env.recovery
docker run --env-file .env.recovery myapp

📊 Migration Best Practices

Pre-Migration Checklist

# 1. Inventory current configuration
anysecret list --format json > pre-migration-inventory.json

# 2. Test classification rules
anysecret bulk import .env --dry-run

# 3. Backup everything
anysecret bulk export --format json --output full-backup.json
anysecret bulk export --output full-backup.env

# 4. Verify provider access
anysecret providers health

During Migration

# 1. Use dry-run first
anysecret bulk import config.json --format json --dry-run

# 2. Import in batches for large configs
split -l 20 large-config.json batch-
for file in batch-*; do
  anysecret bulk import "$file" --format json
  sleep 1  # Rate limiting
done

# 3. Verify each step
anysecret list --format json | jq '.summary'

Post-Migration Validation

# 1. Compare counts
echo "Expected: $(jq -r '.summary.total' pre-migration-inventory.json)"  
echo "Actual: $(anysecret list --format json | jq -r '.summary.total')"

# 2. Test application integration
anysecret bulk export --output .env.test
docker run --env-file .env.test myapp ./test-suite.sh

# 3. Performance baseline
time anysecret bulk export --output /dev/null
# Should be < 2 seconds for 100 items

🔧 Migration Tools & Scripts

Bulk Migration Script

#!/bin/bash
# migrate-provider.sh

set -e

SOURCE_PROFILE="$1"
TARGET_PROFILE="$2"
BACKUP_DIR="./migration-backup-$(date +%Y%m%d)"

if [[ -z "$SOURCE_PROFILE" || -z "$TARGET_PROFILE" ]]; then
  echo "Usage: $0 <source-profile> <target-profile>"
  exit 1
fi

echo "🚀 Starting migration: $SOURCE_PROFILE$TARGET_PROFILE"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Step 1: Export from source
echo "📤 Exporting from $SOURCE_PROFILE..."
anysecret config profile-use "$SOURCE_PROFILE"
anysecret bulk export --format json --output "$BACKUP_DIR/source-backup.json"
anysecret bulk export --output "$BACKUP_DIR/source-backup.env"

# Step 2: Import to target (dry-run first)
echo "🔍 Testing import to $TARGET_PROFILE..."
anysecret config profile-use "$TARGET_PROFILE"
anysecret bulk import "$BACKUP_DIR/source-backup.json" --format json --dry-run

echo "📥 Importing to $TARGET_PROFILE..."
anysecret bulk import "$BACKUP_DIR/source-backup.json" --format json

# Step 3: Verify
echo "✅ Verifying migration..."
anysecret list --format json > "$BACKUP_DIR/target-result.json"

SOURCE_COUNT=$(jq -r '.summary.total' "$BACKUP_DIR/source-backup.json")
TARGET_COUNT=$(jq -r '.summary.total' "$BACKUP_DIR/target-result.json")

if [[ "$SOURCE_COUNT" == "$TARGET_COUNT" ]]; then
  echo "✅ Migration successful: $SOURCE_COUNT items transferred"
  echo "📁 Backups saved to: $BACKUP_DIR"
else
  echo "❌ Migration failed: $SOURCE_COUNT$TARGET_COUNT"
  exit 1
fi

Rollback Script

#!/bin/bash  
# rollback-migration.sh

BACKUP_FILE="$1"
TARGET_PROFILE="$2"

if [[ -z "$BACKUP_FILE" || -z "$TARGET_PROFILE" ]]; then
  echo "Usage: $0 <backup-file> <target-profile>"
  exit 1
fi

echo "🔄 Rolling back to $TARGET_PROFILE from $BACKUP_FILE"

anysecret config profile-use "$TARGET_PROFILE"
anysecret bulk import "$BACKUP_FILE" --format json

echo "✅ Rollback complete"

🚨 Troubleshooting

Common Migration Issues

Import Failures

# Check file format
file config.json
anysecret bulk import config.json --format json --dry-run

# Fix JSON formatting
jq '.' config.json > config-fixed.json
anysecret bulk import config-fixed.json --format json

Provider Authentication

# Check provider access
anysecret providers health

# Re-authenticate
# For GCP:
gcloud auth application-default login

# For AWS:
aws configure

Classification Issues

# Check how keys are being classified
anysecret classify DATABASE_PASSWORD
anysecret classify API_TIMEOUT

# Override if needed
anysecret set LOG_TOKEN "value" --hint secret
anysecret set PUBLIC_KEY "value" --hint parameter

Performance Issues

# Large migrations - use batching
split -l 50 large-config.json chunk-
for chunk in chunk-*; do
  anysecret bulk import "$chunk" --format json
  sleep 2  # Rate limiting
done

🎓 Migration Success Stories

Startup: $0 → $200/month savings

  • Before: 50 config values × $0.40 = $20/month
  • After: 10 secrets × $0.40 + 40 parameters × $0.01 = $4.40/month
  • Savings: $15.60/month (78% reduction)

Scale-up: Multi-cloud resilience

  • Challenge: AWS vendor lock-in concerns
  • Solution: Primary GCP, fallback AWS using AnySecret profiles
  • Result: 99.99% uptime, easy provider switching

Enterprise: Compliance migration

  • Challenge: Move from HashiCorp Vault to cloud-native
  • Solution: Gradual migration with AnySecret classification
  • Result: 60% cost reduction, improved compliance posture

📚 Next Steps

After migration: - Best Practices - Optimize your new setup - CLI Reference - Master advanced commands - Examples - Learn from real-world patterns

Need help? Check the Provider Setup guide for cloud-specific configuration.


Migration with AnySecret: Change where you store secrets, not how you use them.