Skip to main content

Import a live UniFi / Ubiquiti UDM controller into OpenTofu (Terraform) — enumerate the controller and generate clean, appliable HCL for the ubiquiti-community/unifi provider. Plan-only, re-runnable.

Reason this release was yanked:

caused duplicated managed WireGuard peers on every run; fixed in 0.3.1

Project description

ubitofu mascot — a tofu block wearing a UniFi access point, holding an OpenTofu gear

ubitofu — import your UniFi / Ubiquiti UDM config into OpenTofu (Terraform)

ubitofu enumerates a live UniFi Network controller (UDM, UDM-Pro, Cloud Key, or self-hosted) and generates clean, directly-appliable OpenTofu/Terraform HCL for the ubiquiti-community/unifi provider — bringing existing networks, VLANs, WLANs, firewall rules, port profiles, port forwards, WireGuard VPN, clients and devices under infrastructure-as-code. Plan-only and re-runnable: run once to import an existing controller, and again to reconcile drift.

It never runs tofu apply and never writes to the controller. Every run reads from the controller and writes HCL to your working directory, so running it against production networks is safe.

Installation

pip install ubitofu

Requires Python 3.11 or later. Runtime dependencies (python-hcl2, httpx, deepdiff) install automatically.

Both entry points are equivalent:

ubitofu --help
python -m ubitofu --help

Importing an existing UniFi controller into Terraform/OpenTofu

Four subcommands take you from a live controller to appliable code:

$ ubitofu enumerate --config config.toml   # import blocks + coverage gaps
$ ubitofu generate  --config config.toml   # imports.tf + generated.tf + unifi-variables.tf
$ ubitofu reconcile --config config.toml   # merge drift into committed HCL in place
$ ubitofu verify    --config config.toml   # plan must be clean (or secrets-only)
  • enumerate walks the controller and prints import blocks plus a report of anything it cannot bring under management.
  • generate writes imports.tf, generated.tf, and unifi-variables.tf — a self-contained, appliable configuration for the ubiquiti-community/unifi provider.
  • reconcile edits your committed, hand-tuned .tf in place, preserving comments and layout: it updates drifted scalars and names each changed nested attribute precisely in the report; appends newly-adopted objects with their import blocks (and, for objects that carry a secret, the matching variable declaration plus a warning to set it); flags resources that would be destroyed on apply; and distinguishes objects deleted on the controller from those configured but not yet applied. Re-runs against an unchanged controller are a no-op and never produce a duplicate resource name. The printed report is the product; nothing is applied.
  • verify runs a plan and passes only when it is clean (or the only diffs are in schema-sensitive attributes whose values live in variables).

Configuration is TOML:

controller_url = "https://192.168.1.1"
site           = "default"
api_key_source = "op"                                # or "env"
api_key_ref    = "op://YourVault/unifi.api-key/credential"
op_vault       = "YourVault"
workdir        = "./work"

Supported UniFi resources

ubitofu imports the resources the ubiquiti-community/unifi provider can manage: networks and VLANs, WLANs, firewall rules and groups, port profiles, port forwards, WireGuard VPN servers and peers, clients (by MAC), and devices.

ubitofu detects and reports resources the provider cannot manage — NAT rules, DNS content-filtering, device adoption, RF/firmware settings — never silently dropping them, so you always know what remains outside code.

Secrets

Secret attributes (WLAN passphrases, dynamic-DNS passwords, …) are never emitted as plaintext. Each one known to the SECRETS table renders as a var.<name> reference, and generate writes a unifi-variables.tf declaring every referenced variable (type = string, sensitive = true) so the generated config is self-contained.

You supply variable values from your secret manager — e.g. TF_VAR_<name> environment variables or a git-ignored *.auto.tfvars. The tool prints a suggested secret-manager reference for each variable (rendered with your configured op_vault); these references are reporter output only — the tool never writes them to files.

ubitofu omits sensitive attributes without a SECRETS rule from the HCL and adds them to lifecycle { ignore_changes }. As a safety net, any emitted string value that still looks secret-shaped (a secret-bearing attribute name, or a 44-char base64 WireGuard-key shape) is suppressed the same way, with a loud warning naming the resource and attribute — add a SECRETS rule to manage it properly.

How it compares

Unlike general-purpose importers such as terraformer, ubitofu is purpose-built for the ubiquiti-community/unifi provider: it knows which attributes are settable, which are computed, and which are secrets, so the HCL it emits applies cleanly instead of fighting the provider schema. Compared with hand-rolled scripts (e.g. terrifi-style one-offs), it is re-runnable and drift-aware — re-run verify any time to confirm code and controller still agree.

Claude Code workflow skill

The repo ships a Claude Code skill at .claude/skills/unifi-tofu-reconcile-workflow/. Its rule: never hand-author UniFi HCL — draft with ubitofu and refine.

If you run Claude Code inside a clone of this repo, the skill is available automatically.

pip install ubitofu does not install the skill — PyPI packages do not carry Claude Code skills. Its best home is your own infrastructure repo: copy the unifi-tofu-reconcile-workflow directory into that repo's .claude/skills/ and commit it, so everyone who clones the repo gets it. To use it across every project instead, copy it into ~/.claude/skills/.

License

Licensed under GPL-3.0-or-later — see LICENSE.

Also relevant if you searched: unifi terraform import, udm as code, opentofu ubiquiti, ubiquiti-community/unifi provider import.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ubitofu-0.3.0.tar.gz (70.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ubitofu-0.3.0-py3-none-any.whl (48.0 kB view details)

Uploaded Python 3

File details

Details for the file ubitofu-0.3.0.tar.gz.

File metadata

  • Download URL: ubitofu-0.3.0.tar.gz
  • Upload date:
  • Size: 70.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ubitofu-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f1c06fbd844ccd80d8d4614d0ca823b33c62d7de4a416aad5b72558b37f68810
MD5 fb3af60c78b37604f3a94e5fd8994662
BLAKE2b-256 726a66275f38b21ba1c33baaafe4ff57d93268ea2b9dd4ee049adbe56e490459

See more details on using hashes here.

Provenance

The following attestation bundles were made for ubitofu-0.3.0.tar.gz:

Publisher: release.yml on jamesbraid/ubitofu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ubitofu-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: ubitofu-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 48.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ubitofu-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b26f6aee81b0a1c1da543573549e91b86fc24b446f56cc9cad6587e38bc2024d
MD5 e264212046b4e2b78335b72192b2c83b
BLAKE2b-256 8d06be7487415d0ba24334390baede5f0eede54a1757993de8c4a5a5ec3f123a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ubitofu-0.3.0-py3-none-any.whl:

Publisher: release.yml on jamesbraid/ubitofu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page