Files
nixos-servers/terraform/vault
Torjus Håkestad b2b6ab4799 garage01: add Garage S3 service with Caddy HTTPS proxy
Configure Garage object storage on garage01 with S3 API, Vault secrets
for RPC secret and admin token, and Caddy reverse proxy for HTTPS access
at s3.home.2rjus.net via internal ACME CA. Includes flake entry, VM
definition, and Vault policy for the host.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 21:24:25 +01:00
..
2026-02-03 06:53:59 +01:00

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://vault01.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 Certificates from PKI

Method 1: ACME (Recommended for automated services)

First, enable ACME support:

bao write pki_int/config/acme enabled=true

ACME directory endpoint:

https://vault01.home.2rjus.net:8200/v1/pki_int/acme/directory

Use with ACME clients (lego, certbot, cert-manager, etc.):

# Example with lego
lego --email admin@home.2rjus.net \
  --dns manual \
  --server https://vault01.home.2rjus.net:8200/v1/pki_int/acme/directory \
  --accept-tos \
  run -d test.home.2rjus.net

Method 2: Static certificates via Terraform

Define in pki.tf:

locals {
  static_certificates = {
    "monitoring" = {
      common_name = "monitoring.home.2rjus.net"
      alt_names   = ["grafana.home.2rjus.net", "prometheus.home.2rjus.net"]
      ttl         = "720h"
    }
  }
}

Terraform will auto-issue and auto-renew these certificates.

Method 3: Manual CLI issuance

# 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

Initial Setup Steps

After deploying this configuration, perform these one-time setup tasks:

1. Enable ACME

export BAO_ADDR='https://vault01.home.2rjus.net:8200'
export BAO_TOKEN='your-root-token'
export BAO_SKIP_VERIFY=1

# Configure cluster path (required for ACME)
bao write pki_int/config/cluster path=https://vault01.home.2rjus.net:8200/v1/pki_int

# Enable ACME on intermediate CA
bao write pki_int/config/acme enabled=true

# Verify ACME is enabled
curl -k https://vault01.home.2rjus.net:8200/v1/pki_int/acme/directory

2. Download Root CA Certificate

For trusting the internal CA on clients:

# Download root CA certificate
bao read -field=certificate pki/cert/ca > homelab-root-ca.crt

# Install on NixOS hosts (add to system/default.nix or similar)
security.pki.certificateFiles = [ ./homelab-root-ca.crt ];

3. Test Certificate Issuance

# Manual test
bao write pki_int/issue/homelab common_name="test.home.2rjus.net" ttl="24h"

Next Steps

  1. Replace step-ca ACME endpoint with OpenBao in system/acme.nix
  2. Add more AppRoles for different host types
  3. Migrate existing sops-nix secrets to OpenBao KV
  4. Set up SSH CA for host and user certificates
  5. Configure auto-unseal for vault01