teriac server Overview

teriac server

Self-hosted pull request automation for Terraform, Terragrunt and OpenTofu: what happens on every push, how a change goes from plan to apply, and what you need to run it.

teriac server is pull request automation for Terraform, Terragrunt and OpenTofu that you host yourself, with Docker or Helm.

On every push it does three things:

  1. Finds the affected projects, with no config needed.
  2. Plans each one with the exact tool version it pins.
  3. Posts the plan as a new comment, showing the exact command to apply each project, plus a check run per project with an Apply button.

Every action goes through per-project permissions and required approvers taken from your Git platform's users and teams. Scheduled drift checks post to Slack, Teams, Discord, Google Chat or any webhook, and tag who last changed each resource.

The PR comment, Terraform commands, the apply report, and the dashboard with runs, date ranges, metrics, resource usage and unlocking.

The life of a pull request

 push to a PR
      │
      ▼
 GitHub webhook ──▶ teriac server  (/events/github)
                      │
                      ├─ repo on the allowlist?          no → ignored
                      ├─ find affected projects          modules, Terragrunt includes, teriac:watch
                      ├─ lock each project + workspace   another PR holds it → 🔒 noted in the comment
                      ├─ plan each one                   exact pinned version, saved plan file
                      ├─ policy checks                   audit or enforce
                      └─ comment + one check run per project, with an Apply button
      │
      ▼
 review, approvals
      │
      ▼
 "teriac apply -p live/prod/vpc"  or the Apply button
                      │
                      ├─ permission?   apply / apply_destroy for this project
                      ├─ approvals?    of the current commit, author's own never counts
                      ├─ requirements? mergeable, undiverged, two-person rule, policy
                      ├─ plan current? no newer commit, no dependency applied since
                      └─ apply the saved plan  ──▶ apply report, audit log
      │
      ▼
 merge or close ──▶ locks released, plans and checkouts deleted

Key ideas

Apply means the reviewed plan. teriac saves each plan on its own disk. An apply always runs that saved plan, so what runs is exactly what was reviewed. A newer push replaces it.

Locks per project. When a PR plans a project, it takes that project's lock (per workspace). Another PR that touches the same project is told who holds it, until the first PR is applied, unlocked or closed.

Rules live on the server. Permissions, approvals and policies are in repos.yaml on the server, so a pull request can't change its own rules. A repo's teriac.yaml can only make them stricter.

The record can't be edited. Check runs and the dashboard are the trusted record; teriac never reads its own comments back, and warns when someone edits them.

What you need

A GitHub App For webhooks, comments and check runs. GitHub.com or GitHub Enterprise Server
A place to run it Docker, or Kubernetes 1.27+ with the Helm chart
A volume For checkouts, saved plans, tool binaries, the provider cache and the SQLite database. 20 GiB is a good start
Cloud credentials Whatever your Terraform needs: env vars, workload identity (IRSA, GKE, Azure) or mounted files
A public URL For GitHub's webhooks. The dashboard can stay internal

No database server, queue or Redis: teriac keeps its state in SQLite on the volume and runs as one replica. Turn on backups to copy that database to S3, GCS or Azure on a schedule; a new, empty volume is restored from the newest one.

Next