How to Use env0: The Beginner's Guide to Terraform Automation
CodexFuse Team · 2026-11-02T10:37:54.856Z · 18 min read min read
This env0 tutorial is aimed at platform engineers and DevOps beginners who already know basic Terraform and want to stop running applies from their laptops. If you manage infrastructure with Terraform, you know the painful middle part: someone runs terraform apply from their laptop, the state file lives in a folder nobody fully trusts, and a manual change in the cloud console drifts silently until it breaks something at 2 AM. Learning how to use env0 is how platform teams end that era. env0 (branded "env zero") is an infrastructure-as-code automation platform: it runs your Terraform and OpenTofu plans and applies for you, in a governed pipeline, with pull-request plans, drift detection, and approval policies built in. Think of it as CI/CD specifically for your IaC. If you are new to the tool it automates, start with our Terraform beginner guide first; everything below assumes you know what a Terraform plan and a state file are.
What Is env0, Exactly?
env0 is a SaaS control plane that takes your Terraform or OpenTofu code from a Git repository and runs the whole deployment lifecycle: init, plan, apply, and destroy — with policies, approvals, and drift detection around each step. You stop running Terraform from laptops and start deploying environments from a template, exactly the way CI/CD pipelines deploy application code.
The platform's glossary defines the two concepts you must learn first, and the relationship is simple: a template is the reusable recipe; an environment is one live deployment of it. A template is, in the docs' words, "a reusable configuration that links a VCS repository folder to an IaC type (Terraform, OpenTofu, Pulumi, etc.), along with variables, deployment settings, and project assignments." An environment is "a live deployment of a template with its own state, variables, and deployment history. Each environment corresponds to a single Terraform state file. Equivalent to a workspace in Terraform Cloud." One template ("our web app stack") can produce many environments (dev, staging, prod) — each with its own state file, its own variables, and its own deployment history.
Templates are also the unit of governance: approval policies, custom flows, and variable defaults are all applied at the template level, so every environment spawned from it inherits the same guardrails.
How Do Templates and Environments Actually Work?
Templates and environments relate the way a class relates to an instance. You write the Terraform once, wrap it in a template that says where the code lives and which variables it needs, and then every team member can click a button to spin up an environment — a full, isolated, state-tracked deployment — without touching the Terraform CLI.
In practice the flow looks like this: a platform engineer creates one template pointing at the terraform/ folder of the app repository, declares variables like region and instance_type, and assigns it to a project. Developers then create environments from that template for their feature branches. Each environment runs in env0's managed runners (or self-hosted agents on your own network), the state file is stored and locked by the platform, and every deployment — plan, apply, destroy — is logged with who triggered it and why. The beginner's lesson to internalize: the template is where governance lives, the environment is where infrastructure lives, and you never mix the two up again.
How Do You Create Your First env0 Template?
Creating a template is mostly pointing: point env0 at your code, tell it which IaC tool to use, and declare the variables. The env0 Terraform template setup (verified against the docs on 2026-11-02) runs like this. First, sign up at envzero.com and connect your version control — for GitHub this installs the env zero GitHub App on your organization through a popup, which is how env0 gets read access to your Terraform folders and how pull-request plans get posted back as checks. Our Git beginner guide covers the repository concepts if the terms branch and pull request feel new.
Then open the Templates screen from the Organization menu and click CREATE NEW TEMPLATE. You enter the repository URL, a branch or tag name (leaving it empty tracks the default branch), and the path to the root directory of your IaC files (empty means the repository root). Next you choose the template type: Terraform/OpenTofu (needs .tf files in the repo), Terragrunt, Pulumi, or Ansible — either the terraform or the tofu executable handles the deployment, depending on the type you select.
Then comes the IaC version, and this is where env0 is more careful than most wrappers. You can pin the exact binary version three ways, and they resolve in this order: environment variables first, then version files, then the template settings UI.
| Resolution step | How you set it | Example |
|---|---|---|
| 1. Environment variable | Set ENV0_TERRAFORM_VERSION or ENV0_OPENTOFU_VERSION on the template | ENV0_OPENTOFU_VERSION=1.10.6 |
| 2. Version file | Commit a file in the repo root | .opentofu-version containing 1.10.6 |
| 3. Template settings UI | Pick from the dropdown, or "Resolve from code" | Reads required_version from your Terraform block |
Two details worth knowing: "Resolve from code" reads required_version straight from your configuration, and the special value "Latest" is capped for Terraform — "Latest version up to 1.5.x" — while for OpenTofu "Latest" genuinely means the latest available version. After the type and version, the Variables tab is where you declare environment and Terraform variables; by default, environments inherit variables set at the organization level, and you can override or add new ones per template. Finally you assign the template to one or more projects, and it becomes available for anyone in those projects to deploy from.
How Do You Deploy Your First Environment?
Deploying an environment is a two-click affair with a plan gate in the middle: pick the template, give the environment a name and variables, and hit deploy. env0 runs init, then a full plan, shows you the plan output, and — depending on the template's approval settings — either applies automatically or waits for a reviewer to approve the plan first.
That plan gate is the whole point of the platform. When you applied from your laptop, the plan scrolled past in your terminal and vanished. In env0 the plan is a first-class artifact: it is stored with the deployment, it can be commented on, and the apply cannot start until the plan is approved. For a first deployment, point the template at a small, disposable stack — a test VPC or a single server — so you can watch the whole cycle (plan, approve, apply, verify, destroy) without risking anything real. If the concept of a server you rent by the hour is new, our what is VPS hosting explainer covers the infrastructure you are about to provision.
Once the first environment is green, the mental model clicks: every future change is a new deployment of the same environment, every deployment leaves a history, and the state file is something you never have to think about again.
What Happens When You Open a Pull Request?
Every pull request against your IaC repository gets an automatic dry-run plan, before anything merges. The docs define it plainly: a plan is "a dry run that shows what infrastructure changes would be made without applying them. Plans are run automatically on pull requests (Plan on PR) and before every apply."
This changes the code-review dynamic completely. Reviewers no longer have to imagine what terraform plan would do — the plan output is posted directly on the pull request as a check, showing resources to add, change, and destroy. A reviewer can see that a one-line variable change would replace a database before approving, instead of after. Merging the PR is what triggers the real deployment to the environment tracking that branch (for example, the staging environment follows main), which means your IaC repository becomes the single source of truth in the most literal sense. The GitHub Actions-style mental model helps here — if you have used CI for application code, our GitHub Actions beginner guide explains the pull-request automation pattern that env0 applies to infrastructure.
Can You Add Custom Steps Around Terraform?
Yes — custom flows let you run your own commands at named hooks during the deployment. Create a file named env0.yml (or env0.yaml — both suffixes work) inside the template folder of your Git repository, and env0 will pick it up automatically. For sharing across templates, the same file under the repository root applies to everything.
Hooks can run before or after Terraform init, plan, and apply, as well as on destroy, on error, and on ad-hoc tasks; the default shell is sh, switchable to bash. The documented example hooks include deploy.steps.setupVariables.after, terraformInit, and terraformOutput. A minimal pattern following the docs looks like this:
deploy:
steps:
setupVariables:
after:
- run:
name: validate required secrets are set
command: ./scripts/check-secrets.sh
terraformInit:
after:
- run:
name: fetch shared modules
command: ./scripts/fetch-modules.sh
If your custom step needs extra CLI tools inside the deployment container, set the ENV0_INSTALLED_TOOLS environment variable with a comma-separated list of tool names instead of installing them in a hook. Keep custom flows thin — every line you add is a line your Terraform no longer fully describes, so reserve hooks for validation, notification, and glue, not for infrastructure changes.
How Does env0 Detect Drift?
Drift — when the real cloud quietly stops matching your Terraform code — is caught by scheduled plan-analysis jobs. env0 schedules deployment tasks that end by analyzing the Terraform plan output, so a plan that shows changes nobody committed is the signal that something was edited by hand in the console.
Setup is one cron expression per environment: in the environment's Settings tab, under Drift Detection, you add a schedule such as 00 10,19 * * * for twice-daily checks at 10 AM and 7 PM. That schedule is the core of env0 drift detection — the platform runs the plan analysis for you instead of relying on someone remembering to check. When drift is found, the environment's drift status flips to "Drifted" (or "Error"), with a link to the drift-detection deployment logs, and notifications fire through Slack, Microsoft Teams, email, or webhooks configured at the project level. Running a new deployment resets the status, because the state and the code agree again.
Finding drift is only half the feature — the remediation policy decides what happens next, and it is set at the project level so new environments inherit it:
| Remediation option | What env0 does when drift is found |
|---|---|
| Disabled | Nothing automatic; a human reviews and fixes it manually (manual remediation is always available regardless of this setting) |
| Deploy code changes to the cloud | Automatically runs an env0 deployment with the latest VCS config, re-applying your code over the drift |
| Create a pull request for manual changes | If the drift looks like a manual cloud edit, opens a PR in the connected VCS so the change can be reviewed and adopted into code |
| Hybrid | Opens a PR for manual cloud modifications, otherwise deploys the code changes to the cloud |
The beginner takeaway: start with Disabled or Hybrid while you learn what is drifting and why. Full auto-remediation is powerful only after your approvals are trustworthy, because — as the docs note — "the execution of any automatic remediation is subject to your project's approval policies."
How Do Approval Policies and OPA Work in env0?
Approval policies are gates between the plan and the apply, and env0 enforces them with the Open Policy Agent engine. Each env0 approval policy is written as Rego files stored in a repository (not necessarily the repo being deployed), and you can assign multiple policies to a template or a project. During deployment, after the plan and cost-estimation steps, a policy-approval step runs: the deployment may continue, wait for further approval, or get canceled, according to the policy output.
The practical effect is visible in the UI: templates and projects with approval policies get the "Approve plan automatically" checkbox disabled, which means every apply waits for a human (or a passing policy) first. The platform's glossary describes the manual side as "a rule requiring one or more reviewers to approve the plan output before apply runs. Applied at the template or project level. The deployment pauses after the plan step and resumes only after all required approvals are given." On the automated side, the vendor's OPA tutorial shows Rego policies like requiring at least two approvers (count(input.approvers) < 2 marks a deployment pending), cost thresholds (block plans estimated over $100), and plan-size limits (block deployments changing more than N resources). Start with one simple policy — for example, every production environment needs one reviewer — and add cost or resource limits only after the team is comfortable with the flow.
Does env0 Support OpenTofu?
Yes, fully — env0 OpenTofu support makes it a first-class template type, not an afterthought. When you create or edit a template you select OpenTofu as the IaC type, and the tofu executable handles the deployment instead of terraform. The vendor presents it as a drop-in migration with no code changes required, and it has been generally available since January 2024, with CI testing support via tofu test.
Version pinning follows the same three-step resolution as Terraform: set ENV0_OPENTOFU_VERSION, or commit a .opentofu-version file, or pick in the template settings UI — or choose "Resolve from code" to read required_version from your configuration. A minimal version file is exactly what it sounds like:
1.10.6
One asymmetry to remember from the version table above: for OpenTofu, "Latest" means the latest available version, while for Terraform "Latest" is capped at 1.5.x — a leftover of the licensing split that sent many teams to OpenTofu in the first place.
How Much Does env0 Cost?
env0's pricing is refreshingly simple to start with and deliberately vague at the top end. The numbers below are snapshots from the official env0 pricing page on 2026-11-02; they move, so check the page before budgeting.
| Tier | Price | What you get |
|---|---|---|
| Free | $0/month, free forever | 250 runs per month, up to 30 active environments, unlimited users, one self-hosted agent, all Cloud Navigator features, community support |
| Cloud Navigator | Custom quote — "Priced Per Successful Apply or Environment" | Everything in Free, plus unlimited monthly runs, up to 100 active environments, unlimited concurrent deployments with no per-run time limit, unlimited self-hosted agents |
| Cloud Pilot | Custom quote — "Priced Per Successful Apply or Environment" | Everything in Cloud Navigator, plus Cloud Analyst (AI-powered insights, agent, and dashboards) |
The run accounting is friendlier than it looks: "A run is one successful deploy, destroy, or drift detection. Plans, pull request plans, dry runs, tasks, module tests, and failed or cancelled runs do not count against the cap." That means your PR plans — the feature you will use most as a beginner — are free in the accounting sense. When a Free plan hits 250 runs in a month, scheduled runs such as TTL destroys and drift detection are simply skipped until the next cycle. Two cautions: the paid tiers publish no entry price, only custom quotes, so ignore third-party pages listing scraped figures (one aggregator showed conflicting "$250" and "$5,000" numbers — the official page shows only Free plus quotes); and "per successful apply or environment" means failed deploys do not burn your budget.
env0 vs Terraform Cloud: What Is the Difference?
Say it once and keep it straight: env0 is not Terraform Cloud (now called HCP Terraform). They are different products from different companies — env0, Inc. versus HashiCorp (acquired by IBM in 2025) — solving the same problem: running Terraform safely in teams.
The docs themselves draw the closest parallel: an env0 environment is "equivalent to a workspace in Terraform Cloud," its remote backend is "a drop-in replacement for Terraform Cloud's remote backend" requiring no backend-block changes during migration, and its configuration sets are "equivalent to variable sets in Terraform Cloud." The practical differences, per a competitor's comparison (Spacelift's blog, fetched 2026-11-02 — treat vendor-adjacent claims accordingly):
| Dimension | env0 | HCP Terraform (Terraform Cloud) |
|---|---|---|
| Ecosystem focus | Multi-IaC: Terraform, OpenTofu, Terragrunt, Pulumi, CloudFormation, Kubernetes, Ansible | Terraform-only |
| Free tier | Free forever: 250 runs/month, 30 environments, unlimited users | RUM-based pricing (Essentials $0.10, Standard $0.47, Premium $0.99 per managed resource/month) |
| Policy engine | Native OPA (Rego) with a ready-to-use policy catalog | Sentinel plus OPA |
| Drift handling | Scheduled drift detection with optional auto-remediation (auto-deploy, PR, or hybrid) | Health assessments on Standard/Premium tiers |
| Hosting | SaaS control plane, optional self-hosted agents | SaaS control plane, optional self-hosted agents; fully self-hosted Terraform Enterprise also available |
The beginner's decision rule: if your team is Terraform-only and already standardized on HashiCorp tooling, HCP Terraform is the native fit; if you run OpenTofu, Terragrunt, or a mix — or you want the generous free tier while learning — env0's multi-IaC platform is the easier door in. (Crossplane, queued as a separate topic in this series, is a different beast entirely: it reconciles desired state through Kubernetes operators rather than running plan/apply pipelines — draw that line once and keep it drawn.)
7 Beginner Mistakes That Break env0 Deployments
| # | Mistake | What goes wrong | The fix |
|---|---|---|---|
| 1 | Pointing the template at the repo root instead of the IaC folder | env0 tries to plan the whole repository, including unrelated code | Set the Terraform Folder to the exact directory containing your .tf files |
| 2 | Leaving "Latest" Terraform selected for a 1.6+ codebase | Deploys run on Terraform 1.5.x and fail on newer syntax | Pin via ENV0_TERRAFORM_VERSION, a .terraform-version file, or "Resolve from code" |
| 3 | Skipping the GitHub App install step | No pull-request plans, no merge-triggered deploys — half the platform silently missing | Complete the App installation on your org before creating the first template |
| 4 | Putting secrets in Terraform variables instead of the secrets store | Values appear in plan output and deployment logs | Use env0's variables/secrets management; keep secrets out of .tf and .tfvars |
| 5 | Turning on drift auto-remediation on day one | An unexpected redeploy overwrites a change someone made deliberately | Start with Disabled or Hybrid; graduate to auto-deploy after approvals are trusted |
| 6 | Treating env0 like a laptop with a UI | Custom flows grow into shadow infrastructure that Terraform no longer describes | Keep env0.yml hooks to validation, notifications, and glue only |
| 7 | Assuming the free tier counts PR plans against the 250 runs | Teams ration pull requests out of phantom budget fear | Plans, PR plans, dry runs, and failed runs do not count — only successful deploys, destroys, and drift detections |
Sources
The facts in this guide were verified against these sources on 2026-11-02: env0's documentation — glossary (template/environment/plan/approval definitions), templates guide (creation flow, variables, IaC types), IaC binaries versions (version resolution order, 1.5.x cap), custom flows (env0.yml hooks, ENV0_INSTALLED_TOOLS), drift detection (cron schedules, notifications, statuses), drift remediation policy (Disabled/auto-deploy/PR/hybrid), approval policies (OPA/Rego, plan gate, assignment); the official pricing page and subscription tiers (Free tier numbers, run definition, custom-quote tiers); the OPA tutorial (Rego approver/cost/plan examples); OpenTofu alpha announcement and OpenTofu GA (template-type support timeline); Spacelift's env0 vs Terraform Cloud comparison (competitor-authored — dimensions and HCP Terraform figures, used with that caveat); terraform-provider-env0 v1.24.4 (provider reference); env0's GitHub organization (terratag: 1,058 stars, MPL-2.0 — snapshot, moves).
Frequently Asked Questions
Is env0 free?
Yes — the Free tier is free forever at $0/month, with 250 runs per month, up to 30 active environments, unlimited users, and one self-hosted agent. A run means one successful deploy, destroy, or drift detection; plans, pull-request plans, dry runs, and failed runs do not count. If you hit the 250-run cap, scheduled runs like drift detection are skipped until the next cycle. Paid tiers (Cloud Navigator and Cloud Pilot) are custom-quoted per successful apply or environment.
Is env0 the same as Terraform Cloud?
No. env0 (env0, Inc.) and Terraform Cloud — now called HCP Terraform, from HashiCorp/IBM — are separate products. An env0 environment is equivalent to a Terraform Cloud workspace, and env0's remote backend can replace Terraform Cloud's remote backend without changing your backend block. The biggest practical difference: env0 supports multiple IaC tools (Terraform, OpenTofu, Terragrunt, Pulumi, Ansible), while HCP Terraform is Terraform-only.
Does env0 work with OpenTofu?
Yes — OpenTofu is a first-class template type, generally available since January 2024. Select OpenTofu when creating the template and the tofu executable handles deployments. Pin versions with ENV0_OPENTOFU_VERSION, a .opentofu-version file, or the template settings UI, and note that for OpenTofu "Latest" really means the latest version (for Terraform it is capped at 1.5.x).
Do I still need a separate CI server with env0?
For infrastructure, no. env0 replaces the DIY Jenkins/GitHub Actions pipeline most teams build around terraform plan and terraform apply: it runs plans on every pull request, gates applies behind approvals or OPA policies, stores state, and detects drift. You still keep your application CI for building and testing code — env0 is CI/CD specifically for your infrastructure as code.
Can env0 automatically fix drift?
It can, but you choose the behavior per project: do nothing (Disabled), automatically redeploy your code over the drift, open a pull request for manual cloud changes, or a hybrid of the two. Automatic remediation is always subject to your project's approval policies, and the safe beginner move is Disabled or Hybrid until you trust the approvals.
