{"id":23418550,"url":"https://github.com/rustshop/npcnix","last_synced_at":"2025-04-12T11:33:32.992Z","repository":{"id":155442927,"uuid":"626797798","full_name":"rustshop/npcnix","owner":"rustshop","description":"Control your NixOS instances system configuration from a centrally managed location","archived":false,"fork":false,"pushed_at":"2024-04-26T15:39:04.000Z","size":148,"stargazers_count":49,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T17:11:18.065Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rustshop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2023-04-12T07:21:11.000Z","updated_at":"2025-03-18T21:49:02.000Z","dependencies_parsed_at":"2023-12-01T00:27:21.873Z","dependency_job_id":"8c358c73-69c1-4edc-8eca-49dcb6a476db","html_url":"https://github.com/rustshop/npcnix","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustshop%2Fnpcnix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustshop%2Fnpcnix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustshop%2Fnpcnix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustshop%2Fnpcnix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustshop","download_url":"https://codeload.github.com/rustshop/npcnix/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248560349,"owners_count":21124635,"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","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":[],"created_at":"2024-12-23T00:20:18.351Z","updated_at":"2025-04-12T11:33:32.962Z","avatar_url":"https://github.com/rustshop.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NPCNIX\n\n\u003e Control your NixOS instances system configuration from a centrally managed location.\n\n## Overview\n\nIf you are already using NixOS flakes to configure your NixOS\nsystems, why bother using ssh to change their configurations,\nif you could just ... let them configure themselves automatically,\non their own.\n\nThe plan is as follows:\n\nFirst, prepare a location that can store and serve files\n(an npcnix *store*) - e.g. an S3 bucket (or a prefix inside it).\n\nWithin it, publish compressed flakes under certain addresses (an npcnix *remote*s) - e.g. a keys in a S3 bucket.\n\nConfigure your NixOS hosts/images to run an initialization script\nat the first boot that will download a flake from a given *remote*\nand switch to a given NixOS *configuration* inside it, or use\na pre-built system image that includes `npcnix` support.\n\nEach NixOS *configuration* should enable a `npcnix` system daemon,\nthat will periodically check (and reconfigure if needed) the system\nfollowing updates published in the *remote*.\n\nNot exactly a Kubernetes cluster but with a somewhat similar\napproach of agentes reacting to updates published in a central\nlocation. Yet simpler, easy to set up, understand and customize,\nand can go a long way to help manage a small to medium size herd\nof NixOS-based machines.\n\nIt integrates well with existing infrastructure, CI systems and\ntooling, especially in cloud environments.\n\nIn combination with internal remote builders and Nix caching\nservers (or corresponding services like cachix) it can work very\neffectively.\n\nSince the npcnix-managed systems \"pull\" their configuration,\nsecurity posture of the whole system can be improved (in comparison\nto an ssh-based approach), as active remote access is not even necessary,\nand permission system can be centralized around the *store* write privileges.\n\n\n## Setting up in AWS using Terraform\n\nMy use case involves AWS as a cloud, S3 as a cheap, yet abundant *store*,\nwith a built-in and integrated (in AWS) permission system, and Terraform\nintegration for convenience.\n\nThe guide will assume you're familiar with the products and tools\nused.\n\nIt shouldn't be difficult with a bit of cloud/system administration\nskills to implement `npcnix` in any other environment.\n\nAll the terraform modules used here are in the `./terraform` directory. You should\nprobably pin them, or even just use as a reference.\n\nSo first, we need a bucket to store the config:\n\n```terraform\nresource \"aws_s3_bucket\" \"config\" {\n  bucket = \"some-config\"\n}\n\nresource \"aws_s3_bucket_public_access_block\" \"config\" {\n  bucket = aws_s3_bucket.config.id\n\n  block_public_acls   = true\n  block_public_policy = true\n  ignore_public_acls  = true\n}\n```\n\nAnd then let's carve out a part of it for *remotes* (compressed Nix flakes):\n\n```terraform\nmodule \"npcnix_s3_store\" {\n  source = \"github.com/rustshop/npcnix//terraform/store_s3?ref=a1dd4621a56724fe36ca8940eb7172dd0f4be986\"\n\n  bucket = aws_s3_bucket.config\n  prefix = \"npcnix/remotes\"\n}\n```\n\nWe're going to need a boot script:\n\n```terraform\nmodule \"npcnix_install\" {\n  source = \"github.com/rustshop/npcnix//terraform/install?ref=a1dd4621a56724fe36ca8940eb7172dd0f4be986\"\n}\n```\n\nFinally, a remote along with the command that will pack and upload to it:\n\n```terraform\nmodule \"remote_dev\" {\n  source   = \"github.com/rustshop/npcnix//terraform/remote_s3?ref=a1dd4621a56724fe36ca8940eb7172dd0f4be986\"\n\n  name  = \"dev\"\n  store = var.npcnix_s3_store\n}\n\nmodule \"remote_dev_upload\" {\n  source   = \"github.com/rustshop/npcnix//terraform/remote_s3_upload?ref=a1dd4621a56724fe36ca8940eb7172dd0f4be986\"\n\n  remote    = module.remote_dev\n  flake_dir = \"../../configurations\"\n  include   = []\n}\n```\n\nAnd a EC2 instance that will bootstrap itself using the installation script,\nhave some alternative root ssh access (for debugging any issues) and\nthen configure itself to use `\"host\"` NixOS configuration from flake\nin `../../configurations`.\n\n```terraform\nmodule \"host\" {\n  source = \"github.com/rustshop/npcnix//terraform/instance?ref=a1dd4621a56724fe36ca8940eb7172dd0f4be986\"\n\n  providers = {\n    aws = aws\n  }\n\n  remote        = module.remote_dev\n  install       = module.npcnix_install\n  root_access   = true\n  root_ssh_keys = local.fallback_ssh_keys\n\n  hostname      = \"host\"\n  subnet        = module.vpc-us-east-1.subnets[\"public-a\"]\n  dns_zone      = aws_route53_zone.dev\n  ami           = local.ami.nixos_22_11.us-east-1\n  instance_type = \"t3.nano\"\n\n  pre_install_script = local.user_data_network_init\n\n  public_tcp_ports = [22]\n}\n```\n\nAnd that's basically it for Terraform configuration required.\n\nOn `terraform apply`, local `npcnix pack` will pack the Nix flake from `../../configurations`, and upload it to a remote. On start the system daemon will execute script prepared by `npcnix_install` that will configure `npcnix` on the machine, download the packed flake, and switch the configuration. As long as that configuration has a npcnix NixOS module enabled, a system daemon will keep monitoring the remote and switching to the desired configuration. \n\nWith just one command, you can start one or more machines that will automatically provision themselves with the desired configuration.\n\n## FAQ\n\n### What about destination machines having to build each configuration?\n\nUse a build cache and/or remote builder machine. Both the installation script module and the npcnix itself can use it. You can populate it from your local machine or CI of some kind.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustshop%2Fnpcnix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustshop%2Fnpcnix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustshop%2Fnpcnix/lists"}