{"id":31045076,"url":"https://github.com/icetan/nixiform","last_synced_at":"2025-09-14T16:57:32.315Z","repository":{"id":141713832,"uuid":"206108216","full_name":"icetan/nixiform","owner":"icetan","description":"Deploys with Terraform + NixOS","archived":false,"fork":false,"pushed_at":"2025-04-01T16:26:07.000Z","size":161,"stargazers_count":20,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-01T17:43:47.154Z","etag":null,"topics":["devops","nix","nixops","nixos","terraform"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/icetan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-03T15:17:58.000Z","updated_at":"2025-02-14T18:47:49.000Z","dependencies_parsed_at":"2024-04-24T14:29:00.007Z","dependency_job_id":"157091a5-4efd-4188-a309-8d0c043c929e","html_url":"https://github.com/icetan/nixiform","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/icetan/nixiform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icetan%2Fnixiform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icetan%2Fnixiform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icetan%2Fnixiform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icetan%2Fnixiform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icetan","download_url":"https://codeload.github.com/icetan/nixiform/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icetan%2Fnixiform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275136751,"owners_count":25411709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devops","nix","nixops","nixos","terraform"],"created_at":"2025-09-14T16:57:30.964Z","updated_at":"2025-09-14T16:57:32.290Z","avatar_url":"https://github.com/icetan.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nixiform\n\nProvision infrastructure with Terraform and manage configuration with NixOS.\n\n## Installation\n\n```\nnix-env -i -f https://github.com/icetan/nixiform/tarball/master\n```\n\n## Motivation\n\nDeclarative style infrastructure provisioning is really nice! So is declarative\nconfiguration management.\n\nThis makes Terraform and NixOS a nice match, being able to define the result you\nwant in code and realizing it with one command (more or less :P).\n\n## Inspiration\n\nI've been using NixOps for my deployments for some time.\n\nBut infrastructure provisioning is hard and needs a big community effort\nto cover cloud provider API's. Therefore carving out the provisioning part\nof NixOps replacing it with Terraform gives access to the rich provider\nsupport of the Terraform community.\n\nThis leaves implementing a bridge between Terraform and managing NixOS\nconfigurations.\n\nThis is mostly what Nixiform does. It takes the output from Terraform (or any\nother source really) and installs NixOS on the nodes provisioned if needed and\nthen pushes each corresponding NixOS config defined in a `nixiform.nix` file.\n\n## Examples\n\nFirst we need to declare our infrastructure on which we will push our\nconfiguration to.\n\nWe do this using Terraform, although Nixiform despite it's name is agnostic to\nwho provisions the infrastructure. The only requirement is that Nixiform gets\ninformation about how to connect to the nodes it will push to.\n\n**main.tf**\n\n```terraform\nprovider \"hcloud\" {\n}\n```\n\nFirst off we need a SSH key pair for Nixiform to use when pushing it's config.\n\nNixiform does not manage SSH keys for you so you will need to generate and add\nit to your SSH agent manually before pushing.\n\n```terraform\nlocals {\n  ssh_key = file(\"${path.module}/ssh_key.pub\")\n}\n\nresource \"hcloud_ssh_key\" \"default\" {\n  name       = \"Nixiform SSH key\"\n  public_key = local.ssh_key\n}\n```\n\nProvision two Hetzner Cloud nodes with Ubuntu, because most providers don't\nsupport NixOS we select Ubuntu which can be replaced with NixOS automatically\nby Nixiform on first config push.\n\n```terraform\nresource \"hcloud_server\" \"ubuntu\" {\n  count = 2\n  name = format(\"server_%02d\", count.index + 1)\n  server_type = \"cx11\"\n  image = \"ubuntu-16.04\"\n  ssh_keys = [hcloud_ssh_key.default.id]\n}\n```\n\nIn order for Nixiform to know how to connect to the nodes provisioned by\nTerraform we have to give it some input.\n\nBy setting the output property `nixiform` in the Terraform config, Nixiform\nwill be able pick up the relevant data.\n\nThe value of `nixiform` can be a single node or a list of nodes with the keys\n`name`, `ip`, `ssh_key`, `provider`.\n\n- `name`: the node identifier to map against a NixOS config in `nixiform.nix`\n- `ip`: a node IP which can be connected to via SSH\n- `ssh_key`: the public SSH key for which will be allowed access\n- `provider` (optional): determines which configurator will be used to\n  generate a NixOS hardware config\n\n```terraform\noutput \"nixiform\" {\n  value = [for node in hcloud_server.ubuntu : {\n    name = node.name\n    ip = node.ipv4_address\n    ssh_key = local.ssh_key\n    provider = \"hcloud\"\n  }]\n}\n```\n\n**nixiform.nix**\n\nThis is the file which maps which NixOS configuration will be pushed to which\nprovisioned node. Analogous to NixOps' network file.\n\n```nix\nlet\n  webpage = content: pkgs.runCommand \"http-server-content\" {} ''\n    mkdir -p $out\n    cat \u003e $out/index.html \u003c\u003cEOF\n    \u003cpre\u003e\n    ${content}\n    \u003c/pre\u003e\n    EOF\n  '';\nin input: {\n```\n\nDefine a node, the attribute name corresponds to the value of\n`nixiform.*.name` in the terraform output.\n\nThe value is the nodes NixOS configuration, same as a NixOS module or what\nyou would have in your `configuration.nix`. Additional arguments passed is\n`input` and `node`.\n\nWhere `node` is data about the specific node from the Terraform output, in\nthis case the value of `nixiform.*` where `nixiform.*.name` is equal to\n`\"server\"`.\n\nAnd `input` is the value of the entire `nixiform` property from the\nTerraform output, i.e. data about all the provisioned nodes in the network.\n\n```nix\n  \"server_01\" = { config, input, node, ... }: {\n    networking.firewall.allowedTCPPorts = [ 80 443 ];\n    services.nginx = {\n      enable = true;\n      virtualHosts.localhost = {\n        locations.\"/\" = {\n          root = webpage \"${node.ip}\";\n        };\n      };\n    };\n  };\n\n  \"server_02\" = { config, pkgs, input, node, ... }: {\n    networking.firewall.allowedTCPPorts = [ 80 443 ];\n    services.nginx = {\n      enable = true;\n      virtualHosts.localhost = {\n        locations.\"/\" = {\n          root = webpage \"${node.ip}\";\n        };\n      };\n      environment.systemPackages = [ pkgs.htop ];\n    };\n  };\n}\n```\n\nNow that we have declared our infrastructure and configuration we can start to\nrealize them.\n\nWe start by provisioning our Hetzner Cloud nodes:\n\n```sh\nterraform init\nterraform apply\n```\n\nThen we will tell Nixiform to take any Terraform output from the current\ndirectory and connect to each node to get information about the hardware which\nwe will need in order to build the NixOS config.\n\n```sh\nnixiform init\n```\n\nBuilding the configs, this step is optional as it will be done automatically\nbefore each `push` but it can be helpful to check that the configuration is\ncorrect.\n\n```sh\nnixiform build\n```\n\nFinally we push each nodes configuration and if the node doesn't have NixOS yet\nit will be installed replacing whatever OS is currently on there. (**Note**:\nonly some Linux distributions are supported to push over, Ubuntu is the simplest\nchoice.)\n\n**Warning**: Any previously installed OS will be wiped.\n\n```sh\nnixiform push\n```\n\nMore examples in the [examples](./examples) directory.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficetan%2Fnixiform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficetan%2Fnixiform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficetan%2Fnixiform/lists"}