Skip to content

Repository files navigation

Terraform Provider for Alta Labs

Manage Alta Labs routers (Route10 and family) with Terraform, through the Alta cloud, so the portal always shows what Terraform applied.

Status: pre-1.0. The resources below are implemented and tested against recorded fixtures, and changes have been applied to a live Route10 through the gated transaction. The schema is still moving: expect breaking changes between minor versions until 1.0.

Unofficial. This project is not affiliated with, endorsed by, or supported by Alta Labs. Alta publishes no API description, so this provider is built on an interface that was observed rather than documented, and Alta may change it without notice. What was observed, and how, is recorded in api/schema.json and re-checked by the test suite rather than trusted.

Design: docs/DESIGN.md. In short:

  • Port forwards, firewall rules, VLANs, routes, switch ports and DHCP reservations are written to the Alta cloud, which compiles and pushes the router's configuration.
  • Every apply is one gated, commit-confirmed transaction: the router's cloud agent is paused while changes are staged, a single push is released, and the router rolls itself back unless health probes pass and the provider confirms.
  • SSH to the router is used to gate, verify and roll back, and for the few device extensions the portal has no concept of.

Usage

terraform {
  required_providers {
    alta = {
      source = "twilightcoders/alta"
    }
  }
}

provider "alta" {
  # Named once here rather than on every resource. Both default to $ALTA_LABS_SITE_ID
  # and $ALTA_LABS_DEVICE_ID.
  site_id   = "…"
  device_id = "…"

  ssh = {
    host                 = "192.0.2.1"
    host_key_fingerprint = "SHA256:…" # ssh-keyscan <host> | ssh-keygen -lf -
  }
}

# A network is described once; what follows from it is derived rather than repeated.
resource "alta_vlan" "lab" {
  vlan_id   = 40
  name      = "Lab"
  router_ip = "198.18.40.1/24"
}

resource "alta_dhcp_reservation" "printer" {
  mac = "02:00:00:aa:bb:cc"
  ip  = cidrhost(alta_vlan.lab.subnet, 40)
}

resource "alta_switch_port" "uplink" {
  port         = 4
  tagged_vlans = [alta_vlan.lab.vlan_id]
}

# For the few behaviours the cloud has no concept of. Both touch the router only,
# never the cloud, so neither triggers a configuration push.
resource "alta_device_file" "post_cfg" {
  path    = "/cfg/post-cfg.sh"
  content = file("post-cfg.sh")
  mode    = "0755"
}

resource "alta_device_hook" "example" {
  name      = "example"
  interface = "wg0"
  script    = "…"
}

Credentials come from ALTA_LABS_EMAIL and ALTA_LABS_PASSWORD.

Resource What it owns
alta_vlan one network, and the subnet, bridge and interface name derived from it
alta_static_route one route
alta_port_forward one destination NAT rule
alta_firewall_rule one filter rule
alta_dhcp_reservation one client's fixed address
alta_switch_port the VLAN membership of one physical port
alta_router_config every section at once, for managing a router wholesale
alta_device_hook, alta_device_file the router's own scripts and files
alta_devices (data source) the hardware a site has adopted

Each resource owns its own object and leaves the rest of its collection alone, so Terraform and the portal can manage different things in one site. Import an existing object by its id — terraform import alta_vlan.lab 40 — and a plan straight after should show no changes. Full reference: docs/index.md.

The API description

Alta publishes no API schema, so api/schema.json records what was observed: endpoints extracted from the portal bundle named in its provenance, object shapes fitted from captured responses rather than asserted, how each collection behaves when written, and a compile mapping from cloud fields to what the router ends up running — including the places where Alta's own compiler silently drops a field.

It is evidence, not contract, so it is re-checked rather than trusted:

make schema            # refit object shapes from the captured fixtures
make portal-endpoints  # re-extract endpoints from the live portal bundle (read-only)
go test ./internal/apischema                       # fixtures still conform
TF_ACC=1 go test ./internal/apischema -run Live    # a real site and router still agree (read-only)

Drift in Alta's API then shows up as a failing test instead of a surprise at apply time.

The live checks use two observation points, because one is not enough: the cloud's own read-back cannot show whether a value it stores ever reaches a router. So the compile mapping is checked against the configuration the router is actually running, which also reports a recorded defect that has been fixed — a prompt to drop the workaround rather than carry it forever.

Requirements

Component Version
Alta Labs router Route10, firmware 1.5g or later
Terraform 1.14 or later
Go (development) pinned in go.mod; fetched automatically by the go command

Development

Everything runs through make. Run make help for the full list.

make build        # bin/terraform-provider-alta
make test         # unit tests
make lint         # golangci-lint (pinned in tools/go.mod)
make docs         # regenerate docs/ with tfplugindocs
make install      # install into the local Terraform plugin mirror
make dev-override # print a ~/.terraformrc dev_overrides block

Releasing

Releases are built and signed by CI on a v* tag; the signing key belongs to the organisation and covers every provider it publishes. See docs/RELEASING.md.

License

MIT

About

Terraform provider for Alta Labs routers, written through the Alta cloud so the portal always shows what Terraform applied

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages