Files
hhctl/README.md
T
2026-10-27 17:02:15 -06:00

4.8 KiB

hhctl

A command-line tool and a Terraform provider for Hammerhead. Both talk only to Hammerhead's public HTTP API with an API key, so they work against any server you can reach.

client/                          Go API client (the only thing that speaks HTTP)
cmd/hhctl/                       the CLI
cmd/terraform-provider-hammerhead/
internal/provider/               Terraform provider (terraform-plugin-framework)
internal/fakehh/                 in-memory fake of the API, for tests
examples/                        Terraform configuration and a shell script

Needs a Hammerhead with API-key support for server scope (branch feature/api-tokens-hhctl; see hammerhead/docs/api-automation.md for the audit of what the API could and could not do before).

Credentials

Key Made with Can
Organization key Hammerhead dashboard, or POST /api/orgs/{org}/apikeys sites, ports, domains and alert channels of its organization; list edges it may use
Server key POST /api/admin/apikeys as a signed-in server admin everything above in any organization, plus edges, server alert channels and creating organizations

The secret is shown once when the key is created. Keep it out of version control; pass it in the environment.

export HAMMERHEAD_URL=https://hammerhead.example.com
export HAMMERHEAD_TOKEN=hhk_...
export HAMMERHEAD_ORG=...        # optional with an organization key

CLI

go install git.veillax.com/Veillax/hhctl/cmd/hhctl@latest

hhctl orgs list
hhctl edges create --name fra --tunnel 203.0.113.5:51820      # server key; prints the edge's token
hhctl sites create --name home --tag lab                      # prints the agent's token
hhctl domains add  --name example.com --edge fra
hhctl ports  create --name web --proto https --edge fra --port 443 \
    --hostname app.example.com --target home:192.168.1.30:8080
hhctl ports  create -f port.json                              # any option, as JSON
hhctl ports  list
hhctl alerts channel-create --name ops --kind email --target ops@example.com
hhctl alerts channels
hhctl ports delete <id>

Edges and sites can be given by name or ID. -o json prints the API's JSON (and the secret created, once) instead of a table. Commands: orgs, edges, sites, ports, domains (list, create/add, delete) and alerts (list, channels, channel-create, channel-delete, channel-test; --server for server-level ones). See hhctl -h, and examples/bootstrap.sh.

Terraform provider

Resources: hammerhead_site, hammerhead_port, hammerhead_domain, hammerhead_edge, hammerhead_alert_channel. Data source: hammerhead_edge (by name).

terraform {
  required_providers {
    hammerhead = { source = "veillax/hammerhead" }
  }
}

provider "hammerhead" {} # url, token and org come from HAMMERHEAD_URL / _TOKEN / _ORG

resource "hammerhead_site" "home" {
  name = "home"
  tags = ["lab"]
}

resource "hammerhead_port" "web" {
  name     = "web"
  proto    = "https"
  edge_id  = data.hammerhead_edge.fra.id
  port     = 443
  hostname = "app.example.com"
  target {
    site_id = hammerhead_site.home.id
    host    = "192.168.1.30"
    port    = 8080
  }
}

A full example is in examples/main.tf. Notes:

  • hammerhead_site.token and hammerhead_edge.token are sensitive outputs: hand them to the Bamboo / Blacktip program.
  • Ports are replaced wholesale by the API. password and pin are sent only when they change, because changing them signs every visitor out. Hammerhead never returns them, so out-of-band changes show up only as a removed password.
  • The server does not return an alert channel's webhook URL or Sandbar key, so those are kept as configured and drift in them is not detected.
  • Domains cannot be edited in place; any change replaces them.
  • Deleting an edge or a site in Hammerhead also deletes the ports that depend on it; let Terraform order the destroy via references as in the example.
  • Import: terraform import hammerhead_site.home <id> (same for port, domain, edge); alert channels take <id> or server/<id>, and need target set in configuration after import.

For local use, build the provider and point Terraform at it with a dev_overrides block in ~/.terraformrc:

go build -o ~/go/bin/terraform-provider-hammerhead ./cmd/terraform-provider-hammerhead
provider_installation {
  dev_overrides { "veillax/hammerhead" = "/home/you/go/bin" }
  direct {}
}

Tests

go test ./...

The tests run against internal/fakehh, a small in-memory imitation of the API, and drive the provider's CRUD methods directly (no terraform binary needed). The fake was checked by hand against a real Hammerhead for the CLI flows; there are no automated acceptance tests (terraform-plugin-testing) yet.