TerraformCLI icon
Sleep icon
AnsibleCLI icon

Provision a GCP VM with Active Directory Join and DNS Registration

Provision GCP Linux VMs with Terraform, join them to an AD domain over SSH, and register DNS records on the Windows DC via Ansible WinRM with Kestra.

Categories
Infrastructure

A VM is not really provisioned until it is on the domain and resolvable by name. This blueprint chains the three toolchains that usually live in three different runbooks: Terraform creates the Google Cloud instance with a static internal IP and your SSH public key, an Ansible playbook over SSH installs realmd/sssd and joins the machine to Active Directory (including the /etc/hosts, DNS, and NTP prerequisites Kerberos demands), and a second Ansible playbook over WinRM registers the forward A and reverse PTR records on the Windows domain controller. The VM is tracked as a Kestra Asset for lifecycle governance.

How it works

  1. The createVM task (io.kestra.plugin.terraform.cli.TerraformCLI) applies an inlined main.tf with a GCS backend keyed by prefix={{ inputs.vmName }}, so each VM gets its own state and a teardown flow can reuse it. The external IP is exported to external_ip.txt, and an assets block registers the io.kestra.plugin.ee.assets.VM asset with full metadata.
  2. The waitForStartupBootConfig task (io.kestra.plugin.core.flow.Sleep, PT5M) lets the instance finish booting.
  3. The addVMtoAD task (io.kestra.plugin.ansible.cli.AnsibleCLI) targets the fresh external IP read from the Terraform output file. Its playbook pins the DC in /etc/hosts, waits for the DC's DNS port, installs realmd, sssd, and adcli, points systemd-resolved at the DC, syncs time with ntpdate (Kerberos tolerates less than 5 minutes of drift), then runs realm join with the admin password from secrets and enables home directory creation.
  4. The addDNSentry task connects to the DC over WinRM using connection details from the dcConfig KV record (published by the domain controller deployment flow) and calls Add-DnsServerResourceRecordA -CreatePtr to register both DNS records.

What you get

  • End-to-end provisioning: instance, domain membership, and DNS in one execution.
  • Per-VM Terraform state enabling symmetric, safe teardown later.
  • All the fiddly AD-join prerequisites (hosts file, DNS, NTP) encoded once, correctly.
  • Asset catalog tracking with complete VM metadata for downstream lifecycle flows.

Who it's for

  • Enterprises running Linux compute inside an Active Directory environment.
  • Platform teams tired of three-runbook provisioning handoffs between cloud, identity, and DNS owners.
  • Infrastructure engineers pairing this with AD controller deployment and teardown blueprints.

Why orchestrate this with Kestra

Terraform cannot join a machine to a domain; Ansible does not know the IP Terraform just allocated; the DNS registration needs credentials for a completely different host. Kestra threads it together: output files pass the external IP from Terraform into the Ansible inventory, the KV store supplies the DC's connection details across flows, secrets hold the SSH keys and domain password, and one execution log covers the entire provisioning story.

Prerequisites

  • A GCP project and service account able to create instances, plus a GCS state bucket.
  • A Windows domain controller with WinRM enabled and a dcConfig KV record (internalIPAddress, externalIPAddress, username, domainName, vmName) created by the companion AD controller blueprint.
  • Kestra Enterprise Edition for Assets tracking (remove the assets block to run on OSS).

Secrets

  • GCP_SERVICE_ACCOUNT_JSON: JSON key used by Terraform.
  • SSH_PUBLIC_KEY: public key injected into the VM metadata for root access.
  • SSH_PRIVATE_KEY: matching private key used by Ansible to reach the new VM.
  • AD_ADMIN_PASSWORD: domain administrator password used for realm join and the WinRM connection.

Quick start

  1. Add the secrets above to your Kestra namespace and replace the state bucket in backend.tf.
  2. Deploy the AD controller blueprint first so dcConfig exists in the KV store.
  3. Execute with your VM name, static IP, network, and project.
  4. Verify with realm list on the VM and nslookup <vmName>.<domain> against the DC.

How to extend

  • Front it with the approval-gate ordering blueprint for governed self-service.
  • Add a compliance scan flow triggered on SUCCESS via io.kestra.plugin.core.trigger.Flow.
  • Install baseline packages by extending the AD-join playbook.
  • Pair with the teardown blueprint that destroys the VM and removes its AD and DNS entries.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.