Files
2026-10-27 17:02:15 -06:00

125 lines
4.8 KiB
Markdown

# hhctl
A command-line tool and a Terraform provider for [Hammerhead](../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.
```sh
export HAMMERHEAD_URL=https://hammerhead.example.com
export HAMMERHEAD_TOKEN=hhk_...
export HAMMERHEAD_ORG=... # optional with an organization key
```
## CLI
```sh
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).
```hcl
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`:
```sh
go build -o ~/go/bin/terraform-provider-hammerhead ./cmd/terraform-provider-hammerhead
```
```hcl
provider_installation {
dev_overrides { "veillax/hammerhead" = "/home/you/go/bin" }
direct {}
}
```
## Tests
```sh
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.