Sign inSign up

bencejob/terraform-state-http-backend

By bencejob

•Updated 4 months ago

A Fast, Minimal terraform state backend server. An easy centralised solution for homelabs

Image
Integration & delivery
Developer tools
0

4.6K

bencejob/terraform-state-http-backend repository overview

⁠Terraform State HTTP Backend

A small HTTP backend server for storing Terraform state.

This project implements the Terraform HTTP backend protocol with support for state reads, state updates, and state locking. It is intended for self-hosted environments, homelabs, and small teams that want a simple centralized state backend without running a larger storage platform.

Docker Hub: bencejob/terraform-state-http-backend⁠

⁠Features

  • Terraform HTTP backend compatible endpoints
  • State locking and unlocking
  • File-based storage by default
  • Optional SQLite storage
  • Optional HTTP Basic Auth
  • Small Docker image
  • Non-root container runtime user
  • Multi-architecture Docker release workflow
  • Automated Go tests in GitHub Actions

⁠Quick Start

Run the backend with Docker:

docker run --rm \
  --name terraform-state-http-backend \
  -p 8080:8080 \
  -v "${PWD}/storage:/storage" \
  bencejob/terraform-state-http-backend:latest

Create a Terraform backend configuration:

terraform {
  backend "http" {
    address        = "http://localhost:8080/example/default"
    update_method  = "POST"
    lock_address   = "http://localhost:8080/example/default"
    lock_method    = "PUT"
    unlock_address = "http://localhost:8080/example/default"
    unlock_method  = "DELETE"
  }
}

Initialize Terraform:

terraform init

Terraform HTTP backend documentation: HashiCorp HTTP backend⁠

⁠Backend Paths

The backend uses this URL pattern:

/:group/:key

Example:

http://localhost:8080/platform/network

With the file driver, this stores state at:

storage/platform-network.json

Lock data is stored separately:

storage/platform-network.lock

⁠Configuration

Configuration is provided with environment variables.

NameDefaultDescription
HTTP_PORT8080Port the HTTP server listens on.
DRIVERfileStorage driver. Supported values: file, sqlite.
BASIC_AUTH_USERNAMEunsetEnables HTTP Basic Auth when set with BASIC_AUTH_PASSWORD.
BASIC_AUTH_PASSWORDunsetEnables HTTP Basic Auth when set with BASIC_AUTH_USERNAME.

⁠Storage Drivers

⁠File Driver

The file driver is the default.

docker run --rm \
  -p 8080:8080 \
  -v "${PWD}/storage:/storage" \
  bencejob/terraform-state-http-backend:latest

State and lock files are written under /storage. Mount this directory to persistent storage when running in Docker.

⁠SQLite Driver

Set DRIVER=sqlite to use SQLite:

docker run --rm \
  -p 8080:8080 \
  -e DRIVER=sqlite \
  -v "${PWD}/storage:/storage" \
  bencejob/terraform-state-http-backend:latest

SQLite data is stored at:

/storage/database.db

⁠Basic Auth

Basic Auth is disabled by default. To enable it, set both username and password:

docker run --rm \
  -p 8080:8080 \
  -e BASIC_AUTH_USERNAME=terraform \
  -e BASIC_AUTH_PASSWORD=change-me \
  -v "${PWD}/storage:/storage" \
  bencejob/terraform-state-http-backend:latest

Terraform backend configuration with Basic Auth:

terraform {
  backend "http" {
    address        = "http://localhost:8080/example/default"
    update_method  = "POST"
    lock_address   = "http://localhost:8080/example/default"
    lock_method    = "PUT"
    unlock_address = "http://localhost:8080/example/default"
    unlock_method  = "DELETE"

    username = "terraform"
    password = "change-me"
  }
}

For production usage, prefer passing credentials through environment variables, CI secrets, or Terraform partial backend configuration rather than committing them to source control.

⁠HTTP API

MethodPathDescription
GET/:group/:keyRead Terraform state.
POST/:group/:keyWrite Terraform state.
PUT/:group/:keyAcquire a Terraform state lock.
DELETE/:group/:keyRelease a Terraform state lock.

Common responses:

StatusMeaning
200Request succeeded.
404State was not found.
409Unlock attempted with the wrong lock ID.
423State is already locked.
500Storage or server error.

⁠Local Development

Requirements:

  • Go 1.26.0
  • Docker, if building or testing the container image

Run locally:

go run main.go

Run tests:

go test ./...

Build the Docker image:

docker build -t bencejob/terraform-state-http-backend .

Run the locally built image:

docker run --rm \
  -p 8080:8080 \
  -v "${PWD}/storage:/storage" \
  bencejob/terraform-state-http-backend

⁠Docker Build

Build for the local platform:

docker build -t bencejob/terraform-state-http-backend .

Build for multiple platforms:

docker buildx create --use --name terraform-state-builder
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --tag bencejob/terraform-state-http-backend:latest \
  .

⁠CI and Releases

The repository includes GitHub Actions workflows for:

  • Running go test ./... on push and pull request
  • Building and publishing the Docker image to Docker Hub when a GitHub release is published

Docker publishing requires these repository secrets:

DOCKERHUB_USERNAME
DOCKERHUB_TOKEN

⁠Security Notes

Terraform state can contain secrets. Treat the backend storage directory, SQLite database, Docker volumes, logs, backups, and access credentials as sensitive.

Recommended practices:

  • Enable Basic Auth when exposing the service beyond local development.
  • Run behind HTTPS when accessed over a network.
  • Restrict network access to trusted clients.
  • Persist and back up /storage.
  • Use dedicated Docker Hub tokens for CI publishing.
  • Avoid committing backend credentials into Terraform files.

⁠License

This project is licensed under the MIT License. See LICENSE-MIT⁠.

Tag summary

Content type

Image

Digest

sha256:12665477e…

Size

4.2 MB

Last updated

4 months ago

docker pull bencejob/terraform-state-http-backend