
Oracle Cloud
- 124 installs
- 14 repo stars
- Updated January 23, 2026
- dauquangthanh/hanoi-rainbow
For development and infrastructure management.
About
oracle-cloud is an AI coding tool that enhances development workflows. Builders use it for infrastructure, integration, and platform development within the catalog ecosystem.
- oracle-cloud
- Development
Oracle Cloud by the numbers
- 124 all-time installs (skills.sh)
- Ranked #2,790 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dauquangthanh/hanoi-rainbow --skill oracle-cloudAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 124 |
|---|---|
| repo stars | ★ 14 |
| Last updated | January 23, 2026 |
| Repository | dauquangthanh/hanoi-rainbow ↗ |
What it does
For development and infrastructure management.
Files
Oracle Cloud Infrastructure (OCI)
Core Capabilities
Provides expert guidance for Oracle Cloud Infrastructure across all major services:
1. Compute Services - VM instances, bare metal, autoscaling, instance pools 2. Networking - Virtual Cloud Networks (VCN), subnets, security lists, route tables, load balancers, VPN 3. Storage - Block volumes, object storage, file storage, archive storage 4. Database Services - Autonomous Database, MySQL, PostgreSQL, NoSQL, MongoDB 5. Container & Kubernetes - Oracle Kubernetes Engine (OKE), container instances, registries 6. Identity & Access Management - Users, groups, policies, federation, MFA 7. Infrastructure as Code - Terraform OCI provider, Resource Manager, stacks 8. Cost Management - Budgets, cost analysis, resource tagging, rightsizing
Best Practices
Compute
- Use flexible shapes for cost optimization
- Enable boot volume backups and configure lifecycle policies
- Use instance pools with autoscaling for dynamic workloads
- Implement proper tagging for resource management
- Leverage availability domains for high availability
Networking
- Design VCN with proper CIDR blocks (avoid overlaps)
- Use security lists and network security groups together
- Implement private subnets for databases and application tiers
- Enable DRG (Dynamic Routing Gateway) for hybrid connectivity
- Configure load balancer health checks with appropriate intervals
Storage
- Use block volumes with appropriate performance tiers
- Implement lifecycle policies for object storage cost savings
- Enable encryption at rest for all storage services
- Configure regular backups with retention policies
- Use file storage for shared application data
Database
- Use Autonomous Database for automatic management and tuning
- Enable automatic backups with point-in-time recovery
- Configure connection pooling and TLS encryption
- Implement proper IAM policies for database access
- Monitor database metrics and set up alerts
Container Orchestration
- Use managed OKE for Kubernetes workloads
- Enable cluster autoscaling and pod autoscaling
- Implement pod security policies and network policies
- Use OCI Container Registry for private image storage
- Configure proper resource requests and limits
IAM & Security
- Follow principle of least privilege for policies
- Enable MFA for all users with admin access
- Use service-level resources for automation
- Implement compartment hierarchy for resource isolation
- Audit IAM policy changes regularly
Infrastructure as Code
- Use Terraform OCI provider with remote state
- Organize resources by compartment and environment
- Version control all infrastructure code
- Use Resource Manager for managed Terraform execution
- Implement proper variable management and secrets handling
Cost Optimization
- Use flexible shapes to match workload requirements
- Implement autoscaling to scale down during off-peak
- Use preemptible instances for fault-tolerant workloads
- Set up budgets and cost alerts
- Tag resources for cost allocation and tracking
Detailed References
Load reference files based on specific needs:
- Compute Services: See compute-services.md for:
- VM shapes and bare metal configuration
- Instance pools and autoscaling setup
- Boot volume management and backups
- Custom images and cloud-init configuration
- Networking Architecture: See networking-architecture.md for:
- VCN design patterns and CIDR planning
- Security lists and network security groups
- Load balancer configuration (public, private)
- FastConnect and VPN setup for hybrid connectivity
- VCN peering and DNS configuration
- Database Services: See database-services.md for:
- Autonomous Database provisioning and management
- MySQL, PostgreSQL, and NoSQL configuration
- Database backup and recovery procedures
- Connection pooling and performance optimization
- Database migration strategies
- IAM Configuration: See iam-configuration.md for:
- User, group, and policy management
- Compartment design and hierarchy
- Dynamic groups and instance principals
- Federation and identity providers
- Tagging strategy and resource limits
- Terraform for OCI: See terraform-oci.md for:
- Terraform OCI provider configuration
- Common resource provisioning patterns
- Module structure and best practices
- Remote state management in object storage
- Three-tier architecture examples
- OCI CLI Commands: See oci-cli-commands.md for:
- OCI CLI installation and configuration
- Compute, networking, storage, and database commands
- Container registry and OKE operations
- Query and filtering techniques
- Troubleshooting and debugging
Compute Services
VM Instance Configuration
Instance Shapes
Flexible Shapes (VM.Standard.E4.Flex, VM.Optimized3.Flex):
- Configure custom OCPU and memory allocation
- Best for cost optimization and workload-specific sizing
- Memory-to-OCPU ratio: 1:1 to 64:1 GB per OCPU
Fixed Shapes (VM.Standard2.x, VM.Standard3.x):
- Pre-configured OCPU and memory
- Predictable pricing
- Use when workload requirements are well-defined
Bare Metal Shapes (BM.Standard.E4, BM.DenseIO):
- Dedicated physical server
- No hypervisor overhead
- Use for high-performance, latency-sensitive workloads
Instance Creation
# Using OCI CLI
oci compute instance launch \
--availability-domain "AD-1" \
--compartment-id "ocid1.compartment..." \
--shape "VM.Standard.E4.Flex" \
--shape-config '{"ocpus": 2, "memoryInGBs": 16}' \
--subnet-id "ocid1.subnet..." \
--image-id "ocid1.image..." \
--display-name "web-server-01" \
--assign-public-ip true \
--ssh-authorized-keys-file ~/.ssh/id_rsa.pubTerraform Example:
resource "oci_core_instance" "web_server" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
compartment_id = var.compartment_id
shape = "VM.Standard.E4.Flex"
shape_config {
ocpus = 2
memory_in_gbs = 16
}
create_vnic_details {
subnet_id = oci_core_subnet.public_subnet.id
assign_public_ip = true
}
source_details {
source_type = "image"
source_id = var.image_id
boot_volume_size_in_gbs = 100
}
metadata = {
ssh_authorized_keys = file("~/.ssh/id_rsa.pub")
user_data = base64encode(file("cloud-init.yaml"))
}
freeform_tags = {
Environment = "Production"
Application = "WebServer"
}
}Instance Pools and Autoscaling
Instance Configuration
Create reusable instance configuration:
resource "oci_core_instance_configuration" "app_config" {
compartment_id = var.compartment_id
display_name = "app-instance-config"
instance_details {
instance_type = "compute"
launch_details {
compartment_id = var.compartment_id
shape = "VM.Standard.E4.Flex"
shape_config {
ocpus = 2
memory_in_gbs = 16
}
create_vnic_details {
subnet_id = oci_core_subnet.private_subnet.id
}
source_details {
source_type = "image"
image_id = var.image_id
boot_volume_size_in_gbs = 50
}
}
}
}Instance Pool
resource "oci_core_instance_pool" "app_pool" {
compartment_id = var.compartment_id
instance_configuration_id = oci_core_instance_configuration.app_config.id
size = 2
display_name = "app-instance-pool"
placement_configurations {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
primary_subnet_id = oci_core_subnet.private_subnet.id
}
load_balancers {
backend_set_name = oci_load_balancer_backend_set.app_backend.name
load_balancer_id = oci_load_balancer.app_lb.id
port = 80
vnic_selection = "PrimaryVnic"
}
}Autoscaling Configuration
resource "oci_autoscaling_auto_scaling_configuration" "app_autoscaling" {
compartment_id = var.compartment_id
cool_down_in_seconds = 300
display_name = "app-autoscaling"
policies {
display_name = "cpu-based-autoscaling"
capacity {
initial = 2
max = 10
min = 2
}
policy_type = "threshold"
rules {
action {
type = "CHANGE_COUNT_BY"
value = 1
}
display_name = "scale-out-rule"
metric {
metric_type = "CPU_UTILIZATION"
threshold {
operator = "GT"
value = 75
}
}
}
rules {
action {
type = "CHANGE_COUNT_BY"
value = -1
}
display_name = "scale-in-rule"
metric {
metric_type = "CPU_UTILIZATION"
threshold {
operator = "LT"
value = 25
}
}
}
}
auto_scaling_resources {
id = oci_core_instance_pool.app_pool.id
type = "instancePool"
}
}Boot Volume Management
Boot Volume Backups
Automatic Backups:
resource "oci_core_volume_backup_policy" "daily_backup" {
compartment_id = var.compartment_id
display_name = "daily-boot-volume-backup"
schedules {
backup_type = "INCREMENTAL"
period = "ONE_DAY"
retention_seconds = 604800 # 7 days
time_zone = "UTC"
hour_of_day = 2
}
}
resource "oci_core_volume_backup_policy_assignment" "boot_volume_backup" {
asset_id = oci_core_instance.web_server.boot_volume_id
policy_id = oci_core_volume_backup_policy.daily_backup.id
}Custom Images
Create custom image from instance:
# Create custom image
oci compute image create \
--compartment-id "ocid1.compartment..." \
--instance-id "ocid1.instance..." \
--display-name "custom-web-server-image"
# Launch instance from custom image
oci compute instance launch \
--availability-domain "AD-1" \
--compartment-id "ocid1.compartment..." \
--shape "VM.Standard.E4.Flex" \
--image-id "ocid1.image.custom..."Cloud-Init Configuration
Basic Cloud-Init
#cloud-config
package_update: true
package_upgrade: true
packages:
- nginx
- docker
- git
runcmd:
- systemctl enable nginx
- systemctl start nginx
- usermod -aG docker opc
- echo "Hello from OCI instance" > /var/www/html/index.html
write_files:
- path: /etc/nginx/conf.d/app.conf
content: |
server {
listen 80;
server_name _;
location / {
root /var/www/html;
index index.html;
}
}Advanced Configuration
#cloud-config
bootcmd:
- echo "Boot command executed"
package_update: true
package_upgrade: true
packages:
- docker
- docker-compose
groups:
- docker
users:
- default
- name: appuser
groups: docker
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
runcmd:
- systemctl enable docker
- systemctl start docker
- docker pull nginx:latest
- docker run -d -p 80:80 --name web nginx
final_message: "System setup completed in $UPTIME seconds"Instance Metadata Service
Retrieve Instance Metadata
# Get instance ID
curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/id
# Get availability domain
curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/availabilityDomain
# Get region
curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/region
# Get all metadata
curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/Performance Optimization
Compute Performance Best Practices
1. Use Latest Shapes: E4/E5 shapes offer better price-performance 2. Enable Burstable Instances: For variable workloads 3. Optimize OCPU/Memory Ratio: Match workload requirements 4. Use Ultra High Performance Block Volumes: For I/O intensive applications 5. Enable TRIM on Boot Volumes: Improve SSD performance over time
Monitoring Key Metrics
- CPU Utilization: Target < 80% for sustained workloads
- Memory Usage: Monitor for memory pressure
- Network Throughput: Ensure within shape limits
- Disk IOPS: Monitor for storage bottlenecks
- Instance Health: Check for any instance alerts
Database Services
Autonomous Database
Autonomous Transaction Processing (ATP)
Use Cases: OLTP workloads, web applications, SaaS applications
Provisioning:
resource "oci_database_autonomous_database" "atp" {
compartment_id = var.compartment_id
db_name = "atpdb"
display_name = "ATP Database"
admin_password = var.admin_password
cpu_core_count = 1
data_storage_size_in_tbs = 1
db_version = "19c"
db_workload = "OLTP"
is_auto_scaling_enabled = true
is_free_tier = false
license_model = "LICENSE_INCLUDED"
subnet_id = var.private_subnet_id
nsg_ids = [oci_core_network_security_group.db_nsg.id]
whitelisted_ips = ["10.0.0.0/16"]
freeform_tags = {
Environment = "Production"
}
}Autonomous Data Warehouse (ADW)
Use Cases: Analytics, data warehousing, reporting
resource "oci_database_autonomous_database" "adw" {
compartment_id = var.compartment_id
db_name = "adwdb"
display_name = "ADW Database"
admin_password = var.admin_password
cpu_core_count = 2
data_storage_size_in_tbs = 2
db_version = "19c"
db_workload = "DW"
is_auto_scaling_enabled = true
license_model = "LICENSE_INCLUDED"
}Autonomous Database Connection
Wallet Download:
# Download wallet
oci db autonomous-database generate-wallet \
--autonomous-database-id ocid1.autonomousdatabase... \
--file wallet.zip \
--password MyWalletPassword123Connection String:
import cx_Oracle
# Using wallet
connection = cx_Oracle.connect(
user="admin",
password="MyPassword123",
dsn="atpdb_high",
config_dir="/path/to/wallet",
wallet_location="/path/to/wallet",
wallet_password="MyWalletPassword123"
)Auto Scaling Configuration
CPU Auto Scaling:
- Automatically scales up to 3x the base OCPU count
- Scales based on CPU utilization
- No additional configuration needed when
is_auto_scaling_enabled = true
Storage Auto Scaling:
resource "oci_database_autonomous_database" "atp_auto_scale" {
# ... other configuration ...
is_auto_scaling_enabled = true
is_auto_scaling_for_storage_enabled = true
}MySQL Database Service
MySQL DB System
resource "oci_mysql_mysql_db_system" "main_mysql" {
compartment_id = var.compartment_id
shape_name = "MySQL.VM.Standard.E4.1.8GB"
subnet_id = var.private_subnet_id
admin_password = var.admin_password
admin_username = "admin"
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = "main-mysql"
data_storage_size_in_gb = 50
configuration_id = data.oci_mysql_mysql_configurations.mysql_configs.configurations[0].id
backup_policy {
is_enabled = true
retention_in_days = 7
window_start_time = "02:00"
}
maintenance {
window_start_time = "SUNDAY 02:00"
}
is_highly_available = true
freeform_tags = {
Environment = "Production"
}
}MySQL High Availability
resource "oci_mysql_mysql_db_system" "ha_mysql" {
# ... base configuration ...
is_highly_available = true
# HA configuration creates:
# - Primary instance
# - Secondary instance in different AD
# - Automatic failover
}MySQL Backup and Recovery
Manual Backup:
# Create manual backup
oci mysql backup create \
--db-system-id ocid1.mysqldbsystem... \
--display-name "manual-backup-$(date +%Y%m%d)"
# Restore from backup
oci mysql db-system create-from-backup \
--backup-id ocid1.mysqlbackup... \
--compartment-id ocid1.compartment... \
--shape-name "MySQL.VM.Standard.E4.1.8GB" \
--subnet-id ocid1.subnet...MySQL Connection
import mysql.connector
config = {
'host': '10.0.2.10',
'port': 3306,
'user': 'admin',
'password': 'MyPassword123',
'database': 'myapp',
'ssl_ca': '/path/to/ca-cert.pem',
'ssl_verify_cert': True
}
connection = mysql.connector.connect(**config)
cursor = connection.cursor()PostgreSQL Database Service
PostgreSQL DB System
resource "oci_psql_db_system" "main_postgres" {
compartment_id = var.compartment_id
display_name = "main-postgres"
db_version = "14"
shape = "PostgreSQL.VM.Standard.E4.Flex.2.32GB"
instance_count = 1
instance_ocpu_count = 2
instance_memory_size_in_gbs = 32
storage_details {
is_regionally_durable = true
system_type = "OCI_OPTIMIZED_STORAGE"
}
network_details {
subnet_id = var.private_subnet_id
nsg_ids = [oci_core_network_security_group.db_nsg.id]
}
credentials {
username = "postgres"
password_details {
password_type = "PLAIN_TEXT"
password = var.postgres_password
}
}
}PostgreSQL Connection
import psycopg2
connection = psycopg2.connect(
host="10.0.2.20",
port=5432,
database="myapp",
user="postgres",
password="MyPassword123",
sslmode="require"
)NoSQL Database Service
NoSQL Table
resource "oci_nosql_table" "user_table" {
compartment_id = var.compartment_id
name = "users"
ddl_statement = <<-EOT
CREATE TABLE IF NOT EXISTS users (
id INTEGER,
email STRING,
name STRING,
created_at TIMESTAMP(3),
PRIMARY KEY (id)
)
EOT
table_limits {
max_read_units = 50
max_write_units = 50
max_storage_in_gbs = 25
}
}
resource "oci_nosql_index" "email_index" {
table_name_or_id = oci_nosql_table.user_table.id
name = "emailIndex"
keys {
column_name = "email"
}
}NoSQL Operations
Python SDK Example:
from oci import nosql
from oci.config import from_file
config = from_file()
nosql_client = nosql.NosqlClient(config)
# Put row
put_request = nosql.models.UpdateRowDetails(
value={
"id": 1,
"email": "user@example.com",
"name": "John Doe",
"created_at": "2024-01-15T10:00:00.000Z"
},
compartment_id=compartment_id
)
nosql_client.update_row(
table_name_or_id="users",
update_row_details=put_request
)
# Get row
get_request = nosql.models.GetRowDetails(
key={"id": 1}
)
response = nosql_client.get_row(
table_name_or_id="users",
key=["id:1"]
)
# Query
query_request = nosql.models.QueryDetails(
statement="SELECT * FROM users WHERE email = 'user@example.com'",
compartment_id=compartment_id
)
query_response = nosql_client.query(query_request)Database Backup Strategies
Autonomous Database Backups
Automatic Backups:
- Retained for 60 days by default
- Daily incremental backups
- Weekly full backups
- Point-in-time recovery available
Manual Backups:
# Create manual backup
oci db autonomous-database create-backup \
--autonomous-database-id ocid1.autonomousdatabase... \
--display-name "pre-upgrade-backup"
# Restore from backup
oci db autonomous-database restore \
--autonomous-database-id ocid1.autonomousdatabase... \
--timestamp "2024-01-15T10:00:00.000Z"MySQL Backup Policy
resource "oci_mysql_mysql_db_system" "mysql_with_backup" {
# ... base configuration ...
backup_policy {
is_enabled = true
retention_in_days = 30
window_start_time = "02:00"
# Point-in-time recovery
pitr_policy {
is_enabled = true
}
}
}Database Migration
MySQL Migration Using Data Pump
Export from Source:
mysqldump -h source-host \
-u admin -p \
--single-transaction \
--routines \
--triggers \
--databases myapp > myapp_dump.sqlImport to OCI MySQL:
mysql -h mysql-oci-host \
-u admin -p \
--ssl-ca=/path/to/ca-cert.pem < myapp_dump.sqlPostgreSQL Migration
Using pg_dump/pg_restore:
# Export
pg_dump -h source-host \
-U postgres \
-d myapp \
-F c \
-f myapp_dump.dump
# Restore
pg_restore -h postgres-oci-host \
-U postgres \
-d myapp \
myapp_dump.dumpConnection Pooling
PgBouncer for PostgreSQL
[databases]
myapp = host=postgres-host port=5432 dbname=myapp
[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25MySQL Connection Pool (Python)
from mysql.connector import pooling
pool = pooling.MySQLConnectionPool(
pool_name="myapp_pool",
pool_size=10,
pool_reset_session=True,
host='mysql-host',
database='myapp',
user='admin',
password='password'
)
connection = pool.get_connection()Performance Optimization
Autonomous Database Performance
Enable Auto Scaling:
resource "oci_database_autonomous_database" "optimized_atp" {
# ... base configuration ...
is_auto_scaling_enabled = true
cpu_core_count = 1 # Can scale up to 3 OCPUs
}Query Performance:
- Use bind variables to enable plan caching
- Create appropriate indexes
- Monitor Performance Hub for slow queries
- Use result cache for frequently accessed data
MySQL Performance Tuning
Key Parameters:
-- Connection settings
SET GLOBAL max_connections = 500;
-- Buffer pool size (set to 70-80% of available memory)
SET GLOBAL innodb_buffer_pool_size = 25769803776; -- 24GB
-- Query cache (for read-heavy workloads)
SET GLOBAL query_cache_size = 268435456; -- 256MB
SET GLOBAL query_cache_type = 1;
-- Slow query log
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;NoSQL Performance
Optimize Table Limits:
resource "oci_nosql_table" "high_performance" {
# ... base configuration ...
table_limits {
max_read_units = 500 # Increase for read-heavy workloads
max_write_units = 200 # Increase for write-heavy workloads
max_storage_in_gbs = 100
}
}Monitoring and Alerts
Database Metrics
Key Metrics to Monitor:
- CPU Utilization (target < 80%)
- Storage Used (alert at 80%)
- Connection Count (monitor for connection pool exhaustion)
- Query Response Time (track slow queries)
- Replication Lag (for HA configurations)
OCI Monitoring Query:
# Get CPU utilization for Autonomous Database
oci monitoring metric-data summarize-metrics-data \
--compartment-id ocid1.compartment... \
--namespace oci_autonomous_database \
--query-text "CpuUtilization[1m].mean()" \
--start-time 2024-01-15T00:00:00.000Z \
--end-time 2024-01-15T23:59:59.000ZAlarm Configuration
resource "oci_monitoring_alarm" "db_cpu_alarm" {
compartment_id = var.compartment_id
display_name = "db-high-cpu"
is_enabled = true
metric_compartment_id = var.compartment_id
namespace = "oci_autonomous_database"
query = "CpuUtilization[1m].mean() > 80"
severity = "CRITICAL"
destinations = [oci_ons_notification_topic.alerts.id]
repeat_notification_duration = "PT2H"
}Security Best Practices
1. Encryption: Enable TDE (Transparent Data Encryption) for all databases 2. Network Access: Use private subnets and NSGs 3. Authentication: Use strong passwords and rotate regularly 4. Audit Logging: Enable database audit logs 5. Backup Encryption: Ensure backups are encrypted 6. Least Privilege: Grant minimum required permissions 7. Connection Security: Always use SSL/TLS for connections
Identity and Access Management (IAM)
Compartment Design
Compartment Hierarchy Best Practices
Root Compartment (Tenancy)
├── Network (shared networking resources)
│ ├── VCN-Prod
│ └── VCN-Dev
├── Security (shared security resources)
│ ├── Vaults
│ └── Keys
├── Applications
│ ├── App1-Prod
│ ├── App1-Dev
│ ├── App2-Prod
│ └── App2-Dev
└── Shared-Services
├── Monitoring
└── LoggingCreating Compartments
Terraform:
resource "oci_identity_compartment" "network" {
compartment_id = var.tenancy_ocid
description = "Network resources compartment"
name = "Network"
freeform_tags = {
Department = "IT"
}
}
resource "oci_identity_compartment" "app_prod" {
compartment_id = oci_identity_compartment.applications.id
description = "Production environment for App1"
name = "App1-Prod"
enable_delete = false # Prevent accidental deletion
}OCI CLI:
oci iam compartment create \
--compartment-id ocid1.tenancy... \
--name "Network" \
--description "Network resources compartment"Users and Groups
User Management
Create User:
resource "oci_identity_user" "developer" {
compartment_id = var.tenancy_ocid
description = "Developer user"
name = "john.doe@example.com"
email = "john.doe@example.com"
freeform_tags = {
Role = "Developer"
}
}Create API Key:
# Generate key pair
openssl genrsa -out ~/.oci/oci_api_key.pem 2048
openssl rsa -pubout -in ~/.oci/oci_api_key.pem -out ~/.oci/oci_api_key_public.pem
# Get fingerprint
openssl rsa -pubout -outform DER -in ~/.oci/oci_api_key.pem | openssl md5 -c
# Upload public key via CLI
oci iam user api-key upload \
--user-id ocid1.user... \
--key-file ~/.oci/oci_api_key_public.pemGroup Management
resource "oci_identity_group" "developers" {
compartment_id = var.tenancy_ocid
description = "Developer group"
name = "Developers"
}
resource "oci_identity_group" "admins" {
compartment_id = var.tenancy_ocid
description = "Administrator group"
name = "Administrators"
}
resource "oci_identity_user_group_membership" "dev_membership" {
group_id = oci_identity_group.developers.id
user_id = oci_identity_user.developer.id
}IAM Policies
Policy Syntax
Format: Allow <subject> to <verb> <resource-type> in <location> where <conditions>
Subjects:
group <group-name>- User groupdynamic-group <dynamic-group-name>- Dynamic groupany-user- All authenticated usersservice <service-name>- OCI service
Verbs:
inspect- List resourcesread- View resource detailsuse- Use existing resourcesmanage- Full control (create, update, delete)
Common Policy Examples
Read-Only Access:
resource "oci_identity_policy" "read_only" {
compartment_id = var.compartment_id
description = "Read-only access to compute and networking"
name = "ReadOnlyPolicy"
statements = [
"Allow group Developers to inspect instances in compartment App1-Prod",
"Allow group Developers to inspect vcns in compartment Network",
"Allow group Developers to read metrics in compartment App1-Prod"
]
}Developer Policy:
resource "oci_identity_policy" "developers" {
compartment_id = var.compartment_id
description = "Developer policy for non-prod environments"
name = "DeveloperPolicy"
statements = [
"Allow group Developers to manage instances in compartment App1-Dev",
"Allow group Developers to manage volumes in compartment App1-Dev",
"Allow group Developers to use vnics in compartment Network",
"Allow group Developers to use subnets in compartment Network",
"Allow group Developers to use network-security-groups in compartment Network",
"Allow group Developers to read autonomous-databases in compartment App1-Dev"
]
}Administrator Policy:
resource "oci_identity_policy" "admins" {
compartment_id = var.tenancy_ocid
description = "Full administrator access"
name = "AdministratorPolicy"
statements = [
"Allow group Administrators to manage all-resources in tenancy"
]
}Network Administrator:
resource "oci_identity_policy" "network_admins" {
compartment_id = var.tenancy_ocid
description = "Network administrator policy"
name = "NetworkAdminPolicy"
statements = [
"Allow group NetworkAdmins to manage vcns in compartment Network",
"Allow group NetworkAdmins to manage subnets in compartment Network",
"Allow group NetworkAdmins to manage internet-gateways in compartment Network",
"Allow group NetworkAdmins to manage nat-gateways in compartment Network",
"Allow group NetworkAdmins to manage service-gateways in compartment Network",
"Allow group NetworkAdmins to manage security-lists in compartment Network",
"Allow group NetworkAdmins to manage network-security-groups in compartment Network",
"Allow group NetworkAdmins to manage route-tables in compartment Network",
"Allow group NetworkAdmins to manage drgs in compartment Network",
"Allow group NetworkAdmins to manage load-balancers in compartment Network"
]
}Database Administrator:
resource "oci_identity_policy" "db_admins" {
compartment_id = var.compartment_id
description = "Database administrator policy"
name = "DBAdminPolicy"
statements = [
"Allow group DBAdmins to manage autonomous-databases in compartment App1-Prod",
"Allow group DBAdmins to manage autonomous-backups in compartment App1-Prod",
"Allow group DBAdmins to manage database-family in compartment App1-Prod",
"Allow group DBAdmins to read metrics in compartment App1-Prod"
]
}Conditional Policies
IP-Based Access:
resource "oci_identity_policy" "ip_restricted" {
compartment_id = var.tenancy_ocid
description = "Allow access only from specific IP"
name = "IPRestrictedPolicy"
statements = [
"Allow group Developers to manage all-resources in compartment App1-Dev where request.networkSource.name = 'CorporateNetwork'"
]
}
resource "oci_identity_network_source" "corporate" {
compartment_id = var.tenancy_ocid
description = "Corporate network"
name = "CorporateNetwork"
public_source_list = [
"203.0.113.0/24",
"198.51.100.0/24"
]
}Tag-Based Access:
resource "oci_identity_policy" "tag_based" {
compartment_id = var.compartment_id
description = "Tag-based policy"
name = "TagBasedPolicy"
statements = [
"Allow group Developers to manage instances in compartment App1-Dev where target.resource.tag.Environment = 'Development'"
]
}Dynamic Groups
Create Dynamic Group
For Compute Instances in Compartment:
resource "oci_identity_dynamic_group" "app_instances" {
compartment_id = var.tenancy_ocid
description = "Dynamic group for app instances"
name = "AppInstancesDynamicGroup"
matching_rule = "ALL {instance.compartment.id = '${var.compartment_id}'}"
}For OKE Clusters:
resource "oci_identity_dynamic_group" "oke_clusters" {
compartment_id = var.tenancy_ocid
description = "Dynamic group for OKE clusters"
name = "OKEClustersDynamicGroup"
matching_rule = "ALL {resource.type = 'cluster', resource.compartment.id = '${var.compartment_id}'}"
}Complex Matching Rules:
resource "oci_identity_dynamic_group" "complex" {
compartment_id = var.tenancy_ocid
description = "Complex dynamic group"
name = "ComplexDynamicGroup"
matching_rule = <<-EOT
ANY {
instance.compartment.id = '${var.app_compartment_id}',
resource.type = 'fnfunc',
resource.type = 'autonomousdatabase'
}
EOT
}Dynamic Group Policies
resource "oci_identity_policy" "instance_principal" {
compartment_id = var.tenancy_ocid
description = "Policy for instance principals"
name = "InstancePrincipalPolicy"
statements = [
"Allow dynamic-group AppInstancesDynamicGroup to read secret-bundles in compartment Security",
"Allow dynamic-group AppInstancesDynamicGroup to use keys in compartment Security",
"Allow dynamic-group AppInstancesDynamicGroup to manage objects in compartment App1-Prod where target.bucket.name='app-data'",
"Allow dynamic-group AppInstancesDynamicGroup to read autonomous-databases in compartment App1-Prod"
]
}Federation
Identity Provider (SAML 2.0)
resource "oci_identity_identity_provider" "saml_idp" {
compartment_id = var.tenancy_ocid
name = "CorporateSSO"
description = "Corporate SAML SSO"
product_type = "IDCS"
protocol = "SAML2"
metadata_url = "https://idp.example.com/metadata"
freeform_tags = {
Type = "SSO"
}
}
resource "oci_identity_idp_group_mapping" "idp_mapping" {
identity_provider_id = oci_identity_identity_provider.saml_idp.id
idp_group_name = "OCI-Developers"
group_id = oci_identity_group.developers.id
}Multi-Factor Authentication (MFA)
Enable MFA for User
# Enable MFA
oci iam user update-user-capabilities \
--user-id ocid1.user... \
--can-use-console-password true
# User must enable MFA in console settingsPolicy to Require MFA:
resource "oci_identity_policy" "require_mfa" {
compartment_id = var.tenancy_ocid
description = "Require MFA for sensitive operations"
name = "RequireMFAPolicy"
statements = [
"Allow group Administrators to manage all-resources in tenancy where request.user.mfaTotpVerified='true'"
]
}Service Accounts
Create Service Account User
resource "oci_identity_user" "service_account" {
compartment_id = var.tenancy_ocid
description = "Service account for CI/CD"
name = "svc-cicd"
freeform_tags = {
Type = "ServiceAccount"
}
}
resource "oci_identity_api_key" "service_account_key" {
user_id = oci_identity_user.service_account.id
key_value = file("${path.module}/keys/service_account_public_key.pem")
}
resource "oci_identity_user_group_membership" "service_account_membership" {
group_id = oci_identity_group.cicd_group.id
user_id = oci_identity_user.service_account.id
}Tagging Strategy
Tag Namespaces and Keys
resource "oci_identity_tag_namespace" "corporate" {
compartment_id = var.tenancy_ocid
description = "Corporate tag namespace"
name = "Corporate"
}
resource "oci_identity_tag" "cost_center" {
tag_namespace_id = oci_identity_tag_namespace.corporate.id
description = "Cost center for billing"
name = "CostCenter"
validator {
validator_type = "ENUM"
values = ["IT", "Finance", "HR", "Engineering"]
}
}
resource "oci_identity_tag" "environment" {
tag_namespace_id = oci_identity_tag_namespace.corporate.id
description = "Environment type"
name = "Environment"
validator {
validator_type = "ENUM"
values = ["Development", "Staging", "Production"]
}
is_cost_tracking = true
}Tag Defaults
resource "oci_identity_tag_default" "default_env" {
compartment_id = var.compartment_id
tag_definition_id = oci_identity_tag.environment.id
value = "Development"
is_required = true
}Using Tags
resource "oci_core_instance" "tagged_instance" {
# ... other configuration ...
freeform_tags = {
Application = "WebApp"
Team = "Platform"
}
defined_tags = {
"${oci_identity_tag_namespace.corporate.name}.${oci_identity_tag.cost_center.name}" = "Engineering"
"${oci_identity_tag_namespace.corporate.name}.${oci_identity_tag.environment.name}" = "Production"
}
}Resource Limits and Quotas
Check Service Limits
# List all service limits
oci limits value list \
--compartment-id ocid1.tenancy... \
--service-name compute
# Get specific limit
oci limits value get \
--compartment-id ocid1.tenancy... \
--service-name compute \
--scope-type REGION \
--limit-name vm-standard-e4-flex-core-count \
--availability-domain "AD-1"Request Limit Increase
oci limits quota create \
--compartment-id ocid1.tenancy... \
--description "Increase compute quota" \
--name "compute-quota-increase" \
--statements '["Set compute quotas vm-standard-e4-flex-core-count to 100 in compartment App1-Prod"]'Audit Logging
Enable Audit Logs
OCI automatically logs all API calls. View audit logs:
# List audit events
oci audit event list \
--compartment-id ocid1.compartment... \
--start-time 2024-01-15T00:00:00.000Z \
--end-time 2024-01-15T23:59:59.000ZAudit Log Analysis
# Get audit events for specific user
oci audit event list \
--compartment-id ocid1.tenancy... \
--start-time 2024-01-15T00:00:00.000Z \
--end-time 2024-01-15T23:59:59.000Z \
--query "data[?\"principal-id\"=='ocid1.user...'].{time:\"event-time\",action:\"event-name\",resource:\"resource-name\"}"
# Filter by event type
oci audit event list \
--compartment-id ocid1.tenancy... \
--start-time 2024-01-15T00:00:00.000Z \
--end-time 2024-01-15T23:59:59.000Z \
--query "data[?\"event-name\"=='DeleteInstance']"Best Practices
IAM Best Practices
1. Least Privilege: Grant minimum required permissions 2. Use Groups: Never assign policies directly to users 3. Compartment Isolation: Separate resources by compartment 4. Regular Reviews: Audit users, groups, and policies quarterly 5. Service Accounts: Use dynamic groups for compute instances 6. MFA: Enable MFA for all administrator accounts 7. API Key Rotation: Rotate API keys every 90 days 8. Tag Everything: Use tags for cost tracking and access control
Policy Design Patterns
Principle of Least Privilege:
# Good - Specific permissions
"Allow group Developers to use instances in compartment App1-Dev"
"Allow group Developers to use vnics in compartment Network"
# Avoid - Overly broad permissions
"Allow group Developers to manage all-resources in tenancy"Separation of Duties:
# Network team manages networking
"Allow group NetworkAdmins to manage vcns in compartment Network"
# App team uses networking
"Allow group Developers to use vnics in compartment Network"
"Allow group Developers to use subnets in compartment Network"Security Recommendations
1. Enable Cloud Guard: Automated threat detection 2. Use Security Zones: Enforce security policies 3. Regular Audits: Review audit logs for suspicious activity 4. Implement Network Sources: Restrict access by IP 5. Use Vault: Store secrets and encryption keys 6. Enable Logging: Comprehensive logging for compliance
Networking Architecture
Virtual Cloud Network (VCN) Design
VCN CIDR Planning
Best Practices:
- Use RFC 1918 private address space (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Plan for growth: Use /16 for VCN, /24 for subnets
- Avoid overlapping CIDRs with on-premises networks
- Reserve space for peering with other VCNs
Example CIDR Layout:
VCN: 10.0.0.0/16
├── Public Subnet (Web Tier): 10.0.1.0/24
├── Private Subnet (App Tier): 10.0.2.0/24
├── Private Subnet (DB Tier): 10.0.3.0/24
└── Reserved for future: 10.0.4.0/22VCN Creation
Terraform Example:
resource "oci_core_vcn" "main_vcn" {
compartment_id = var.compartment_id
cidr_blocks = ["10.0.0.0/16"]
display_name = "main-vcn"
dns_label = "mainvcn"
freeform_tags = {
Environment = "Production"
}
}
resource "oci_core_internet_gateway" "igw" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "internet-gateway"
enabled = true
}
resource "oci_core_nat_gateway" "nat" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "nat-gateway"
}
resource "oci_core_service_gateway" "service_gw" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "service-gateway"
services {
service_id = data.oci_core_services.all_services.services[0].id
}
}Subnet Configuration
Public Subnet
Use Cases: Web servers, load balancers, bastion hosts
resource "oci_core_subnet" "public_subnet" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
cidr_block = "10.0.1.0/24"
display_name = "public-subnet"
dns_label = "public"
prohibit_public_ip_on_vnic = false
route_table_id = oci_core_route_table.public_rt.id
security_list_ids = [oci_core_security_list.public_sl.id]
}
resource "oci_core_route_table" "public_rt" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "public-route-table"
route_rules {
network_entity_id = oci_core_internet_gateway.igw.id
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
}
}Private Subnet
Use Cases: Application servers, databases, internal services
resource "oci_core_subnet" "private_subnet" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
cidr_block = "10.0.2.0/24"
display_name = "private-subnet"
dns_label = "private"
prohibit_public_ip_on_vnic = true
route_table_id = oci_core_route_table.private_rt.id
security_list_ids = [oci_core_security_list.private_sl.id]
}
resource "oci_core_route_table" "private_rt" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "private-route-table"
route_rules {
network_entity_id = oci_core_nat_gateway.nat.id
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
}
route_rules {
network_entity_id = oci_core_service_gateway.service_gw.id
destination = data.oci_core_services.all_services.services[0].cidr_block
destination_type = "SERVICE_CIDR_BLOCK"
}
}Security Lists
Public Subnet Security List
resource "oci_core_security_list" "public_sl" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "public-security-list"
# Ingress Rules
ingress_security_rules {
protocol = "6" # TCP
source = "0.0.0.0/0"
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
min = 80
max = 80
}
description = "Allow HTTP from internet"
}
ingress_security_rules {
protocol = "6" # TCP
source = "0.0.0.0/0"
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
min = 443
max = 443
}
description = "Allow HTTPS from internet"
}
ingress_security_rules {
protocol = "6" # TCP
source = var.admin_cidr
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
min = 22
max = 22
}
description = "Allow SSH from admin network"
}
# Egress Rules
egress_security_rules {
protocol = "all"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
stateless = false
description = "Allow all outbound"
}
}Private Subnet Security List
resource "oci_core_security_list" "private_sl" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "private-security-list"
# Ingress from public subnet
ingress_security_rules {
protocol = "6"
source = oci_core_subnet.public_subnet.cidr_block
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
min = 8080
max = 8080
}
description = "Allow app traffic from public subnet"
}
# Ingress within private subnet
ingress_security_rules {
protocol = "all"
source = oci_core_subnet.private_subnet.cidr_block
source_type = "CIDR_BLOCK"
stateless = false
description = "Allow all traffic within private subnet"
}
# Egress Rules
egress_security_rules {
protocol = "all"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
stateless = false
description = "Allow all outbound"
}
}Network Security Groups (NSG)
NSG for Web Servers
resource "oci_core_network_security_group" "web_nsg" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "web-nsg"
}
resource "oci_core_network_security_group_security_rule" "web_http_ingress" {
network_security_group_id = oci_core_network_security_group.web_nsg.id
direction = "INGRESS"
protocol = "6"
source = "0.0.0.0/0"
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
destination_port_range {
min = 80
max = 80
}
}
description = "Allow HTTP"
}
resource "oci_core_network_security_group_security_rule" "web_https_ingress" {
network_security_group_id = oci_core_network_security_group.web_nsg.id
direction = "INGRESS"
protocol = "6"
source = "0.0.0.0/0"
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
destination_port_range {
min = 443
max = 443
}
}
description = "Allow HTTPS"
}NSG for Database
resource "oci_core_network_security_group" "db_nsg" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main_vcn.id
display_name = "db-nsg"
}
resource "oci_core_network_security_group_security_rule" "db_ingress_from_app" {
network_security_group_id = oci_core_network_security_group.db_nsg.id
direction = "INGRESS"
protocol = "6"
source = oci_core_network_security_group.app_nsg.id
source_type = "NETWORK_SECURITY_GROUP"
stateless = false
tcp_options {
destination_port_range {
min = 3306
max = 3306
}
}
description = "Allow MySQL from app tier"
}Load Balancer Configuration
Public Load Balancer
resource "oci_load_balancer_load_balancer" "public_lb" {
compartment_id = var.compartment_id
display_name = "public-load-balancer"
shape = "flexible"
shape_details {
minimum_bandwidth_in_mbps = 10
maximum_bandwidth_in_mbps = 100
}
subnet_ids = [
oci_core_subnet.public_subnet.id
]
is_private = false
}
resource "oci_load_balancer_backend_set" "web_backend" {
load_balancer_id = oci_load_balancer_load_balancer.public_lb.id
name = "web-backend-set"
policy = "ROUND_ROBIN"
health_checker {
protocol = "HTTP"
port = 80
url_path = "/health"
interval_ms = 10000
timeout_in_millis = 3000
retries = 3
return_code = 200
}
}
resource "oci_load_balancer_listener" "http_listener" {
load_balancer_id = oci_load_balancer_load_balancer.public_lb.id
name = "http-listener"
default_backend_set_name = oci_load_balancer_backend_set.web_backend.name
port = 80
protocol = "HTTP"
}
resource "oci_load_balancer_listener" "https_listener" {
load_balancer_id = oci_load_balancer_load_balancer.public_lb.id
name = "https-listener"
default_backend_set_name = oci_load_balancer_backend_set.web_backend.name
port = 443
protocol = "HTTP"
ssl_configuration {
certificate_name = "ssl-cert"
verify_peer_certificate = false
}
}SSL Certificate Management
resource "oci_load_balancer_certificate" "ssl_cert" {
load_balancer_id = oci_load_balancer_load_balancer.public_lb.id
certificate_name = "ssl-cert"
ca_certificate = file("ca-cert.pem")
private_key = file("private-key.pem")
public_certificate = file("public-cert.pem")
lifecycle {
create_before_destroy = true
}
}VPN and Hybrid Connectivity
Site-to-Site VPN
resource "oci_core_drg" "main_drg" {
compartment_id = var.compartment_id
display_name = "main-drg"
}
resource "oci_core_drg_attachment" "vcn_attachment" {
drg_id = oci_core_drg.main_drg.id
vcn_id = oci_core_vcn.main_vcn.id
}
resource "oci_core_cpe" "on_prem_cpe" {
compartment_id = var.compartment_id
display_name = "on-premises-cpe"
ip_address = var.on_prem_public_ip
}
resource "oci_core_ipsec" "vpn_connection" {
compartment_id = var.compartment_id
cpe_id = oci_core_cpe.on_prem_cpe.id
drg_id = oci_core_drg.main_drg.id
static_routes = ["192.168.0.0/16"]
display_name = "vpn-connection"
}FastConnect
resource "oci_core_virtual_circuit" "fastconnect" {
compartment_id = var.compartment_id
type = "PRIVATE"
bandwidth_shape_name = "1 Gbps"
customer_bgp_asn = var.customer_bgp_asn
gateway_id = oci_core_drg.main_drg.id
provider_service_id = var.provider_service_id
region = var.region
display_name = "fastconnect-circuit"
}VCN Peering
Local Peering (Same Region)
resource "oci_core_local_peering_gateway" "lpg1" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.vcn1.id
display_name = "lpg-vcn1"
}
resource "oci_core_local_peering_gateway" "lpg2" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.vcn2.id
display_name = "lpg-vcn2"
peer_id = oci_core_local_peering_gateway.lpg1.id
}Remote Peering (Cross-Region)
resource "oci_core_remote_peering_connection" "rpc1" {
compartment_id = var.compartment_id
drg_id = oci_core_drg.drg1.id
display_name = "rpc-region1"
}
resource "oci_core_remote_peering_connection" "rpc2" {
compartment_id = var.compartment_id
drg_id = oci_core_drg.drg2.id
display_name = "rpc-region2"
peer_id = oci_core_remote_peering_connection.rpc1.id
peer_region_name = var.peer_region
}DNS Configuration
Private DNS
resource "oci_dns_zone" "private_zone" {
compartment_id = var.compartment_id
name = "internal.example.com"
zone_type = "PRIMARY"
scope = "PRIVATE"
view_id = oci_dns_view.private_view.id
}
resource "oci_dns_rrset" "app_record" {
zone_name_or_id = oci_dns_zone.private_zone.id
domain = "app.internal.example.com"
rtype = "A"
scope = "PRIVATE"
view_id = oci_dns_view.private_view.id
items {
domain = "app.internal.example.com"
rdata = "10.0.2.10"
rtype = "A"
ttl = 300
}
}Network Monitoring
Flow Logs
resource "oci_core_capture_filter" "flow_logs_filter" {
compartment_id = var.compartment_id
display_name = "flow-logs-filter"
filter_type = "VTAP"
vtap_capture_filter_rules {
traffic_direction = "INGRESS"
}
}Best Practices Summary
1. VCN Design: Use /16 for VCN, /24 for subnets, plan for growth 2. Security: Use NSGs for fine-grained control, Security Lists for subnet-level 3. High Availability: Deploy across multiple availability domains 4. Load Balancing: Use flexible shapes, configure health checks properly 5. Hybrid Connectivity: Use FastConnect for production, VPN for dev/test 6. DNS: Use private DNS for internal service discovery 7. Monitoring: Enable VCN flow logs for troubleshooting
OCI CLI Commands Reference
Installation and Configuration
Install OCI CLI
macOS/Linux:
bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"Python pip:
pip install oci-cliConfigure OCI CLI
Interactive Setup:
oci setup configManual Configuration (~/.oci/config):
[DEFAULT]
user=ocid1.user.oc1..aaaa...
fingerprint=12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef
tenancy=ocid1.tenancy.oc1..aaaa...
region=us-ashburn-1
key_file=~/.oci/oci_api_key.pem
[PRODUCTION]
user=ocid1.user.oc1..bbbb...
fingerprint=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99
tenancy=ocid1.tenancy.oc1..bbbb...
region=us-phoenix-1
key_file=~/.oci/prod_api_key.pemUse Specific Profile:
oci compute instance list --profile PRODUCTIONVerify Configuration
# Test connection
oci iam region list
# Get current user
oci iam user get --user-id $(oci iam user list --query 'data[0].id' --raw-output)Compute Commands
List Instances
# List all instances in compartment
oci compute instance list \
--compartment-id ocid1.compartment... \
--all
# List instances with specific display name
oci compute instance list \
--compartment-id ocid1.compartment... \
--display-name "web-server"
# List running instances only
oci compute instance list \
--compartment-id ocid1.compartment... \
--lifecycle-state RUNNING
# Get instance details
oci compute instance get \
--instance-id ocid1.instance...Launch Instance
oci compute instance launch \
--availability-domain "AD-1" \
--compartment-id ocid1.compartment... \
--shape "VM.Standard.E4.Flex" \
--shape-config '{"ocpus": 2, "memoryInGBs": 16}' \
--display-name "web-server-01" \
--image-id ocid1.image... \
--subnet-id ocid1.subnet... \
--assign-public-ip true \
--ssh-authorized-keys-file ~/.ssh/id_rsa.pub \
--wait-for-state RUNNINGManage Instance State
# Stop instance
oci compute instance action \
--instance-id ocid1.instance... \
--action STOP \
--wait-for-state STOPPED
# Start instance
oci compute instance action \
--instance-id ocid1.instance... \
--action START \
--wait-for-state RUNNING
# Restart instance
oci compute instance action \
--instance-id ocid1.instance... \
--action RESET
# Terminate instance
oci compute instance terminate \
--instance-id ocid1.instance... \
--preserve-boot-volume false \
--forceConsole Connection
# Create instance console connection
oci compute instance-console-connection create \
--instance-id ocid1.instance... \
--ssh-public-key-file ~/.ssh/id_rsa.pub
# Get console connection string
oci compute instance-console-connection get \
--instance-console-connection-id ocid1.instanceconsoleconnection...
# Connect to console
ssh -o ProxyCommand='ssh -W %h:%p -p 443 ocid1.instanceconsoleconnection...@instance-console.us-ashburn-1.oraclecloud.com' ocid1.instance...Networking Commands
VCN Operations
# List VCNs
oci network vcn list \
--compartment-id ocid1.compartment...
# Create VCN
oci network vcn create \
--compartment-id ocid1.compartment... \
--display-name "main-vcn" \
--cidr-block "10.0.0.0/16" \
--dns-label "mainvcn"
# Get VCN details
oci network vcn get \
--vcn-id ocid1.vcn...
# Delete VCN
oci network vcn delete \
--vcn-id ocid1.vcn... \
--forceSubnet Operations
# List subnets
oci network subnet list \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn...
# Create subnet
oci network subnet create \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn... \
--display-name "public-subnet" \
--cidr-block "10.0.1.0/24" \
--dns-label "public" \
--route-table-id ocid1.routetable...
# Update subnet
oci network subnet update \
--subnet-id ocid1.subnet... \
--route-table-id ocid1.routetable... \
--forceSecurity Lists
# List security lists
oci network security-list list \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn...
# Create security list
oci network security-list create \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn... \
--display-name "web-security-list" \
--ingress-security-rules '[{"source":"0.0.0.0/0","protocol":"6","tcpOptions":{"destinationPortRange":{"min":80,"max":80}}}]' \
--egress-security-rules '[{"destination":"0.0.0.0/0","protocol":"all"}]'Network Security Groups
# List NSGs
oci network nsg list \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn...
# Create NSG
oci network nsg create \
--compartment-id ocid1.compartment... \
--vcn-id ocid1.vcn... \
--display-name "web-nsg"
# Add NSG rule
oci network nsg rules add \
--nsg-id ocid1.networksecuritygroup... \
--security-rules '[{
"direction": "INGRESS",
"protocol": "6",
"source": "0.0.0.0/0",
"tcpOptions": {"destinationPortRange": {"min": 443, "max": 443}}
}]'Load Balancer
# List load balancers
oci lb load-balancer list \
--compartment-id ocid1.compartment...
# Create load balancer
oci lb load-balancer create \
--compartment-id ocid1.compartment... \
--display-name "app-lb" \
--shape-name "flexible" \
--subnet-ids '["ocid1.subnet..."]' \
--shape-details '{"minimumBandwidthInMbps": 10, "maximumBandwidthInMbps": 100}' \
--wait-for-state SUCCEEDED
# Get load balancer details
oci lb load-balancer get \
--load-balancer-id ocid1.loadbalancer...Storage Commands
Block Volumes
# List volumes
oci bv volume list \
--compartment-id ocid1.compartment... \
--availability-domain "AD-1"
# Create volume
oci bv volume create \
--compartment-id ocid1.compartment... \
--availability-domain "AD-1" \
--display-name "data-volume" \
--size-in-gbs 100 \
--vpus-per-gb 20 \
--wait-for-state AVAILABLE
# Attach volume to instance
oci compute volume-attachment attach \
--instance-id ocid1.instance... \
--type paravirtualized \
--volume-id ocid1.volume... \
--device "/dev/oracleoci/oraclevdb" \
--wait-for-state ATTACHED
# Detach volume
oci compute volume-attachment detach \
--volume-attachment-id ocid1.volumeattachment... \
--force \
--wait-for-state DETACHED
# Create volume backup
oci bv backup create \
--volume-id ocid1.volume... \
--display-name "data-volume-backup" \
--type INCREMENTALObject Storage
# List buckets
oci os bucket list \
--compartment-id ocid1.compartment... \
--namespace-name your-namespace
# Create bucket
oci os bucket create \
--compartment-id ocid1.compartment... \
--name "my-bucket" \
--namespace-name your-namespace \
--public-access-type NoPublicAccess
# Upload object
oci os object put \
--bucket-name "my-bucket" \
--namespace-name your-namespace \
--file /path/to/file.txt \
--name "file.txt"
# Download object
oci os object get \
--bucket-name "my-bucket" \
--namespace-name your-namespace \
--name "file.txt" \
--file /path/to/download/file.txt
# List objects
oci os object list \
--bucket-name "my-bucket" \
--namespace-name your-namespace
# Delete object
oci os object delete \
--bucket-name "my-bucket" \
--namespace-name your-namespace \
--name "file.txt" \
--force
# Generate pre-authenticated request
oci os preauth-request create \
--bucket-name "my-bucket" \
--namespace-name your-namespace \
--name "download-link" \
--access-type ObjectRead \
--time-expires "2024-12-31T23:59:59+00:00" \
--object-name "file.txt"Database Commands
Autonomous Database
# List Autonomous Databases
oci db autonomous-database list \
--compartment-id ocid1.compartment...
# Create Autonomous Database
oci db autonomous-database create \
--compartment-id ocid1.compartment... \
--db-name "ATPDB" \
--display-name "ATP Database" \
--admin-password "MyPassword123!" \
--cpu-core-count 1 \
--data-storage-size-in-tbs 1 \
--db-workload "OLTP" \
--is-auto-scaling-enabled true \
--wait-for-state AVAILABLE
# Stop Autonomous Database
oci db autonomous-database stop \
--autonomous-database-id ocid1.autonomousdatabase... \
--wait-for-state STOPPED
# Start Autonomous Database
oci db autonomous-database start \
--autonomous-database-id ocid1.autonomousdatabase... \
--wait-for-state AVAILABLE
# Download wallet
oci db autonomous-database generate-wallet \
--autonomous-database-id ocid1.autonomousdatabase... \
--file wallet.zip \
--password "WalletPassword123!"
# Create backup
oci db autonomous-database create-backup \
--autonomous-database-id ocid1.autonomousdatabase... \
--display-name "manual-backup"
# Restore from backup
oci db autonomous-database restore \
--autonomous-database-id ocid1.autonomousdatabase... \
--timestamp "2024-01-15T10:00:00.000Z"MySQL Database
# List MySQL DB Systems
oci mysql db-system list \
--compartment-id ocid1.compartment...
# Create MySQL DB System
oci mysql db-system create \
--compartment-id ocid1.compartment... \
--shape-name "MySQL.VM.Standard.E4.1.8GB" \
--subnet-id ocid1.subnet... \
--admin-username "admin" \
--admin-password "MyPassword123!" \
--availability-domain "AD-1" \
--display-name "main-mysql" \
--data-storage-size-in-gbs 50 \
--is-highly-available true \
--wait-for-state ACTIVE
# Stop MySQL DB System
oci mysql db-system stop \
--db-system-id ocid1.mysqldbsystem... \
--wait-for-state INACTIVE
# Create backup
oci mysql backup create \
--db-system-id ocid1.mysqldbsystem... \
--display-name "manual-backup"Container and Kubernetes Commands
Container Registry
# List container repositories
oci artifacts container repository list \
--compartment-id ocid1.compartment...
# Create repository
oci artifacts container repository create \
--compartment-id ocid1.compartment... \
--display-name "myapp"
# List images
oci artifacts container image list \
--compartment-id ocid1.compartment... \
--repository-name "myapp"OKE (Oracle Kubernetes Engine)
# List clusters
oci ce cluster list \
--compartment-id ocid1.compartment...
# Create cluster
oci ce cluster create \
--compartment-id ocid1.compartment... \
--name "oke-cluster" \
--vcn-id ocid1.vcn... \
--kubernetes-version "v1.28.2" \
--wait-for-state SUCCEEDED
# Get cluster details
oci ce cluster get \
--cluster-id ocid1.cluster...
# Generate kubeconfig
oci ce cluster create-kubeconfig \
--cluster-id ocid1.cluster... \
--file $HOME/.kube/config \
--region us-ashburn-1 \
--token-version 2.0.0
# List node pools
oci ce node-pool list \
--compartment-id ocid1.compartment... \
--cluster-id ocid1.cluster...
# Create node pool
oci ce node-pool create \
--cluster-id ocid1.cluster... \
--compartment-id ocid1.compartment... \
--name "node-pool-1" \
--node-shape "VM.Standard.E4.Flex" \
--node-shape-config '{"ocpus": 2, "memoryInGBs": 16}' \
--node-image-id ocid1.image... \
--size 3 \
--subnet-ids '["ocid1.subnet..."]'IAM Commands
User Management
# List users
oci iam user list \
--compartment-id ocid1.tenancy...
# Create user
oci iam user create \
--compartment-id ocid1.tenancy... \
--name "john.doe@example.com" \
--description "Developer user" \
--email "john.doe@example.com"
# Upload API key
oci iam user api-key upload \
--user-id ocid1.user... \
--key-file ~/.ssh/oci_api_key_public.pemGroup Management
# List groups
oci iam group list \
--compartment-id ocid1.tenancy...
# Create group
oci iam group create \
--compartment-id ocid1.tenancy... \
--name "Developers" \
--description "Developer group"
# Add user to group
oci iam group add-user \
--group-id ocid1.group... \
--user-id ocid1.user...Policy Management
# List policies
oci iam policy list \
--compartment-id ocid1.compartment...
# Create policy
oci iam policy create \
--compartment-id ocid1.compartment... \
--name "DeveloperPolicy" \
--description "Developer access policy" \
--statements '["Allow group Developers to manage instances in compartment App1-Dev"]'
# Update policy
oci iam policy update \
--policy-id ocid1.policy... \
--statements '["Allow group Developers to manage all-resources in compartment App1-Dev"]' \
--forceCompartment Management
# List compartments
oci iam compartment list \
--compartment-id ocid1.tenancy... \
--all
# Create compartment
oci iam compartment create \
--compartment-id ocid1.tenancy... \
--name "App1-Prod" \
--description "Production compartment for App1"
# Move compartment
oci iam compartment move \
--compartment-id ocid1.compartment... \
--target-compartment-id ocid1.compartment.new...Monitoring and Logging
Monitoring Metrics
# List metrics
oci monitoring metric list \
--compartment-id ocid1.compartment... \
--namespace oci_computeagent
# Query metric data
oci monitoring metric-data summarize-metrics-data \
--compartment-id ocid1.compartment... \
--namespace oci_computeagent \
--query-text "CpuUtilization[1m].mean()" \
--start-time "2024-01-15T00:00:00.000Z" \
--end-time "2024-01-15T23:59:59.000Z"Alarms
# List alarms
oci monitoring alarm list \
--compartment-id ocid1.compartment...
# Create alarm
oci monitoring alarm create \
--compartment-id ocid1.compartment... \
--display-name "high-cpu-alarm" \
--metric-compartment-id ocid1.compartment... \
--namespace oci_computeagent \
--query "CpuUtilization[1m].mean() > 80" \
--severity "CRITICAL" \
--destinations '["ocid1.onstopic..."]' \
--is-enabled trueLogging
# List logs
oci logging log list \
--log-group-id ocid1.loggroup...
# Create log
oci logging log create \
--log-group-id ocid1.loggroup... \
--display-name "app-logs" \
--log-type SERVICE \
--configuration file://log-config.jsonQuery and Filtering
Using JMESPath Queries
# Get only instance IDs
oci compute instance list \
--compartment-id ocid1.compartment... \
--query 'data[*].id' \
--raw-output
# Get instance names and IPs
oci compute instance list \
--compartment-id ocid1.compartment... \
--query 'data[*].{"Name":"display-name","IP":"private-ip"}'
# Filter by lifecycle state
oci compute instance list \
--compartment-id ocid1.compartment... \
--query 'data[?lifecycle-state==`RUNNING`].{Name:"display-name",State:"lifecycle-state"}'
# Count instances
oci compute instance list \
--compartment-id ocid1.compartment... \
--query 'length(data)'Output Formats
# JSON output (default)
oci compute instance list --compartment-id ocid1.compartment...
# Table output
oci compute instance list \
--compartment-id ocid1.compartment... \
--output table
# Raw output (no formatting)
oci compute instance get \
--instance-id ocid1.instance... \
--query 'data."display-name"' \
--raw-outputBulk Operations
Bulk Instance Management
# Stop all instances in compartment
for instance in $(oci compute instance list \
--compartment-id ocid1.compartment... \
--lifecycle-state RUNNING \
--query 'data[*].id' \
--raw-output); do
echo "Stopping instance: $instance"
oci compute instance action \
--instance-id $instance \
--action STOP
done
# Tag all instances
for instance in $(oci compute instance list \
--compartment-id ocid1.compartment... \
--query 'data[*].id' \
--raw-output); do
oci compute instance update \
--instance-id $instance \
--freeform-tags '{"Environment":"Production","ManagedBy":"OCI-CLI"}'
doneTroubleshooting Commands
Debug Mode
# Enable debug output
export OCI_CLI_DEBUG=true
oci compute instance list --compartment-id ocid1.compartment...
# Or use --debug flag
oci compute instance list \
--compartment-id ocid1.compartment... \
--debugConnection Testing
# Test connectivity
curl -I https://objectstorage.us-ashburn-1.oraclecloud.com
# Verify authentication
oci iam region list
# Check API endpoint
oci iam availability-domain list \
--compartment-id ocid1.tenancy...Common Issues
Issue: ServiceError: Authorization failed or requested resource not found Solution: Verify compartment ID and IAM policies
Issue: ServiceError: Service limit exceeded Solution: Check service limits and request increase
Issue: Connection timeout Solution: Check network connectivity and proxy settings
Best Practices
1. Use Config Profiles: Separate profiles for different environments 2. Leverage Queries: Use --query for efficient data extraction 3. Wait for State: Use --wait-for-state for synchronous operations 4. Enable Pagination: Use --all for complete results 5. Script Carefully: Check exit codes and handle errors 6. Use Variables: Store OCIDs in variables for reusability 7. Audit Commands: Log all CLI operations for compliance
Terraform for Oracle Cloud Infrastructure
Provider Configuration
Basic Provider Setup
terraform {
required_providers {
oci = {
source = "oracle/oci"
version = "~> 5.0"
}
}
required_version = ">= 1.0"
}
provider "oci" {
region = var.region
tenancy_ocid = var.tenancy_ocid
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key_path = var.private_key_path
}Using Instance Principal Authentication
For compute instances with dynamic groups:
provider "oci" {
region = var.region
auth = "InstancePrincipal"
}Multi-Region Setup
provider "oci" {
alias = "home"
region = "us-ashburn-1"
tenancy_ocid = var.tenancy_ocid
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key_path = var.private_key_path
}
provider "oci" {
alias = "dr"
region = "us-phoenix-1"
tenancy_ocid = var.tenancy_ocid
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key_path = var.private_key_path
}Remote State Configuration
OCI Object Storage Backend
terraform {
backend "http" {
address = "https://objectstorage.us-ashburn-1.oraclecloud.com/n/your-namespace/b/terraform-state/o/prod/terraform.tfstate"
update_method = "PUT"
}
}S3-Compatible Backend
terraform {
backend "s3" {
bucket = "terraform-state"
key = "prod/terraform.tfstate"
region = "us-ashburn-1"
endpoint = "https://your-namespace.compat.objectstorage.us-ashburn-1.oraclecloud.com"
skip_region_validation = true
skip_credentials_validation = true
skip_metadata_api_check = true
force_path_style = true
}
}Variables Configuration
variables.tf
variable "tenancy_ocid" {
description = "OCID of the tenancy"
type = string
}
variable "user_ocid" {
description = "OCID of the user"
type = string
}
variable "fingerprint" {
description = "API key fingerprint"
type = string
}
variable "private_key_path" {
description = "Path to private key"
type = string
default = "~/.oci/oci_api_key.pem"
}
variable "region" {
description = "OCI region"
type = string
default = "us-ashburn-1"
}
variable "compartment_id" {
description = "Compartment OCID"
type = string
}
variable "availability_domain" {
description = "Availability domain"
type = string
}
variable "ssh_public_key" {
description = "SSH public key"
type = string
}
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}terraform.tfvars
tenancy_ocid = "ocid1.tenancy.oc1..aaaa..."
user_ocid = "ocid1.user.oc1..aaaa..."
fingerprint = "12:34:56:78:90:ab:cd:ef"
private_key_path = "~/.oci/oci_api_key.pem"
region = "us-ashburn-1"
compartment_id = "ocid1.compartment.oc1..aaaa..."
ssh_public_key = "ssh-rsa AAAAB3NzaC1..."
environment = "prod"Data Sources
Common Data Sources
# Get availability domains
data "oci_identity_availability_domains" "ads" {
compartment_id = var.tenancy_ocid
}
# Get compute shapes
data "oci_core_shapes" "available_shapes" {
compartment_id = var.compartment_id
filter {
name = "name"
values = ["VM.Standard.E4.Flex"]
}
}
# Get latest Oracle Linux image
data "oci_core_images" "oracle_linux" {
compartment_id = var.compartment_id
operating_system = "Oracle Linux"
operating_system_version = "8"
shape = "VM.Standard.E4.Flex"
sort_by = "TIMECREATED"
sort_order = "DESC"
}
# Get fault domains
data "oci_identity_fault_domains" "fault_domains" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
compartment_id = var.compartment_id
}
# Get OCI services for service gateway
data "oci_core_services" "all_services" {
filter {
name = "name"
values = ["All .* Services In Oracle Services Network"]
regex = true
}
}Module Structure
Project Layout
terraform/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── prod/
├── modules/
│ ├── compute/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── database/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── README.mdCompute Module Example
modules/compute/main.tf:
resource "oci_core_instance" "this" {
availability_domain = var.availability_domain
compartment_id = var.compartment_id
shape = var.shape
display_name = var.instance_name
shape_config {
ocpus = var.ocpus
memory_in_gbs = var.memory_in_gbs
}
create_vnic_details {
subnet_id = var.subnet_id
assign_public_ip = var.assign_public_ip
display_name = "${var.instance_name}-vnic"
hostname_label = var.hostname_label
nsg_ids = var.nsg_ids
skip_source_dest_check = var.skip_source_dest_check
}
source_details {
source_type = "image"
source_id = var.source_image_id
boot_volume_size_in_gbs = var.boot_volume_size
}
metadata = {
ssh_authorized_keys = var.ssh_public_key
user_data = var.user_data_base64
}
freeform_tags = var.tags
defined_tags = var.defined_tags
lifecycle {
ignore_changes = [
source_details[0].source_id,
metadata["ssh_authorized_keys"]
]
}
}
resource "oci_core_volume" "data_volume" {
count = var.create_data_volume ? 1 : 0
availability_domain = var.availability_domain
compartment_id = var.compartment_id
display_name = "${var.instance_name}-data"
size_in_gbs = var.data_volume_size
vpus_per_gb = var.data_volume_vpus_per_gb
}
resource "oci_core_volume_attachment" "data_volume_attachment" {
count = var.create_data_volume ? 1 : 0
attachment_type = "paravirtualized"
instance_id = oci_core_instance.this.id
volume_id = oci_core_volume.data_volume[0].id
device = "/dev/oracleoci/oraclevdb"
}modules/compute/variables.tf:
variable "compartment_id" {
description = "Compartment OCID"
type = string
}
variable "availability_domain" {
description = "Availability domain"
type = string
}
variable "instance_name" {
description = "Instance display name"
type = string
}
variable "shape" {
description = "Instance shape"
type = string
default = "VM.Standard.E4.Flex"
}
variable "ocpus" {
description = "Number of OCPUs"
type = number
default = 2
}
variable "memory_in_gbs" {
description = "Memory in GB"
type = number
default = 16
}
variable "subnet_id" {
description = "Subnet OCID"
type = string
}
variable "assign_public_ip" {
description = "Assign public IP"
type = bool
default = false
}
variable "source_image_id" {
description = "Source image OCID"
type = string
}
variable "ssh_public_key" {
description = "SSH public key"
type = string
}
variable "boot_volume_size" {
description = "Boot volume size in GB"
type = number
default = 50
}
variable "create_data_volume" {
description = "Create additional data volume"
type = bool
default = false
}
variable "data_volume_size" {
description = "Data volume size in GB"
type = number
default = 100
}
variable "tags" {
description = "Freeform tags"
type = map(string)
default = {}
}modules/compute/outputs.tf:
output "instance_id" {
description = "Instance OCID"
value = oci_core_instance.this.id
}
output "private_ip" {
description = "Private IP address"
value = oci_core_instance.this.private_ip
}
output "public_ip" {
description = "Public IP address"
value = oci_core_instance.this.public_ip
}
output "instance_state" {
description = "Instance state"
value = oci_core_instance.this.state
}Using the Module
module "web_server" {
source = "../../modules/compute"
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
instance_name = "web-server-01"
shape = "VM.Standard.E4.Flex"
ocpus = 2
memory_in_gbs = 16
subnet_id = module.networking.public_subnet_id
assign_public_ip = true
source_image_id = data.oci_core_images.oracle_linux.images[0].id
ssh_public_key = var.ssh_public_key
boot_volume_size = 100
create_data_volume = true
data_volume_size = 200
tags = {
Environment = "Production"
Application = "WebServer"
ManagedBy = "Terraform"
}
}Common Patterns
Three-Tier Architecture
# VCN and Networking
module "networking" {
source = "./modules/networking"
compartment_id = var.compartment_id
vcn_cidr = "10.0.0.0/16"
vcn_name = "three-tier-vcn"
public_subnet_cidr = "10.0.1.0/24"
app_subnet_cidr = "10.0.2.0/24"
db_subnet_cidr = "10.0.3.0/24"
}
# Web Tier (Public)
module "web_servers" {
source = "./modules/compute"
count = 2
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[count.index % 2].name
instance_name = "web-${count.index + 1}"
subnet_id = module.networking.public_subnet_id
assign_public_ip = true
source_image_id = data.oci_core_images.oracle_linux.images[0].id
ssh_public_key = var.ssh_public_key
}
# App Tier (Private)
module "app_servers" {
source = "./modules/compute"
count = 3
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[count.index % 2].name
instance_name = "app-${count.index + 1}"
subnet_id = module.networking.app_subnet_id
assign_public_ip = false
source_image_id = data.oci_core_images.oracle_linux.images[0].id
ssh_public_key = var.ssh_public_key
}
# Database
module "database" {
source = "./modules/database"
compartment_id = var.compartment_id
db_name = "proddb"
admin_password = var.db_admin_password
subnet_id = module.networking.db_subnet_id
cpu_core_count = 2
storage_in_tbs = 1
}Conditional Resource Creation
resource "oci_core_instance" "app_server" {
count = var.create_instance ? 1 : 0
# configuration...
}
resource "oci_load_balancer_load_balancer" "app_lb" {
count = var.environment == "prod" ? 1 : 0
# configuration...
}Dynamic Blocks
resource "oci_core_security_list" "app_sl" {
compartment_id = var.compartment_id
vcn_id = oci_core_vcn.main.id
dynamic "ingress_security_rules" {
for_each = var.allowed_ingress_ports
content {
protocol = "6"
source = "10.0.0.0/16"
source_type = "CIDR_BLOCK"
stateless = false
tcp_options {
min = ingress_security_rules.value
max = ingress_security_rules.value
}
}
}
}State Management
Workspaces
# Create workspace
terraform workspace new prod
# List workspaces
terraform workspace list
# Switch workspace
terraform workspace select prod
# Show current workspace
terraform workspace showImport Existing Resources
# Import VCN
terraform import oci_core_vcn.main ocid1.vcn.oc1..aaaa...
# Import instance
terraform import oci_core_instance.web ocid1.instance.oc1..aaaa...
# Import subnet
terraform import oci_core_subnet.public ocid1.subnet.oc1..aaaa...Terraform Commands
Common Workflow
# Initialize
terraform init
# Validate configuration
terraform validate
# Format code
terraform fmt -recursive
# Plan changes
terraform plan -out=tfplan
# Apply changes
terraform apply tfplan
# Show current state
terraform show
# List resources
terraform state list
# Destroy resources
terraform destroyTargeted Operations
# Plan specific resource
terraform plan -target=module.web_server
# Apply specific resource
terraform apply -target=module.web_server
# Destroy specific resource
terraform destroy -target=module.web_serverState Operations
# Show resource
terraform state show oci_core_instance.web
# Move resource
terraform state mv oci_core_instance.old oci_core_instance.new
# Remove resource from state
terraform state rm oci_core_instance.old
# Pull remote state
terraform state pull > terraform.tfstate.backup
# Push state
terraform state push terraform.tfstateBest Practices
1. Version Control
terraform {
required_version = "~> 1.5"
required_providers {
oci = {
source = "oracle/oci"
version = "~> 5.20"
}
}
}2. Use Variables
# Good
cidr_block = var.vcn_cidr
# Avoid
cidr_block = "10.0.0.0/16"3. Output Important Values
output "vcn_id" {
description = "VCN OCID"
value = oci_core_vcn.main.id
}
output "load_balancer_ip" {
description = "Load balancer public IP"
value = oci_load_balancer_load_balancer.app_lb.ip_addresses[0].ip_address
sensitive = false
}4. Use Locals for Computed Values
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform"
CostCenter = var.cost_center
}
instance_count = var.environment == "prod" ? 3 : 1
db_name = "${var.project_name}-${var.environment}-db"
}5. Implement Lifecycle Rules
resource "oci_core_instance" "web" {
# configuration...
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [
metadata["ssh_authorized_keys"],
source_details[0].source_id
]
}
}6. Use Data Sources
# Instead of hardcoding image OCID
data "oci_core_images" "latest_ol8" {
compartment_id = var.compartment_id
operating_system = "Oracle Linux"
operating_system_version = "8"
sort_by = "TIMECREATED"
sort_order = "DESC"
}
resource "oci_core_instance" "web" {
source_details {
source_id = data.oci_core_images.latest_ol8.images[0].id
}
}7. Tag Everything
freeform_tags = merge(
local.common_tags,
{
Name = "web-server-01"
Role = "WebServer"
}
)8. Use Remote State
data "terraform_remote_state" "networking" {
backend = "http"
config = {
address = "https://objectstorage.../networking/terraform.tfstate"
}
}
resource "oci_core_instance" "app" {
subnet_id = data.terraform_remote_state.networking.outputs.app_subnet_id
}Troubleshooting
Common Issues
Issue: 409 Conflict - Resource already exists Solution: Import existing resource or use different name
Issue: Service limit exceeded Solution: Request service limit increase or clean up unused resources
Issue: Authentication error Solution: Verify API key configuration and permissions
Issue: Terraform state lock Solution: Force unlock (use with caution)
terraform force-unlock LOCK_IDDebug Mode
# Enable debug logging
export TF_LOG=DEBUG
export TF_LOG_PATH=./terraform-debug.log
terraform apply