Files
nixos-servers/terraform/vault/README.md

4.5 KiB

OpenBao Terraform Configuration

This directory contains Terraform/OpenTofu configuration for managing OpenBao (Vault) infrastructure as code.

Overview

Manages the following OpenBao resources:

  • AppRole Authentication: For host-based authentication
  • PKI Infrastructure: Root CA + Intermediate CA for TLS certificates
  • KV Secrets Engine: Key-value secret storage (v2)
  • Policies: Access control policies

Setup

  1. Copy the example tfvars file:

    cp terraform.tfvars.example terraform.tfvars
    
  2. Edit terraform.tfvars with your OpenBao credentials:

    vault_address         = "https://vault.home.2rjus.net:8200"
    vault_token           = "hvs.your-root-token-here"
    vault_skip_tls_verify = true
    
  3. Initialize Terraform:

    tofu init
    
  4. Review the plan:

    tofu plan
    
  5. Apply the configuration:

    tofu apply
    

Files

  • main.tf - Provider configuration
  • variables.tf - Variable definitions
  • approle.tf - AppRole authentication backend and roles
  • pki.tf - PKI engines (root CA and intermediate CA)
  • secrets.tf - KV secrets engine and test secrets
  • terraform.tfvars - Credentials (gitignored)
  • terraform.tfvars.example - Example configuration

Resources Created

AppRole Authentication

  • AppRole backend at approle/
  • Host-based roles and policies (defined in locals.host_policies)

PKI Infrastructure

  • Root CA at pki/ (10 year TTL)
  • Intermediate CA at pki_int/ (5 year TTL)
  • Role homelab for issuing certificates to *.home.2rjus.net
  • Certificate max TTL: 30 days

Secrets

  • KV v2 engine at secret/
  • Secrets and policies defined in locals.secrets and locals.host_policies

Usage Examples

Adding a New Host

  1. Define the host policy in approle.tf:
locals {
  host_policies = {
    "monitoring01" = {
      paths = [
        "secret/data/hosts/monitoring01/*",
        "secret/data/services/prometheus/*",
      ]
    }
  }
}
  1. Add secrets in secrets.tf:
locals {
  secrets = {
    "hosts/monitoring01/grafana-admin" = {
      auto_generate   = true
      password_length = 32
    }
  }
}
  1. Apply changes:
tofu apply
  1. Get AppRole credentials:
# Get role_id
bao read auth/approle/role/monitoring01/role-id

# Generate secret_id
bao write -f auth/approle/role/monitoring01/secret-id

Issue a certificate from PKI

# Issue certificate for a host
bao write pki_int/issue/homelab \
  common_name="test.home.2rjus.net" \
  ttl="720h"

Read a secret

# Authenticate with AppRole first
bao write auth/approle/login \
  role_id="..." \
  secret_id="..."

# Read the test secret
bao kv get secret/test/example

Managing Secrets

Secrets are defined in the locals.secrets block in secrets.tf using a declarative pattern:

Most secrets can be auto-generated using the random_password provider:

locals {
  secrets = {
    "hosts/monitoring01/grafana-admin" = {
      auto_generate   = true
      password_length = 32
    }
  }
}

Manual Secrets

For secrets that must have specific values (external services, etc.):

# In variables.tf
variable "smtp_password" {
  type      = string
  sensitive = true
}

# In secrets.tf locals block
locals {
  secrets = {
    "shared/smtp/credentials" = {
      auto_generate = false
      data = {
        username = "notifications@2rjus.net"
        password = var.smtp_password
        server   = "smtp.gmail.com"
      }
    }
  }
}

# In terraform.tfvars
smtp_password = "super-secret-password"

Path Structure

Secrets follow a three-tier hierarchy:

  • hosts/{hostname}/* - Host-specific secrets
  • services/{service}/* - Service-wide secrets (any host running the service)
  • shared/{category}/* - Shared secrets (SMTP, backup, etc.)

Security Notes

  • terraform.tfvars is gitignored to prevent credential leakage
  • Root token should be stored securely (consider using a limited admin token instead)
  • skip_tls_verify = true is acceptable for self-signed certs in homelab
  • AppRole secret_ids can be scoped to specific CIDR ranges for additional security

Next Steps

  1. Add more AppRoles for different host types
  2. Create policies for different service tiers
  3. Migrate existing sops-nix secrets to OpenBao KV
  4. Enable ACME support on PKI intermediate CA (OpenBao 2.0+)
  5. Set up SSH CA for host and user certificates