Terraform on OCI: the provider, Resource Manager and whether to run your own pipeline
Oracle ships a managed Terraform service that removes the backend and the runner. Here is when it is the right call, when to run your own pipeline, and the OCI-specific things that catch people.
The oci Terraform provider is complete and well maintained — most OCI features arrive in it quickly, and the resource names map cleanly onto the API. The interesting decision is not whether to use Terraform but where to run it, because OCI is the one cloud that ships a genuinely usable managed Terraform service.
Resource Manager, and when it is the right answer
OCI Resource Manager runs Terraform for you: it stores state, executes plans and applies, holds variables, and integrates with OCI IAM so a stack is a resource with policies like anything else.
Take it when:
- You do not already have a CI/CD platform you are happy with. Resource Manager removes the backend bucket, the locking, the runner and the credential problem in one go.
- Your infrastructure is OCI-only. There is no benefit to a managed service for one cloud if half your infrastructure is elsewhere.
- You want private access to resources in a VCN during apply. Private endpoints for Resource Manager let a stack reach a private Kubernetes API or a database without a runner in the VCN.
- You want the plan and apply history to be an auditable OCI resource rather than a CI log that rotates out.
Run your own pipeline when:
- You manage other providers alongside OCI — DNS, GitHub, another cloud. Splitting Terraform across two execution models for one estate costs more than it saves.
- You want policy checks (
checkov,conftest), custom testing or plan output posted to a pull request as part of the review. Resource Manager's workflow is stack-oriented rather than pull-request-oriented, and that mismatch is the most common reason teams move off it.
Either way, the state layout is the same principle as everywhere else: one state per compartment per layer, split by blast radius and rate of change, as in the AWS Terraform piece. If you run your own, use Object Storage for the backend with versioning enabled.
Authentication, without API keys
The pattern to aim for: no API signing key in a config file anywhere.
- Resource Manager authenticates as the stack's own principal. Grant it via a policy scoped to the compartment it manages.
- A self-managed runner on an OCI compute instance uses an instance principal via a dynamic group. Configure the provider with
auth = "InstancePrincipal"and there is no key. - A runner outside OCI — GitHub Actions, GitLab — uses an OCI user with an API key, which is the case where a key is still unavoidable. Scope that user tightly, rotate it on a schedule you actually run, and store it in your CI's secret store.
- Humans use
oci session authenticatefor a token-based session rather than a long-lived key on their laptop.
This is the same argument as OCI policies and dynamic groups: the long-lived key is the credential that leaks, so the goal is to have as few as possible.
Provider specifics that catch people
- OCIDs everywhere. Nearly every resource reference is an OCID, and they are long, opaque and easy to paste wrong. Use data sources and outputs rather than hardcoding them, and never copy an OCID between environments.
- The
compartment_idon almost every resource. Pass it as a variable per layer rather than repeating it, and remember that moving a resource between compartments is an update in some services and a recreate in others. - Defined tags need the namespace to exist first. Create the tag namespace and tag defaults in an early layer, or every subsequent apply fails on a missing namespace.
- Availability domain names are tenancy-specific.
AD-1in your tenancy is not the same physical AD as in someone else's. Always look them up with theoci_identity_availability_domainsdata source rather than hardcoding. - Service limits are per compartment and per region and a raise is a support request with a lead time. An apply that fails on a limit during a migration weekend is avoidable by checking first.
- Some resources take a long time. DRG attachments, FastConnect and database provisioning are minutes, not seconds. Set generous timeouts rather than assuming a hang.
The pipeline shape
Whichever runner you choose: format and validate, a security scan of the plan, plan reviewed by a human, apply from the saved plan, and no human with write access to production outside a break-glass path. Add a scheduled drift plan — a weekly plan that reports non-empty diffs is how you find the resources someone changed in the console, which every estate has.
We set this up alongside the compartment structure at the start of an OCI engagement, because policies and tag namespaces need to exist before workloads start landing.
What to do this week
Search your repositories and CI configuration for OCI API signing keys — a .pem file or a key_file entry in a config. Each one is a credential with no expiry. The ones used by runners inside OCI can be replaced with an instance principal this afternoon.