oraclecloud-multi-env-setup

Configure multi-environment OCI workflows with config profiles and compartment-per-environment patterns. Use when setting up dev/staging/prod separation, switching between OCI profiles, or preventing accidental production deployments. Trigger with "oraclecloud multi env setup", "oci profiles", "oci environments", "oci config profiles".

1,868 stars

Best use case

oraclecloud-multi-env-setup is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Configure multi-environment OCI workflows with config profiles and compartment-per-environment patterns. Use when setting up dev/staging/prod separation, switching between OCI profiles, or preventing accidental production deployments. Trigger with "oraclecloud multi env setup", "oci profiles", "oci environments", "oci config profiles".

Teams using oraclecloud-multi-env-setup should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/oraclecloud-multi-env-setup/SKILL.md --create-dirs "https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/main/plugins/saas-packs/oraclecloud-pack/skills/oraclecloud-multi-env-setup/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/oraclecloud-multi-env-setup/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How oraclecloud-multi-env-setup Compares

Feature / Agentoraclecloud-multi-env-setupStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Configure multi-environment OCI workflows with config profiles and compartment-per-environment patterns. Use when setting up dev/staging/prod separation, switching between OCI profiles, or preventing accidental production deployments. Trigger with "oraclecloud multi env setup", "oci profiles", "oci environments", "oci config profiles".

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Oracle Cloud Multi-Environment Setup

## Overview

OCI has no "accounts" like AWS — you use compartments plus OCI config profiles for dev/staging/prod separation. But profile switching is manual, compartment OCIDs are easy to confuse, and one wrong `--compartment-id` deploys to production. This skill sets up safe multi-environment workflows with named profiles, compartment aliasing, environment validation, and deployment guardrails.

**Purpose:** Configure safe, repeatable multi-environment OCI workflows that prevent accidental cross-environment operations.

## Prerequisites

- **OCI Python SDK** — `pip install oci`
- **OCI CLI** — installed and configured (`oci setup config`)
- **Separate API keys per environment** (recommended) or a single key with cross-compartment policies
- **Compartment OCIDs** for each environment (dev, staging, prod)
- Python 3.8+

## Instructions

### Step 1: Configure Multi-Profile ~/.oci/config

The OCI config file supports named profiles. Each profile can point to different tenancies, regions, or use different API keys:

```ini
# ~/.oci/config

[DEFAULT]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99
tenancy=ocid1.tenancy.oc1..exampleuniqueID
region=us-ashburn-1
key_file=~/.oci/oci_api_key.pem

[DEV]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99
tenancy=ocid1.tenancy.oc1..exampleuniqueID
region=us-ashburn-1
key_file=~/.oci/oci_api_key_dev.pem

[STAGING]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00
tenancy=ocid1.tenancy.oc1..exampleuniqueID
region=us-phoenix-1
key_file=~/.oci/oci_api_key_staging.pem

[PROD]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=ff:ee:dd:cc:bb:aa:00:99:88:77:66:55:44:33:22:11
tenancy=ocid1.tenancy.oc1..exampleuniqueID
region=us-ashburn-1
key_file=~/.oci/oci_api_key_prod.pem
```

**Best practice:** Use different API key pairs per environment. If the dev key is compromised, prod is unaffected.

### Step 2: Create an Environment Configuration Module

Centralize compartment OCIDs and profile mappings to prevent OCID confusion:

```python
import oci
import os

# Environment configuration — single source of truth for OCIDs
ENVIRONMENTS = {
    "dev": {
        "profile": "DEV",
        "compartment_id": "ocid1.compartment.oc1..dev_example",
        "region": "us-ashburn-1",
        "allow_destructive": True,
    },
    "staging": {
        "profile": "STAGING",
        "compartment_id": "ocid1.compartment.oc1..staging_example",
        "region": "us-phoenix-1",
        "allow_destructive": True,
    },
    "prod": {
        "profile": "PROD",
        "compartment_id": "ocid1.compartment.oc1..prod_example",
        "region": "us-ashburn-1",
        "allow_destructive": False,  # Safety: block destructive ops
    },
}

def get_oci_config(env_name):
    """Load OCI config for the specified environment.

    Validates the environment name and returns a configured
    OCI config dict ready for client construction.
    """
    if env_name not in ENVIRONMENTS:
        raise ValueError(
            f"Unknown environment: {env_name}. "
            f"Valid: {list(ENVIRONMENTS.keys())}"
        )

    env = ENVIRONMENTS[env_name]
    config = oci.config.from_file("~/.oci/config", profile_name=env["profile"])
    oci.config.validate_config(config)
    return config, env

def get_compartment_id(env_name):
    """Get the compartment OCID for an environment."""
    return ENVIRONMENTS[env_name]["compartment_id"]

def is_destructive_allowed(env_name):
    """Check if destructive operations are allowed in this environment."""
    return ENVIRONMENTS[env_name]["allow_destructive"]
```

### Step 3: Build Safe Environment-Aware Clients

Wrap OCI clients with environment validation to prevent cross-environment mistakes:

```python
import oci
import sys

class OCIEnvironment:
    """Environment-aware OCI client factory with safety guardrails."""

    def __init__(self, env_name):
        self.env_name = env_name
        self.config, self.env = get_oci_config(env_name)
        self.compartment_id = self.env["compartment_id"]

        # Verify we can authenticate
        identity = oci.identity.IdentityClient(self.config)
        user = identity.get_user(self.config["user"]).data
        print(f"[{env_name.upper()}] Authenticated as {user.name} "
              f"in {self.config['region']}")

    def compute(self):
        return oci.core.ComputeClient(self.config)

    def network(self):
        return oci.core.VirtualNetworkClient(self.config)

    def storage(self):
        return oci.object_storage.ObjectStorageClient(self.config)

    def database(self):
        return oci.database.DatabaseClient(self.config)

    def safe_delete(self, operation, resource_name):
        """Execute a delete operation with environment safety checks."""
        if not is_destructive_allowed(self.env_name):
            print(f"BLOCKED: Destructive operation on {resource_name} "
                  f"not allowed in {self.env_name.upper()}")
            print("Set allow_destructive=True in ENVIRONMENTS to override")
            sys.exit(1)

        print(f"WARNING: Deleting {resource_name} in {self.env_name.upper()}")
        return operation()

# Usage
dev = OCIEnvironment("dev")
instances = dev.compute().list_instances(compartment_id=dev.compartment_id).data
print(f"Dev instances: {len(instances)}")

prod = OCIEnvironment("prod")
# prod.safe_delete(...) would be blocked by allow_destructive=False
```

### Step 4: CLI Profile Switching

Use profiles with the OCI CLI to target specific environments:

```bash
# List instances in dev
oci compute instance list --compartment-id ocid1.compartment.oc1..dev_example --profile DEV

# List instances in prod (read-only)
oci compute instance list --compartment-id ocid1.compartment.oc1..prod_example --profile PROD

# Set default profile via environment variable
export OCI_CLI_PROFILE=DEV

# Override per-command
OCI_CLI_PROFILE=PROD oci compute instance list --compartment-id ocid1.compartment.oc1..prod_example
```

**Shell aliases for safety:**

```bash
# Add to ~/.bashrc or ~/.zshrc
alias oci-dev='OCI_CLI_PROFILE=DEV oci'
alias oci-staging='OCI_CLI_PROFILE=STAGING oci'
alias oci-prod='OCI_CLI_PROFILE=PROD oci'

# Usage
oci-dev compute instance list --compartment-id ocid1.compartment.oc1..dev_example
oci-prod compute instance list --compartment-id ocid1.compartment.oc1..prod_example
```

### Step 5: Validate Config Before Operations

Always validate the config file and profile before running automation:

```python
import oci

def validate_all_profiles():
    """Validate all OCI config profiles are properly configured."""
    profiles = ["DEFAULT", "DEV", "STAGING", "PROD"]
    results = {}

    for profile in profiles:
        try:
            config = oci.config.from_file("~/.oci/config", profile_name=profile)
            oci.config.validate_config(config)

            # Test authentication
            identity = oci.identity.IdentityClient(config)
            user = identity.get_user(config["user"]).data
            results[profile] = f"OK — {user.name} in {config['region']}"
        except oci.exceptions.ConfigFileNotFound:
            results[profile] = "FAIL — config file not found"
        except oci.exceptions.ProfileNotFound:
            results[profile] = "FAIL — profile not found in config"
        except oci.exceptions.ServiceError as e:
            results[profile] = f"FAIL — {e.status}: {e.code}"
        except Exception as e:
            results[profile] = f"FAIL — {str(e)}"

    print("OCI Profile Validation:")
    for profile, status in results.items():
        print(f"  [{profile}] {status}")

    return all("OK" in s for s in results.values())

validate_all_profiles()
```

### Step 6: Environment Variables for CI/CD

For CI/CD pipelines where config files are impractical, use environment variables:

```bash
# Set OCI config via environment variables (CI/CD pipelines)
export OCI_CLI_USER="ocid1.user.oc1..exampleuniqueID"
export OCI_CLI_FINGERPRINT="aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99"
export OCI_CLI_TENANCY="ocid1.tenancy.oc1..exampleuniqueID"
export OCI_CLI_REGION="us-ashburn-1"
export OCI_CLI_KEY_FILE="/path/to/key.pem"
# Or use key content directly:
export OCI_CLI_KEY_CONTENT="-----BEGIN RSA PRIVATE KEY-----\n..."
```

```python
import oci

# Python SDK reads from environment when no config file exists
config = oci.config.from_file()  # Falls back to env vars if ~/.oci/config missing

# Or construct config dict directly for CI/CD
config = {
    "user": os.environ["OCI_CLI_USER"],
    "fingerprint": os.environ["OCI_CLI_FINGERPRINT"],
    "tenancy": os.environ["OCI_CLI_TENANCY"],
    "region": os.environ["OCI_CLI_REGION"],
    "key_file": os.environ["OCI_CLI_KEY_FILE"],
}
oci.config.validate_config(config)
```

## Output

Successful completion produces:
- A `~/.oci/config` file with named profiles for each environment (DEV, STAGING, PROD)
- An environment configuration module mapping profiles to compartment OCIDs
- An environment-aware client factory with safety guardrails blocking destructive prod operations
- Shell aliases for safe CLI profile switching
- Validated authentication for all profiles

## Error Handling

| Error | Code | Cause | Solution |
|-------|------|-------|----------|
| ProfileNotFound | — | Wrong profile name in `from_file()` | Check `~/.oci/config` profile names match exactly (case-sensitive) |
| ConfigFileNotFound | — | Missing `~/.oci/config` | Run `oci setup config` or create the file manually |
| NotAuthenticated | 401 | Wrong key for the selected profile | Verify key_file path and fingerprint match the uploaded public key |
| NotAuthorizedOrNotFound | 404 | Profile's user lacks access to target compartment | Add IAM policies for the user/group in the target compartment |
| TooManyRequests | 429 | Rate limited | Back off; see `oraclecloud-rate-limits` |
| InternalError | 500 | OCI service error | Retry after 30s; check https://ocistatus.oraclecloud.com |

**Critical mistake:** Using the DEFAULT profile's compartment OCID with the PROD profile's credentials (or vice versa). The environment config module in Step 2 prevents this by coupling profile names to compartment OCIDs.

## Examples

**Quick profile test from the command line:**

```bash
# Test all profiles in one shot
for profile in DEFAULT DEV STAGING PROD; do
  echo -n "[$profile] "
  oci iam user get --user-id "$(oci iam user list --profile "$profile" --query 'data[0].id' --raw-output 2>/dev/null)" --profile "$profile" --query 'data.name' --raw-output 2>/dev/null || echo "FAILED"
done
```

**Check which profile is active:**

```python
import oci
import os

profile = os.environ.get("OCI_CLI_PROFILE", "DEFAULT")
config = oci.config.from_file("~/.oci/config", profile_name=profile)
print(f"Active profile: {profile}")
print(f"Region: {config['region']}")
print(f"Tenancy: {config['tenancy']}")
```

## Resources

- [OCI Config File](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm) — config file format and profile syntax
- [CLI Environment Variables](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/clienvironmentvariables.htm) — OCI_CLI_* variables
- [CLI Reference](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm) — command-line interface guide
- [Python SDK Reference](https://docs.oracle.com/en-us/iaas/tools/python/latest/) — config loading and client construction
- [Compartment Management](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingcompartments.htm) — organizing resources by environment

## Next Steps

After environments are configured, see `oraclecloud-enterprise-rbac` for compartment hierarchy design with least-privilege policies, or `oraclecloud-deploy-integration` for CI/CD pipeline integration.

Related Skills

windsurf-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Windsurf IDE and Cascade AI across team members and project environments. Use when onboarding teams to Windsurf, setting up per-project Cascade configuration, or managing Windsurf settings across development, staging, and production contexts. Trigger with phrases like "windsurf team setup", "windsurf environments", "windsurf multi-project", "windsurf team config", "cascade rules per env".

webflow-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Webflow across development, staging, and production environments with per-environment API tokens, site IDs, and secret management via Vault/AWS/GCP. Trigger with phrases like "webflow environments", "webflow staging", "webflow dev prod", "webflow environment setup", "webflow config by env".

vercel-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Vercel across development, preview, and production environments with scoped secrets. Use when setting up per-environment configuration, managing environment-specific variables, or implementing environment isolation on Vercel. Trigger with phrases like "vercel environments", "vercel staging", "vercel dev prod", "vercel environment setup", "vercel env scoping".

veeva-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Veeva Vault multi env setup for enterprise operations. Use when implementing advanced Veeva Vault patterns. Trigger: "veeva multi env setup".

vastai-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Vast.ai GPU cloud across dev, staging, and production environments. Use when isolating GPU pools per team, managing API key separation by env, or implementing spending controls per deployment tier. Trigger with phrases like "vastai environments", "vastai staging", "vastai dev prod", "vastai multi-env".

supabase-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Supabase across development, staging, and production with separate projects, environment-specific secrets, and safe migration promotion. Use when setting up multi-environment deployments, isolating dev from prod data, configuring per-environment Supabase projects, or promoting migrations through environments. Trigger: "supabase environments", "supabase staging", "supabase dev prod", "supabase multi-project", "supabase env config", "database branching".

speak-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Speak across dev, staging, and production with separate API keys and mock modes. Use when implementing multi env setup, or managing Speak language learning platform operations. Trigger with phrases like "speak multi env setup", "speak multi env setup".

snowflake-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Snowflake across dev, staging, and production with account-level isolation, zero-copy clones, and environment-specific RBAC. Trigger with phrases like "snowflake environments", "snowflake staging", "snowflake dev prod", "snowflake clone", "snowflake environment setup".

windsurf-workspace-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Initialize Windsurf workspace with project-specific AI rules. Activate when users mention "create windsurfrules", "setup workspace", "configure project ai", "initialize windsurf workspace", or "migrate to windsurf". Handles workspace configuration and team standardization. Use when working with windsurf workspace setup functionality. Trigger with phrases like "windsurf workspace setup", "windsurf setup", "windsurf".

windsurf-multi-file-editing

1868
from jeremylongshore/claude-code-plugins-plus-skills

Manage multi-file edits with Cascade coordination. Activate when users mention "multi-file edit", "edit multiple files", "cross-file changes", "refactor across files", or "batch modifications". Handles coordinated multi-file operations. Use when working with windsurf multi file editing functionality. Trigger with phrases like "windsurf multi file editing", "windsurf editing", "windsurf".

shopify-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Shopify apps across development, staging, and production environments with separate stores, API credentials, and app instances. Trigger with phrases like "shopify environments", "shopify staging", "shopify dev vs prod", "shopify multi-store", "shopify environment setup".

salesforce-multi-env-setup

1868
from jeremylongshore/claude-code-plugins-plus-skills

Configure Salesforce across Developer, Sandbox, and Production environments with proper org management. Use when setting up multi-environment deployments, configuring per-environment credentials, or implementing sandbox-to-production promotion flows. Trigger with phrases like "salesforce environments", "salesforce sandbox", "salesforce dev prod", "salesforce org management", "salesforce sandbox types".