Deployment Guide

This guide covers best practices for deploying Mushu across multiple environments (staging, production) with proper secrets management and CI/CD integration.

Environment Strategy

We recommend one organization with separate apps per environment. API keys are scoped to apps, so this gives you isolated credentials for each environment.

# Create your organization (once)
mushu org create "My Company"

# Create an app for each environment
mushu app create "My App - Staging" --bundle-id com.mycompany.myapp.staging --org ORG_ID
mushu app create "My App - Production" --bundle-id com.mycompany.myapp --org ORG_ID

This approach gives you:

  • Isolated API keys per environment
  • Separate usage tracking and analytics
  • No risk of staging code hitting production data
  • Ability to test key rotation in staging first

API Key Management

Creating Keys

Create separate API keys for each environment and service:

# Staging keys
mushu api-key create "staging-backend" --app APP_ID_STAGING --scope write
mushu api-key create "staging-ci" --app APP_ID_STAGING --scope read

# Production keys
mushu api-key create "production-backend" --app APP_ID_PROD --scope write
mushu api-key create "production-ci" --app APP_ID_PROD --scope read

Important: The full API key is only shown once when created. Save it immediately to your secrets manager.

Key Scopes

ScopePermissionsUse Case
readRead-only accessAnalytics, monitoring, CI checks
writeRead + writeBackend services, API calls
adminFull accessInfrastructure, key management

Storing Secrets

Never commit API keys to your repository. Use your platform's secrets management.

Environment Variables

The simplest approach for local development and basic deployments:

# .env.staging (never commit this file)
MUSHU_API_KEY=msk_live_staging_xxx

# .env.production
MUSHU_API_KEY=msk_live_production_xxx

AWS Secrets Manager

# Store the key
aws secretsmanager create-secret \
  --name myapp/staging/mushu-api-key \
  --secret-string "msk_live_xxx"

# Retrieve in your app
import boto3
client = boto3.client('secretsmanager')
secret = client.get_secret_value(SecretId='myapp/staging/mushu-api-key')
api_key = secret['SecretString']

GCP Secret Manager

# Store the key
echo -n "msk_live_xxx" | gcloud secrets create mushu-api-key-staging --data-file=-

# Retrieve in your app
from google.cloud import secretmanager
client = secretmanager.SecretManagerServiceClient()
response = client.access_secret_version(name="projects/PROJECT/secrets/mushu-api-key-staging/versions/latest")
api_key = response.payload.data.decode("UTF-8")

HashiCorp Vault

# Store the key
vault kv put secret/myapp/staging mushu_api_key="msk_live_xxx"

# Retrieve in your app (using hvac)
import hvac
client = hvac.Client()
secret = client.secrets.kv.v2.read_secret_version(path='myapp/staging')
api_key = secret['data']['data']['mushu_api_key']

CI/CD Integration

GitHub Actions

Store your API key in repository secrets, then use it in workflows:

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main, staging]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to staging
        if: github.ref == 'refs/heads/staging'
        env:
          MUSHU_API_KEY: ${{ secrets.MUSHU_API_KEY_STAGING }}
        run: ./deploy.sh staging

      - name: Deploy to production
        if: github.ref == 'refs/heads/main'
        env:
          MUSHU_API_KEY: ${{ secrets.MUSHU_API_KEY_PRODUCTION }}
        run: ./deploy.sh production

GitLab CI

# .gitlab-ci.yml
deploy:staging:
  stage: deploy
  environment: staging
  variables:
    MUSHU_API_KEY: $MUSHU_API_KEY_STAGING
  script:
    - ./deploy.sh staging
  only:
    - staging

deploy:production:
  stage: deploy
  environment: production
  variables:
    MUSHU_API_KEY: $MUSHU_API_KEY_PRODUCTION
  script:
    - ./deploy.sh production
  only:
    - main

Key Rotation

Rotate keys periodically without downtime using this process:

  1. Create new key: mushu api-key create "backend-v2" --app APP_ID
  2. Deploy with new key: Update your secrets and deploy
  3. Verify: Confirm the new key is working
  4. Revoke old key: mushu api-key delete OLD_KEY_ID --app APP_ID

Tip: Test key rotation in staging before doing it in production. This catches any hardcoded keys or caching issues.

Production Checklist

Before going live, verify:

  • Separate apps for staging and production
  • API keys stored in secrets manager (not env files)
  • Keys use appropriate scopes (not all admin)
  • CI/CD uses environment-specific secrets
  • Key rotation process tested in staging
  • Monitoring/alerts set up for API errors

Next Steps