HashiCorp Vault — Consul & Nomad

1 minute read

Vault integrates deeply with Consul (service mesh) and Nomad (workload orchestrator) to provide a complete infrastructure platform.


Vault + Consul

Consul as Vault Storage Backend

# vault.hcl
storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault/"
  token   = "consul-acl-token"
}

Consul Connect (Service Mesh) + Vault CA

Vault can serve as the Certificate Authority for Consul’s service mesh:

# Configure Consul to use Vault as CA provider
# consul.hcl
connect {
  ca_provider = "vault"
  ca_config {
    address               = "https://vault.example.com:8200"
    token                 = "vault-consul-token"
    root_pki_path         = "pki-connect-root"
    intermediate_pki_path = "pki-connect-intermediate"
  }
}

Consul Secrets Engine

Generate Consul ACL tokens dynamically:

# Enable Consul secrets engine in Vault
vault secrets enable consul

# Configure connection
vault write consul/config/access \
    address="127.0.0.1:8500" \
    token="consul-management-token"

# Create a role
vault write consul/roles/readonly \
    policies='key-read,service-read'

# Generate a dynamic Consul token
vault read consul/creds/readonly
# Returns: token (auto-revoked after TTL)

Vault + Nomad

Nomad Secrets Engine

Generate Nomad ACL tokens dynamically:

# Enable Nomad secrets engine in Vault
vault secrets enable nomad

# Configure
vault write nomad/config/access \
    address="http://127.0.0.1:4646" \
    token="nomad-management-token"

# Create a role
vault write nomad/role/deploy \
    type=client \
    policies="submit-job,read-job"

# Generate a dynamic Nomad token
vault read nomad/creds/deploy

Nomad Vault Integration

Nomad jobs can request Vault secrets:

# Nomad job spec
job "webapp" {
  group "app" {
    vault {
      policies = ["webapp"]
    }

    task "server" {
      driver = "docker"

      config {
        image = "myapp:latest"
      }

      # Vault template — secrets injected into the task
      template {
        data = <<-EOT
          DB_USER={{ with secret "database/creds/webapp" }}{{ .Data.username }}{{ end }}
          DB_PASS={{ with secret "database/creds/webapp" }}{{ .Data.password }}{{ end }}
        EOT
        destination = "secrets/db.env"
        env         = true
      }
    }
  }
}

The HashiCorp Stack

┌────────────────────────────────────────────┐
│              Applications                   │
├─────────┬──────────┬──────────┬────────────┤
│  Vault  │ Consul   │  Nomad   │  Boundary  │
│ Secrets │ Service  │ Workload │  Access    │
│ Mgmt    │ Mesh     │ Orch     │  Mgmt      │
├─────────┴──────────┴──────────┴────────────┤
│          Terraform (Infrastructure)         │
├────────────────────────────────────────────┤
│          Packer (Machine Images)            │
└────────────────────────────────────────────┘
Tool Purpose
Terraform Provision infrastructure
Packer Build machine images
Vault Manage secrets and encryption
Consul Service discovery and mesh
Nomad Orchestrate workloads
Boundary Secure remote access
Waypoint Application deployment

Learn More

Tool URL
Consul developer.hashicorp.com/consul
Nomad developer.hashicorp.com/nomad
Terraform developer.hashicorp.com/terraform

Next: Community Resources