Skip to content
Français
Français
medium

67 free Terraform Professional practice labs

2 min read

67 hands-on labs to practise for the HashiCorp Certified: Terraform Authoring and Operations Professional, roughly 63 hours of work, each one graded on the state of your machine rather than on the commands you typed. They run on your own hardware with the `dsoxlab` command line, and cost nothing.

The level above, and this one is hands-on: writing reusable modules, managing shared state, and operating Terraform inside a delivery pipeline.

  • 67labs
  • 63hours of practice

Levels 43 intermediate 24 advanced

Official exam objectives published by HashiCorp

These are not exam questions. They are hands-on exercises on the skills the exam measures, graded on the state of your machine.

Terraform, Associate and Professional

67 labs every lab replayed and scored

Add this catalogue dsoxlab catalog add https://github.com/stephrobert/terraform-dsoxlab-training

Writing Terraform code

  • Explicit source and provider alias

    Declare providers correctly: an explicit source address that resolves to registry.terraform.io/hashicorp/random, a second configuration of the same provider distinguished by an alias, and a resource wired to it with provider =. Proven by version -json and the plan JSON provider_config. Associate 5b.

    dsoxlab start write-code-providers

    35m intermediate shell Companion guide (French)

  • Read a resource's lifecycle in the plan

    Build four resources ordered only by references, then prove in the plan JSON the four lifecycle operations: update in place, replace, create before destroy, and destroy. Pro objective 1c.

    dsoxlab start write-code-declare-resources

    45m intermediate shell Companion guide (French)

  • Variables typing, validation and precedence

    Type variables correctly and master their traps: a map of objects with optional() defaults, a validation rule that rejects before any provider, an explicit null that falls back to the default with nullable=false, the real source precedence (auto.tfvars over TF_VAR_, -var above all), and sensitive as a display mask, not a state protection. Associate 2e plus 2f.

    dsoxlab start write-code-variables

    45m intermediate shell Companion guide (French)

  • The secret the output does not hide

    Master the real output block: a type constraint (object), sensitivity propagation (an output referencing a secret must be sensitive, and sensitive is only a display mask, cleartext stays in state, -json and -raw), nonsensitive() to expose a hash deliberately, and a precondition that fails the plan. Associate 2e plus 2f.

    dsoxlab start write-code-outputs

    45m intermediate shell Companion guide (French)

  • The local that is not resolved at plan time

    Centralize expressions in locals blocks: normalize with HCL functions, keep a ternary typed, generate a list with a for expression, derive from a resource attribute (known after apply), and inherit a variable's sensitivity. Pro objective 2c.

    dsoxlab start write-code-locals

    45m intermediate shell Companion guide (French)

  • When exactly does Terraform read a data source?

    Build three data sources whose read timing is deliberate: one read during the plan, one deferred to the apply because the resource it depends on is changing, and one carrying an explicit depends_on that does NOT defer it. Prove each case in the plan JSON. Pro objective 2b.

    dsoxlab start write-code-data-sources

    45m intermediate shell Companion guide (French)

  • What expressions really compute

    Write correct Terraform expressions: reference a managed resource with no prefix, know that == does not convert types (so 3 is not "3") while arithmetic does, respect operator precedence, and use null to omit an argument rather than an empty string. Associate 2e.

    dsoxlab start write-code-expressions

    30m intermediate shell Companion guide (French)

  • Compose values with HCL functions

    Deduplicate a collection for for_each, handle out-of-range element(), lookup() fallback, ceil() rounding, template escaping and a provider-defined function. Pro objective 2c.

    dsoxlab start write-code-functions

    45m intermediate shell Companion guide (French)

  • Provider-defined functions

    Use functions exposed by a provider with the provider:: syntax. Pro objectives 2c and 5a.

    dsoxlab start write-code-provider-defined-functions

    30m intermediate shell Companion guide (French)

  • The configuration that refuses absurd values

    Compute values with conditional expressions, then place each guard at the right level: validation, precondition, postcondition and check block. Pro objective 2a.

    dsoxlab start write-code-conditionals

    45m intermediate shell Companion guide (French)

  • Custom conditions: precondition, postcondition and check blocks

    Validate a configuration with the language features designed for it. Pro objective 2a.

    dsoxlab start write-code-validation-check-preconditions

    30m intermediate shell Companion guide (French)

  • count indexes by position, and the position lies

    Choose count or for_each per resource and prove it: index a set by name with for_each, migrate a count resource to for_each with no destroy using moved blocks, keep count for interchangeable copies, and expose a conditional resource with one(). Associate objective 4b plus the Professional moved migration.

    dsoxlab start write-code-count

    45m intermediate shell Companion guide (French)

  • Add an instance without destroying the others

    Migrate count to for_each with moved blocks on an already applied configuration, then add a service proving zero destruction. Pro objective 2d.

    dsoxlab start write-code-for-each

    45m intermediate shell Companion guide (French)

  • Transform a catalog with for expressions

    Derive four collections from a single map of servers with for expressions: a filtered tuple, an object grouped by role with the ellipsis, a flattened two-level cross, and a filtered for_each. Avoid the splat-on-a-map trap. Pro objective 2c.

    dsoxlab start write-code-for-loops

    45m intermediate shell Companion guide (French)

  • Generate blocks, and know when not to

    Generate cloudinit parts with a dynamic block filtered in for_each and named from the key, keep the fixed part literal, and hit the wall: a lifecycle meta-argument block cannot be generated by dynamic. Pro objective 2d.

    dsoxlab start write-code-dynamic-blocks

    45m intermediate shell Companion guide (French)

  • depends_on belongs only where a reference cannot go

    Remove a redundant depends_on that a reference already covers, replace a hardcoded path with a reference, keep the one depends_on nothing else can express, and prove the graph in the plan JSON. Pro objective 2d.

    dsoxlab start write-code-depends-on

    45m intermediate shell Companion guide (French)

  • The lifecycle block decides the order, not you

    Set create_before_destroy and watch its propagation go down to dependencies, hit the documented limit of prevent_destroy, scope ignore_changes to a single attribute, trigger a replacement from a bare value through terraform_data, and reject an invalid input at plan time. Pro objective 2d.

    dsoxlab start write-code-lifecycle

    45m intermediate shell Companion guide (French)

  • The typo that breaks nothing

    Two tfvars traps: an undeclared variable in a .tfvars is only a warning, so the real variable silently stays at its default (fix the typo), and terraform.tfvars.json outranks terraform.tfvars (a distinct precedence level). Associate 3c.

    dsoxlab start write-code-tfvars-files

    25m intermediate shell Companion guide (French)

  • Version constraints and the lock file

    Write correct version constraints: a literal required_version (the terraform block accepts no variable), an exact provider pin that resolves to that version, and the pessimistic ~> that allows 3.x but not 4.0. Proven by version -json and the h1 hashes of the lock file. Associate 3a.

    dsoxlab start write-code-version-constraints

    30m intermediate shell Companion guide (French)

  • The config that works but no CI accepts

    Take a working but non-conforming config and make it CI-ready: pass terraform fmt, fix the orphan reference that breaks validate, rename resources to snake_case, type and describe variables and outputs, mark the token sensitive, type the number output (1.15), and write a .gitignore that excludes state but keeps the lock file. Associate 2a plus 2e.

    dsoxlab start write-code-style-guide

    40m intermediate shell Companion guide (French)

  • When sensitivity breaks for_each

    A side effect of sensitive rarely taught: a sensitive value cannot be a for_each key (Invalid for_each argument), so you must iterate over a non-sensitive set. The contaminated resource attribute is flagged in sensitive_values, and a hash is exposed with nonsensitive(). Professional 2f.

    dsoxlab start write-code-sensitive-data-sensitive-values

    30m intermediate shell Companion guide (French)

  • The value that never touches the state

    Declare an ephemeral value that is generated during the run but never written to the state or plan: the ephemeral block (random 3.7+), the contrast with a persisted random_password, exposing it safely at the root with ephemeralasnull(), and the two errors it triggers when leaked. Professional 2f.

    dsoxlab start write-code-sensitive-data-ephemeral-values

    35m intermediate shell Companion guide (French)

  • Write-only arguments: a secret that never lands in the state

    Send a secret to the provider without ever persisting it in the Terraform state, using write-only arguments against a local AWS emulator.

    dsoxlab start write-code-sensitive-data-write-only-arguments

    30m intermediate shell Companion guide (French)

  • Read secrets from Vault

    Fetch secrets from HashiCorp Vault with the vault provider and consume them without freezing them in clear text in the state. Pro objective 2f.

    dsoxlab start write-code-sensitive-data-vault-secrets

    30m intermediate shell Companion guide (French)

Terraform state

  • Take over a secret already in service, without regenerating it

    A plain `apply` would draw a new password. Attach the existing one through an `import` block, then observe that the secret sits in clear text in the state while being marked `sensitive_attributes`: masking is a display, not encryption.

    dsoxlab start state-understand-state

    30m intermediate shell Companion guide (French)

  • Migrate the state without breaking its lineage

    A backend block accepts no named value. Move from an implicit local backend to a parameterised one through partial configuration and `-backend-config`, and prove the state migrated rather than being recreated: same `lineage`, both resources still managed.

    dsoxlab start state-backends

    30m intermediate shell Companion guide (French)

  • State locking, what it really blocks

    Measure the exact scope of the state lock on a local backend, and state what enables it on S3.

    dsoxlab start state-state-locking

    30m intermediate shell Companion guide (French)

  • terraform state list, the address is the identity

    Find the address of an instance when all you know is its real identifier, and count managed resources without being caught by a module.

    dsoxlab start state-terraform-state-list

    30m intermediate shell Companion guide (French)

  • terraform state show, and what the summary hides

    Extraire du state une valeur sensible et des attributs nuls, que la sortie humaine de state show caviarde ou omet.

    dsoxlab start state-terraform-state-show

    30m intermediate shell Companion guide (French)

  • terraform state mv and the moved block, refactor without destroying

    Reattach three existing objects to their new addresses, imperatively then declaratively, and prove nothing was recreated.

    dsoxlab start state-terraform-state-mv

    30m intermediate shell Companion guide (French)

  • terraform state rm and the removed block, stop managing without destroying

    Take two resources out of the state without deleting the files, and learn why a removed block destroys unless you write destroy = false.

    dsoxlab start state-terraform-state-rm

    30m intermediate shell Companion guide (French)

  • The removed block: bequeath an infrastructure without destroying it

    Take resources out of the state deciding for each whether the real object survives, and find where the removed block gives up. Pro objectives 1e and 4c.

    dsoxlab start state-removed-block

    40m intermediate shell Companion guide (French)

  • Restore an amputated state: pick the right backup, prove nothing was recreated

    A state rm went wrong and the backup was overwritten. Three candidate backups, one restorable, compared by lineage and serial, then pushed without touching the real files.

    dsoxlab start state-backup-restore-state

    40m intermediate shell Companion guide (French)

  • Diagnose a drift and adopt an orphan resource, without losing its value

    Prove a drift with a saved refresh-only plan, reconcile it, then adopt a pre-existing token with an import block, without Terraform regenerating it.

    dsoxlab start state-diagnose-state

    40m intermediate shell Companion guide (French)

Terraform modules

  • A reusable module configures no provider of its own

    Empty a child module of its provider configuration, have it declare the aliased configuration it expects, pass that configuration from the root, and instantiate the module three times with a single for_each.

    dsoxlab start modules-create-modules

    45m intermediate shell Companion guide (French)

  • Refactor a monolith into the standard module structure

    Split a single .tf file into the official layout, add a nested module called by relative path, a standalone example, and prove that override.tf is the one file name with a functional effect.

    dsoxlab start modules-module-structure

    45m intermediate shell Companion guide (French)

  • A module interface is a contract, not just types

    Make an object attribute optional, refuse an explicit null, reject an out-of-range value, gate an output behind a precondition, and re-export a secret without breaking the plan.

    dsoxlab start modules-module-variables-outputs

    45m intermediate shell Companion guide (French)

  • A local module is read in place, not installed

    Wire two root projects onto one shared local module, and prove from modules.json which folder each call really reads: relative path versus absolute path.

    dsoxlab start modules-module-local

    45m intermediate shell Companion guide (French)

  • A registry module is downloaded, versioned, and never locked

    Pin a registry module, resolve a flexible constraint, and prove from modules.json and the plan JSON which version got installed: the lock file never covers a module.

    dsoxlab start modules-module-registry

    45m intermediate shell Companion guide (French)

  • Publish and consume module versions with Git tags

    Publish three versions of a shared module, then consume them from three projects: an immutable reference, a minor tag and a major tag, with no version argument in sight.

    dsoxlab start modules-version-modules

    45m intermediate shell Companion guide (French)

  • Prove a module with terraform test, mutations included

    Write the .tftest.hcl suite of a module, covering its default, its options and its refusal of an invalid input: every behaviour is checked by mutating the module.

    dsoxlab start modules-test-module

    45m intermediate shell Companion guide (French)

  • Make a module composable, and prove it from the plan JSON

    Strip a legacy module of its own provider configuration, invert its dependency and document it, then read the proof in provider_config and module_calls.

    dsoxlab start modules-module-best-practices

    45m intermediate shell Companion guide (French)

  • Refactor a copy-pasted project without destroying anything

    Extract two copy-pasted resources into a typed module called once, and prove from the state identifiers that nothing was destroyed on the way.

    dsoxlab start modules-module-anti-patterns

    45m intermediate shell Companion guide (French)

Environments

  • Split a monolithic configuration, and prove the plan did not move

    Split an eighty-line main.tf into the official file layout, then prove by comparing two plans that nothing changed: a green validate proves nothing here.

    dsoxlab start environments-organize-terraform-repo

    40m advanced shell Companion guide (French)

  • Two roots, two states, one shared module

    Wire two root configurations onto one shared module with a partial backend, then prove by destroying dev that prod never moved.

    dsoxlab start environments-separate-environments

    45m advanced shell Companion guide (French)

  • Workspaces or separate configurations, and what the split costs

    Decide which parts still belong in workspaces, split the rest into two root configurations, and wire their dependency through terraform_remote_state without duplicating a value.

    dsoxlab start environments-when-to-use-workspaces

    50m advanced shell Companion guide (French)

  • Split a monorepo into two stacks that talk to each other

    Re-export a nested module output at the root, consume it from a downstream stack through terraform_remote_state, and keep the platform secret out of the shared state.

    dsoxlab start environments-monorepo-vs-repo-per-stack

    45m advanced shell Companion guide (French)

  • Run Terraform in automation (CI/CD)

    Build a non-interactive Terraform chain judged on exit codes alone, then record what a saved plan really freezes, what a lock does, and where a secret leaks.

    dsoxlab start environments-terraform-in-automation

    30m advanced shell Companion guide (French)

Terraform on AWS, via Floci

  • Compose the IAM chain, and name its two policies correctly

    `aws_iam_policy_document` is a LOCAL data source: it queries nothing, it builds JSON. Compose the policy, role, instance profile and instance chain, and prove in the structured state that the trust policy and the permissions take two distinct paths to the role.

    dsoxlab start aws-iam-role-policy-instance-profile

    30m advanced shell Companion guide (French)

  • A remote state, locked, and read by another stack

    Repair a trapped backend block, make the S3 lock actually effective, and have a second configuration consume the outputs without copying a single value.

    dsoxlab start aws-backend-s3-remote-state

    50m advanced shell Companion guide (French)

  • Read a replacement in the plan, before it happens

    An ASG referencing `version = "$Latest"` never triggers an instance refresh, and a `create_before_destroy` placed on the launch template protects nothing. Read both truths in the plan converted to JSON, without ever calling AWS.

    dsoxlab start aws-launch-template-autoscaling

    30m advanced shell Companion guide (French)

  • Import, moved and drift: the three traps a tutorial never shows

    Bring an EC2 instance created outside Terraform under its control, change its logical address without the real object being recreated, then reconcile a drift by ACCEPTING reality rather than overwriting it.

    dsoxlab start aws-import-moved-drift

    30m advanced shell Companion guide (French)

HCP Terraform

  • The run workflow: played in two steps, then qualified

    A run is a plan, then an apply of THAT plan. Reproduce it locally with saved plans, see what a stale plan and a frozen variable refuse, then qualify six described runs and put the eleven stages back in the order the documentation gives.

    dsoxlab start hcp-terraform-hcp-terraform-overview

    35m advanced shell Companion guide (French)

  • Workspaces: one word, two meanings, two attachment strategies

    A CLI workspace is one more state in the same directory; an HCP Terraform workspace is a unit of execution with its own variables, permissions and history. Repair two `cloud` blocks, attach one by name and the other by tags, and establish what `terraform validate` does not catch.

    dsoxlab start hcp-terraform-hcp-workspaces

    30m advanced shell Companion guide (French)

  • The stream a run sends back, and the three ways to start one

    What a CLI receives from a remote run is the structured stream `terraform apply -json` also produces locally. Record it, analyse it in HCL , two `change_summary` messages, only one of which says what happened , and establish what each of the three workflows allows.

    dsoxlab start hcp-terraform-remote-runs

    35m advanced shell Companion guide (French)

  • Fifteen precedence levels, and one inversion

    Among priority variable sets the broadest scope wins, whereas among normal sets it is the narrowest. Build the complete fifteen-level table, then resolve cases the tests generate and that no case-by-case answer can handle.

    dsoxlab start hcp-terraform-variable-sets

    30m advanced shell Companion guide (French)

  • Credentials: neither in the code, nor in the state

    `sensitive` hides a value from the screen, and the state holds it in clear text all the same. Take the provider's keys out of the configuration, replace a token carried in a tag with its fingerprint, and establish how dynamic credentials work.

    dsoxlab start hcp-terraform-shared-credentials

    35m advanced shell Companion guide (French)

  • Permissions add up, they do not override

    A permission set at the organization level can beat one set on the workspace, and the reverse is also true: the most permissive wins, never the most specific. Write the rule that computes six teams' effective access, and establish two scales that are not the same.

    dsoxlab start hcp-terraform-projects-teams

    30m advanced shell Companion guide (French)

  • Policy as code: what blocks a run, and who can override it

    A `hard-mandatory` is not unbypassable: the policy set setting decides, crossed with the user's permission. Qualify seven runs, establish the levels of the three frameworks, and write a rule that refuses a non-compliant plan and accepts the compliant one.

    dsoxlab start hcp-terraform-policy-as-code

    30m advanced shell Companion guide (French)

  • The first remote run, for real (optional, needs an account)

    The only lab in the catalog that needs an HCP Terraform account. Provision the platform with the `tfe` provider , project, workspace, settings, a sensitive variable , attach a configuration with a `cloud` block, and watch a run execute on HashiCorp's infrastructure.

    dsoxlab start hcp-terraform-premier-run-distant

    45m advanced shell Companion guide (French)

Professional certification

  • Pro · Objective 1: resource lifecycle, import and drift reconciliation

    Import into state an EC2 instance created outside Terraform (aws cli on Floci), then detect and reconcile a drift. Exam objective 1.

    dsoxlab start certifications-professional-capstone1-resource-lifecycle

    4h advanced shell Companion guide (French)

  • Pro · Objective 2: dynamic configuration and troubleshooting

    Data sources, HCL functions, meta-arguments (count/for_each/dynamic), complex types, sensitive data and Vault. Exam objective 2.

    dsoxlab start certifications-professional-capstone2-dynamic-config

    4h advanced shell Companion guide (French)

  • Pro · Objective 3: collaborative workflows

    Remote state (S3 backend on Floci), version constraints, workflow in automation and data sharing via terraform_remote_state. Exam objective 3.

    dsoxlab start certifications-professional-capstone3-collaborative-workflows

    4h advanced shell Companion guide (French)

  • Pro · Objective 4: create, maintain and use modules

    Create a module, consume it, refactor and version it; refactor a flat configuration into modules. Exam objective 4.

    dsoxlab start certifications-professional-capstone4-modules

    4h advanced shell Companion guide (French)

  • Pro · Objective 5: configure and use providers

    Plugin architecture, aliasing, versioning/sourcing/upgrades, authentication and provider error troubleshooting (on Floci). Exam objective 5.

    dsoxlab start certifications-professional-capstone5-providers

    4h advanced shell Companion guide (French)

  • Pro · Objective 6: HCP Terraform, where the sub-objectives cross

    Objective 6 is assessed by multiple choice, and needs no account. Six situations that each cross two sub-objectives, a `cloud` block to write, and a secret that must not reach the state. Six situations, six different outcomes: no constant answer passes.

    dsoxlab start certifications-professional-capstone6-hcp

    45m advanced shell Companion guide (French)

  • Pro · Integrative mock exam: the six objectives in one sitting

    A rehearsal, not a lesson: six tasks, one per objective, to be played in one go once the six capstones are done. Drift reconciliation, dynamic configuration, two states that talk, a module that recreates nothing, two configurations of one provider, and a twelve-question HCP paper scored per sub-objective.

    dsoxlab start certifications-professional-mock-pro

    4h advanced shell Companion guide (French)

Back to all 352 labs How to run a lab